בניית רכיב הגדרות

סקירה כללית בסיסית על יצירת רכיב הגדרות של פסולים וקופסאות סימון.

בפוסט הזה אני רוצה לשתף איתכם חשיבה על פיתוח רכיב הגדרות בשביל האינטרנט, שהוא רספונסיבי, תומך בקלט מרובים של מכשירים ועובד בדפדפנים שונים. אפשר לנסות את ההדגמה.

דמו

אם אתם מעדיפים סרטון או רוצים לראות תצוגה מקדימה של ממשק המשתמש או חוויית המשתמש של מה שאנחנו מפתחים, תוכלו לצפות בהדרכה קצרה יותר ב-YouTube:

סקירה כללית

פירטתי את ההיבטים של הרכיב הזה בקטעים הבאים:

  1. פריסות
  2. צבע
  3. קלט של טווח בהתאמה אישית
  4. קלט מותאם אישית של תיבת סימון
  5. שיקולים בנושא נגישות
  6. JavaScript

פריסות

זוהי הדגמה הראשונה של אתגר GUI שמורכבת רק מ-CSS Grid! כאן מוצגת כל רשת עם הדגשה באמצעות כלי הפיתוח ל-Chrome לרשת:

קווי מתאר צבעוניים ושכבות-על עם מרווחים בין הפערים שעוזרים להציג את כל התיבות שמהן מורכב פריסת ההגדרות

רק לצורך פער

הפריסה הנפוצה ביותר:

foo {
  display: grid;
  gap: var(--something);
}

אני קורא לפריסה הזו 'רק לפער' כי היא משתמשת רק בתצוגת רשת כדי להוסיף פערים בין בלוקים.

יש חמישה פריסות שמשתמשות בשיטה הזו. אלה כל הפריסות:

פריסות רשת אנכיות מודגשות בקווי מתאר וממולאות ברווחים

ברכיב fieldset, שמכיל כל קבוצת קלט (.fieldset-item), נעשה שימוש ב-gap: 1px כדי ליצור את גבולות קו השיער בין אלמנטים. אין פתרון מסובך לשוליים!

מילוי פער
.grid {
  display: grid;
  gap: 1px;
  background: var(--bg-surface-1);

  & > .fieldset-item {
    background: var(--bg-surface-2);
  }
}
תרגיל גבול
.grid {
  display: grid;

  & > .fieldset-item {
    background: var(--bg-surface-2);

    &:not(:last-child) {
      border-bottom: 1px solid var(--bg-surface-1);
    }
  }
}

עיטוף טבעי של רשת

הפריסה המורכבת ביותר הייתה פריסת המאקרו – מערכת הפריסה הלוגית בין <main> ל-<form>.

מרכוז התוכן של העטיפה

גם Flexbox וגם grid מאפשרים align-items או align-content, וכאשר עובדים עם רכיבי גלישת טקסט, התאמות הפריסה של content יחלקו את המרחב בין הצאצאים כקבוצה.

main {
  display: grid;
  gap: var(--space-xl);
  place-content: center;
}

באלמנט הראשי נעשה שימוש ב-place-content: center קיצור דרך של יישור כדי שהצאצאים ימורכזים אנכית ואופקית גם בפריסות של עמודה אחת וגם בפריסות של שתי עמודות.

עיינו בסרטון שלמעלה כדי לראות איך ה'תוכן' נשאר במרכז, למרות שהתבצעה אריזה.

חזרה על התאמה אוטומטית ל-minmax

ב-<form> נעשה שימוש בפריסת רשת גמישה לכל קטע. הפריסה הזו עוברת מעמודה אחת לשתי עמודות בהתאם למרחב הזמין.

form {
  display: grid;
  gap: var(--space-xl) var(--space-xxl);
  grid-template-columns: repeat(auto-fit, minmax(min(10ch, 100%), 35ch));
  align-items: flex-start;
  max-width: 89vw;
}

הערך של row-gap (‎--space-xl) בתצוגת הרשת הזו שונה מהערך של column-gap (‎--space-xxl) כדי להוסיף את המגע המותאם אישית לפריסת האתר הרספונסיבית. כשהעמודות מקובצות, אנחנו רוצים פער גדול, אבל לא גדול כמו במסך רחב.

בנכס grid-template-columns נעשה שימוש ב-3 פונקציות CSS: repeat(),‏ minmax() ו-min(). Una Kravets כתבה פוסט מעולה בבלוג בנושא פריסה, והיא מכנה אותו RAM.

יש 3 תוספות מיוחדות בפריסה שלנו, בהשוואה לפריסה של Una:

  • אנחנו מעבירים פונקציית min() נוספת.
  • מציינים את הערך align-items: flex-start.
  • יש סגנון max-width: 89vw.

פונקציית min() הנוספת מתוארת בצורה טובה על ידי Evan Minto בבלוג שלו, במאמר Intrinsically Responsive CSS Grid with minmax() and min(). מומלץ לקרוא אותו. תיקון ההתאמה flex-start נועד להסיר את אפקט מתיחת ברירת המחדל, כך שלרכיבי הצאצאים של הפריסה הזו לא צריכות להיות גובהים זהים, אלא גובהים טבעיים ואינטראלים. בסרטון ב-YouTube יש פירוט קצר של התכונה הזו.

הערך של max-width: 89vw הוא פירוט קטן בפוסט הזה. אראה לך את הפריסה עם הסגנון שהוחל עליה וגם בלי הסגנון:

מה קורה? כשמציינים את max-width, הוא מספק הקשר, גודל מפורש או גודל מוגדר לאלגוריתם הפריסה של auto-fit כדי שהוא יוכל לדעת כמה חזרות הוא יכול להציב במרחב. נראה ברור שהמרחב הוא 'רוחב מלא', אבל לפי מפרט התצוגה של CSS, צריך לציין גודל מוגדר או גודל מקסימלי. ציננתי את הגודל המקסימלי.

אז למה 89vw? כי "זה עבד" בפריסה שלי. אני וכמה אנשים נוספים ב-Chrome בודקים למה ערך סביר יותר, כמו 100vw, לא מספיק, ואם מדובר בבאג.

ריווח

רוב ההרמוניה של הפריסה הזו נובעת מלוח צבעים מוגבל של רווחים, 7 בדיוק.

:root {
  --space-xxs: .25rem;
  --space-xs:  .5rem;
  --space-sm:  1rem;
  --space-md:  1.5rem;
  --space-lg:  2rem;
  --space-xl:  3rem;
  --space-xxl: 6rem;
}

השימוש בתהליכים האלה מתאים מאוד לרשת, ל-CSS @nest ולתחביר ברמה 5 של @media. דוגמה: קבוצת הסגנונות המלאה של הפריסה <main>.

main {
  display: grid;
  gap: var(--space-xl);
  place-content: center;
  padding: var(--space-sm);

  @media (width >= 540px) {
    & {
      padding: var(--space-lg);
    }
  }

  @media (width >= 800px) {
    & {
      padding: var(--space-xl);
    }
  }
}

רשת עם תוכן במרכז, עם שוליים בינוניים כברירת מחדל (כמו בנייד). אבל ככל ששטח שדה התצוגה יגדל, הוא יתפרס על ידי הגדלת הרווח. CSS מ-2021 נראה די טוב!

זכורה לך הפריסה הקודמת, "Just for gam"? לפניכם גרסה מלאה יותר של האופן שבו הם נראים ברכיב הזה:

header {
  display: grid;
  gap: var(--space-xxs);
}

section {
  display: grid;
  gap: var(--space-md);
}

צבע

השימוש המבוקר בצבעים עזר לעיצוב הזה לבלוט כעיצוב דרשני אך מינימלי. אני עושה את זה כך:

:root {
  --surface1: lch(10 0 0);
  --surface2: lch(15 0 0);
  --surface3: lch(20 0 0);
  --surface4: lch(25 0 0);

  --text1: lch(95 0 0);
  --text2: lch(75 0 0);
}

אני נותן שמות לצבעים של המשטח והטקסט באמצעות מספרים, במקום שמות כמו surface-dark ו-surface-darker, כי בשאילתת מדיה אצטרך להפוך אותם, והצבעים בהיר וחושך לא יהיו משמעותיים.

אני הופך אותם בשאילתת מדיה של העדפה באופן הבא:

:root {
  ...

  @media (prefers-color-scheme: light) {
    & {
      --surface1: lch(90 0 0);
      --surface2: lch(100 0 0);
      --surface3: lch(98 0 0);
      --surface4: lch(85 0 0);

      --text1: lch(20 0 0);
      --text2: lch(40 0 0);
    }
  }
}

לפני שנצלול לפרטים של תחביר הצבעים, חשוב לקבל הצצה מהירה לתמונה הכוללת ולאסטרטגיה. אבל מאחר שהקדמתי את עצמי, אשמח לחזור קצת אחורה.

LCH?

בלי להיכנס לעומק לתיאוריית הצבע, LCH הוא תחביר שמותאם לאדם, שמתאים לאופן שבו אנחנו תופסים את הצבע, ולא לאופן שבו אנחנו מודדים את הצבע במתמטיקה (כמו 255). לכן, יש לו יתרון משמעותי: קל יותר לאנשים לכתוב אותו, ואנשים אחרים יוכלו להבין את השינויים האלה.

צילום מסך של דף האינטרנט pod.link/csspodcast, שבו מוצג הפרק Color 2: Perception
בפודקאסט של CSS תוכלו לקבל מידע נוסף על צבעים תפיסתיים (ועוד!)

היום, בדגמה הזו, נתמקד בתחביר ובערכים שאני מחליף כדי ליצור צבעים בהירים וחשוכים. נבחן משטח אחד וצבע טקסט אחד:

:root {
  --surface1: lch(10 0 0);
  --text1:    lch(95 0 0);

  @media (prefers-color-scheme: light) {
    & {
      --surface1: lch(90 0 0);
      --text1:    lch(40 0 0);
    }
  }
}

הערך --surface1: lch(10 0 0) מתורגם ל-10% בהירות, 0 צפיפות צבעים ו-0 גוון: אפור כהה מאוד ללא צבע. לאחר מכן, בשאילתת המדיה למצב בהיר, ערך הבהירות הופך ל-90% באמצעות --surface1: lch(90 0 0);. זהו תמצית האסטרטגיה. בתור התחלה, פשוט משנים את הבהירות בין שני הנושאים, ושומרים על יחסי הניגודיות שנדרשים לעיצוב או מה ששומר על הנגישות.

היתרון של lch() הוא שהקלילות היא תכונה אנושית, ואנחנו יכולים להיות בטוחים ש% שינוי בה יהיה % שונה באופן תפישתי ועקבי. למשל, hsl() לא מהימן.

מידע נוסף על מרחבי צבעים ועל lch() בקרוב!

נכון לעכשיו, אין ל-CSS גישה לצבעים האלה בכלל. חשוב לי לחזור על זה: אין לנו גישה לשליש מהצבעים ברוב המסכים המודרניים. ואלה לא סתם צבעים, אלא הצבעים הססגוניים ביותר שהמסך יכול להציג. האתרים שלנו דהויים כי חומרת המסכים התפתחה מהר יותר מהמפרטים של CSS וההטמעות בדפדפנים.

Lea Verou

פקדי צורה מותאמים עם ערכת צבעים

בדפדפנים רבים יש אמצעי בקרה לשימוש בעיצוב כהה, כרגע ב-Safari וב-Chromium, אבל צריך לציין ב-CSS או ב-HTML שהעיצוב שלכם משתמש בהם.

הדוגמה שלמעלה ממחישה את ההשפעה של הנכס מחלונית הסגנונות של כלי הפיתוח. ההדגמה משתמשת בתג HTML, שלדעתי הוא בדרך כלל מיקום טוב יותר:

<meta name="color-scheme" content="dark light">

מידע נוסף זמין color-scheme במאמר הזה של Thomas Steiner. יש הרבה יותר יתרונות מאשר רק תיבת סימון כהה!

CSS accent-color

הייתה פעילות לאחרונה סביב accent-color ברכיבי טפסים. זהו סגנון CSS יחיד שיכול לשנות את צבע הטשטוש שמשמש ברכיב הקלט בדפדפנים. מידע נוסף זמין כאן ב-GitHub. צירפתי אותו לסגנונות שלי לרכיב הזה. מכיוון שהדפדפנים תומכים בכך, תיבות הסימון שלי יהיו תואמות יותר לעיצוב עם הצבעים הוורודים והסגולים הבולטים.

input[type="checkbox"] {
  accent-color: var(--brand);
}

צילום מסך של תיבות סימון ורודות ב-Chromium ב-Linux

הבלטת צבעים באמצעות שינויי צבע הדרגתיים קבועים והתמקדות בתוך התמונה

צבעים בולטים יותר כשמשתמשים בהם בנדיבות, ואחת מהדרכים שאני אוהב להשיג את זה היא באמצעות אינטראקציות צבעוניות בממשק המשתמש.

בסרטון שלמעלה יש הרבה שכבות של משוב ואינטראקציה בממשק המשתמש, שעוזרות להעניק אישיות לאינטראקציה באמצעות:

  • הדגשת ההקשר.
  • מתן משוב בממשק המשתמש לגבי מידת ההתקרבות של הערך לטווח.
  • שליחת משוב בממשק המשתמש על כך ששדה מסוים מקבל קלט.

כדי לספק משוב כשמתבצעת אינטראקציה עם רכיב, ב-CSS נעשה שימוש בפסאודו המחלקה :focus-within כדי לשנות את המראה של אלמנטים שונים. נבחן את .fieldset-item לעומק, כי זה ממש מעניין:

.fieldset-item {
  ...

  &:focus-within {
    background: var(--surface2);

    & svg {
      fill: white;
    }

    & picture {
      clip-path: circle(50%);
      background: var(--brand-bg-gradient) fixed;
    }
  }
}

כשאחד מהצאצאים של הרכיב הזה מקבל את האירוע focus-within:

  1. לרקע .fieldset-item מוקצה צבע משטח בעל ניגודיות גבוהה יותר.
  2. ה-svg המוטמע ממולא בלבן כדי לשפר את הניגודיות.
  3. ה-<picture> clip-path המוטמע מתרחב למעגל מלא והרקע מתמלא בפס ההדרגתי הקבוע הבהיר.

טווח מותאם אישית

הנה רכיב קלט ב-HTML, ואראה לכם איך התאמתי אישית את המראה שלו:

<input type="range">

יש 3 חלקים ברכיב הזה שעלינו להתאים אישית:

  1. רכיב טווח / מאגר
  2. טראק
  3. אגודל

סגנונות של רכיבי טווח

input[type="range"] {
  /* style setting variables */
  --track-height: .5ex;
  --track-fill: 0%;
  --thumb-size: 3ex;
  --thumb-offset: -1.25ex;
  --thumb-highlight-size: 0px;

  appearance: none;         /* clear styles, make way for mine */
  display: block;
  inline-size: 100%;        /* fill container */
  margin: 1ex 0;            /* ensure thumb isn't colliding with sibling content */
  background: transparent;  /* bg is in the track */
  outline-offset: 5px;      /* focus styles have space */
}

השורות הראשונות של CSS הן החלקים המותאמים אישית של הסגנונות, ואני מקווה שתיוג ברור שלהן יעזור לך. שאר הסגנונות הם בעיקר סגנונות איפוס, כדי לספק בסיס עקבי ליצירת החלקים המורכבים של הרכיב.

סגנונות של טראקים

input[type="range"]::-webkit-slider-runnable-track {
  appearance: none; /* clear styles, make way for mine */
  block-size: var(--track-height);
  border-radius: 5ex;
  background:
    /* hard stop gradient:
        - half transparent (where colorful fill we be)
        - half dark track fill
        - 1st background image is on top
    */
    linear-gradient(
      to right,
      transparent var(--track-fill),
      var(--surface1) 0%
    ),
    /* colorful fill effect, behind track surface fill */
    var(--brand-bg-gradient) fixed;
}

הטריק הוא 'לחשוף' את צבע המילוי העז. ניתן לעשות זאת באמצעות הדרגתיות של עצירה קשיחה מעליה. השיפוע שקוף עד לאחוז המילוי, ולאחר מכן משתמש בצבע פני השטח של המסלול שלא מולאו. מאחורי פני השטח הלא מלאים האלה, יש צבע ברוחב מלא, שמחכה לשקיפות כדי לחשוף אותו.

סגנון המילוי של הטראק

העיצוב שלי נדרש JavaScript כדי לשמור על סגנון המילוי. יש אסטרטגיות שמתבססות רק על CSS, אבל הן מחייבות שהתמונה הממוזערת תהיה באותו גובה כמו הטראק, ולא הצלחתי למצוא פתרון שתואם למגבלות האלה.

/* grab sliders on page */
const sliders = document.querySelectorAll('input[type="range"]')

/* take a slider element, return a percentage string for use in CSS */
const rangeToPercent = slider => {
  const max = slider.getAttribute('max') || 10;
  const percent = slider.value / max * 100;

  return `${parseInt(percent)}%`;
};

/* on page load, set the fill amount */
sliders.forEach(slider => {
  slider.style.setProperty('--track-fill', rangeToPercent(slider));

  /* when a slider changes, update the fill prop */
  slider.addEventListener('input', e => {
    e.target.style.setProperty('--track-fill', rangeToPercent(e.target));
  })
})

לדעתי, זה שדרוג חזותי נחמד. פס ההזזה פועל מצוין בלי JavaScript, לא חובה להשתמש ב---track-fill, פשוט לא יהיה לו סגנון מילוי אם הוא לא יופיע. אם JavaScript זמין, מאכלסים את המאפיין המותאם אישית תוך מעקב אחר השינויים של המשתמשים, ומסנכרנים את המאפיין המותאם אישית עם הערך.

כאן תוכלו לקרוא פוסט מעולה של Ana Tudor בנושא CSS-Tricks, שבו מוצגת פתרון ל-CSS בלבד למילוי טראקים. גם הרכיב range עורר בי השראה רבה.

סגנונות של תמונות ממוזערות

input[type="range"]::-webkit-slider-thumb {
  appearance: none; /* clear styles, make way for mine */
  cursor: ew-resize; /* cursor style to support drag direction */
  border: 3px solid var(--surface3);
  block-size: var(--thumb-size);
  inline-size: var(--thumb-size);
  margin-top: var(--thumb-offset);
  border-radius: 50%;
  background: var(--brand-bg-gradient) fixed;
}

רוב הסגנונות האלה נועדו ליצור עיגול יפה. שוב רואים את הגרדיאנט הקבוע של הרקע שמאחד את הצבעים הדינמיים של התמונות הממוזערות, הטראקים ואלמנטי ה-SVG המשויכים. הפרדתי את הסגנונות של האינטראקציה כדי לבודד את השיטה box-shadow שמשמשת להדגשה במעבר עכבר:

@custom-media --motionOK (prefers-reduced-motion: no-preference);

::-webkit-slider-thumb {
  

  /* shadow spread is initally 0 */
  box-shadow: 0 0 0 var(--thumb-highlight-size) var(--thumb-highlight-color);

  /* if motion is OK, transition the box-shadow change */
  @media (--motionOK) {
    & {
      transition: box-shadow .1s ease;
    }
  }

  /* on hover/active state of parent, increase size prop */
  @nest input[type="range"]:is(:hover,:active) & {
    --thumb-highlight-size: 10px;
  }
}

המטרה הייתה קלה לניהול והדגשה ויזואלית באמצעות אנימציה כדי לקבל משוב ממשתמשים. אם משתמשים בצל תיבה, אפשר להימנע מהפעלת הפריסה עם ההשפעה הזו. כדי לעשות את זה, יוצרים צללית שלא מטושטשת שמתאימה לצורה המעגלית של אלמנט האגודל. לאחר מכן, משנים את גודל ההתפשטות של התמונה במעבר מעל התמונה.

אם רק היה קל להדגיש תיבות סימון…

בוררים בדפדפנים שונים

גיליתי שצריך את הבוררים -webkit- ו--moz- כדי לשמור על עקביות בין הדפדפנים:

input[type="range"] {
  &::-webkit-slider-runnable-track {}
  &::-moz-range-track {}
  &::-webkit-slider-thumb {}
  &::-moz-range-thumb {}
}

תיבת סימון בהתאמה אישית

הנה רכיב קלט ב-HTML, ואראה לכם איך התאמתי אישית את המראה שלו:

<input type="checkbox">

יש 3 חלקים ברכיב הזה שעלינו להתאים אישית:

  1. רכיב תיבת סימון
  2. תוויות משויכות
  3. אפקט הדגשה

רכיב תיבת סימון

input[type="checkbox"] {
  inline-size: var(--space-sm);   /* increase width */
  block-size: var(--space-sm);    /* increase height */
  outline-offset: 5px;            /* focus style enhancement */
  accent-color: var(--brand);     /* tint the input */
  position: relative;             /* prepare for an absolute pseudo element */
  transform-style: preserve-3d;   /* create a 3d z-space stacking context */
  margin: 0;
  cursor: pointer;
}

הסגנונות transform-style ו-position מכינים את השטח לשימוש בפסאודו-אלמנט שנסביר עליו בהמשך, כדי להוסיף סגנון להדגשה. אחרת, רוב הדברים שאני כותב הם בעיקר דברים קטנים עם דעה אישית. אני אוהב שהסמן יהיה משולש, אני אוהב את ההזחות של קווי המתאר, תיבות הסימון שמוגדרות כברירת מחדל קטנות מדי, ואם יש תמיכה ב-accent-color, כדאי להתאים את תיבות הסימון לסכמת הצבעים של המותג.

תוויות של תיבות סימון

חשוב לספק תוויות לתיבות הסימון, מ-2 סיבות. הדרך הראשונה היא לייצג את מטרת הערך של תיבת הסימון, ולענות 'לאיזה מצב מופעל או מושבת?' הסיבה השנייה היא חוויית המשתמש (UX). משתמשי אינטרנט התרגלו לבצע פעולות בתיבת הסימון באמצעות התוויות המשויכות.

קלט
<input
  type="checkbox"
  id="text-notifications"
  name="text-notifications"
>
תווית
<label for="text-notifications">
  <h3>Text Messages</h3>
  <small>Get notified about all text messages sent to your device</small>
</label>

בתווית, מוסיפים מאפיין for שמפנה לתיבת סימון לפי מזהה: <label for="text-notifications">. בתיבה לבחירה, מוסיפים את השם והמזהה פעמיים כדי לוודא שהם יימצאו באמצעות כלים וטכנולוגיות שונים, כמו עכבר או קורא מסך: <input type="checkbox" id="text-notifications" name="text-notifications">. :hover,‏ :active ועוד שירותים זמינים בחינם עם החיבור, כך שתוכלו להגדיל את אפשרויות האינטראקציה עם הטופס.

הדגשת תיבת סימון

אני רוצה לשמור על עקביות בממשקים שלי, ולרכיב פס ההזזה יש הדגשה יפה של התמונה הממוזערת, ואני רוצה להשתמש בה עם תיבת הסימון. התמונה הממוזערת הצליחה להשתמש ב-box-shadow ובנכס spread שלו כדי לשנות את הגודל של הצללית. אבל האפקט הזה לא עובד כאן כי תיבות הסימון שלנו וצריכות להיות ריבועיות.

הצלחתי להשיג את אותו אפקט חזותי באמצעות פסאודו-רכיב, ומספר לא מבוטל של קוד CSS מסובך:

@custom-media --motionOK (prefers-reduced-motion: no-preference);

input[type="checkbox"]::before {
  --thumb-scale: .01;                        /* initial scale of highlight */
  --thumb-highlight-size: var(--space-xl);

  content: "";
  inline-size: var(--thumb-highlight-size);
  block-size: var(--thumb-highlight-size);
  clip-path: circle(50%);                     /* circle shape */
  position: absolute;                         /* this is why position relative on parent */
  top: 50%;                                   /* pop and plop technique (https://web.dev/centering-in-css#5-pop-and-plop) */
  left: 50%;
  background: var(--thumb-highlight-color);
  transform-origin: center center;            /* goal is a centered scaling circle */
  transform:                                  /* order here matters!! */
    translateX(-50%)                          /* counter balances left: 50% */
    translateY(-50%)                          /* counter balances top: 50% */
    translateZ(-1px)                          /* PUTS IT BEHIND THE CHECKBOX */
    scale(var(--thumb-scale))                 /* value we toggle for animation */
  ;
  will-change: transform;

  @media (--motionOK) {                       /* transition only if motion is OK */
    & {
      transition: transform .2s ease;
    }
  }
}

/* on hover, set scale custom property to "in" state */
input[type="checkbox"]:hover::before {
  --thumb-scale: 1;
}

קל ליצור רכיב מדומה של מעגל, אבל היה קשה יותר להציב אותו מאחורי הרכיב שאליו הוא מצורף. לפני פתרון הבעיה ואחרי פתרון הבעיה:

זו בהחלט אינטראקציה מיקרו, אבל חשוב לי לשמור על העקביות החזותית. טכניקת שינוי הגודל באנימציה זהה לזו שבה השתמשנו במקומות אחרים. אנחנו מגדירים למאפיין מותאם אישית ערך חדש ומאפשרים ל-CSS לבצע את המעבר שלו על סמך העדפות התנועה. התכונה העיקרית כאן היא translateZ(-1px). הרכיב ההורה יצר מרחב תלת-ממדי, והרכיב הצאצא של הפרוטוטיפ השתמש בו על ידי מיקום עצמו מעט לאחור במרחב z.

נגישות

הסרטון ב-YouTube מדגים בצורה נהדרת את האינטראקציות של העכבר, המקלדת וקורא המסך עבור רכיב ההגדרות הזה. אציין כאן כמה פרטים.

אפשרויות לרכיבי HTML

<form>
<header>
<fieldset>
<picture>
<label>
<input>

כל אחד מהם מכיל טיפים והצעות לגבי כלי הגלישה של המשתמש. חלק מהרכיבים מספקים טיפים לאינטראקציה, חלק מקשרים בין רכיבים אינטראקטיביים וחלק עוזרים לעצב את עץ הנגישות שבו קורא המסך מנווט.

מאפייני HTML

אנחנו יכולים להסתיר רכיבים שלא נחוצים לקוראי מסך, במקרה הזה הסמל לצד פס ההזזה:

<picture aria-hidden="true">

בסרטון שלמעלה מוצגת התהליך של קורא המסך ב-Mac OS. שימו לב איך מיקוד הקלט נע ישר מפס הזזה אחד לפס הזזה אחר. הסיבה לכך היא שהסתרתם את הסמל שיכול להיות שעצר בדרך לפס ההזזה הבא. בלי המאפיין הזה, המשתמש יצטרך לעצור, להקשיב ולעבור את התמונה, שאולי הוא לא יוכל לראות.

קובץ ה-SVG הוא אוסף של נוסחאות מתמטיות. נוסיף אליו רכיב <title> כדי להציג כותרת ללא תשלום כשהעכבר מרחף מעליו, ותגובה שאנשים יכולים לקרוא על מה שהנוסחאות יוצרות:

<svg viewBox="0 0 24 24">
  <title>A note icon</title>
  <path d="M12 3v10.55c-.59-.34-1.27-.55-2-.55-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4V7h4V3h-6z"/>
</svg>

בנוסף, השתמשנו בכמות מספקת של HTML עם סימון ברור, כך שהטופס נבדק בצורה טובה מאוד בעזרת עכבר, מקלדת, שלטים למשחקי וידאו וקוראי מסך.

JavaScript

כבר התייחסתי לאופן שבו מנוהל צבע המילוי של הטראק מ-JavaScript, אז עכשיו נבחן את קוד ה-JavaScript הקשור ל-<form>:

const form = document.querySelector('form');

form.addEventListener('input', event => {
  const formData = Object.fromEntries(new FormData(form));
  console.table(formData);
})

בכל פעם שמתבצעת אינטראקציה עם הטופס והוא משתנה, המסוף מתעד את הטופס כאובייקט בטבלה כדי שיהיה קל לבדוק אותו לפני השליחה לשרת.

צילום מסך של התוצאות console.table() , שבו נתוני הטופס מוצגים בטבלה

סיכום

עכשיו, אחרי שסיפרתי לך איך עשיתי את זה, איך היית עושה את זה? זה יוצר ארכיטקטורה מעניינת של רכיבים. מי ירצה ליצור את הגרסה הראשונה עם משבצות בסביבת הפיתוח המועדפת עליו? 🙂

נרחיב את הגישות שלנו ונלמד את כל הדרכים לפיתוח באינטרנט. אפשר ליצור הדגמה, לשלוח לי קישור לשלחו לי ציוץ ואני אוסיף אותו לקטע רמיקסים מהקהילה בהמשך!

רמיקסים של הקהילה

  • @tomayac עם הסגנון שלהם לגבי אזור ההעברה מעל תוויות התיבות הסימון! בגרסה הזו אין פער בנתונים בין הרכיבים: demo ו-source.