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

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

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

הדגמה

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

סקירה כללית

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

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

פריסות

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

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

לפער

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

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

אני קורא לפריסה הזו "Just for gap" כי היא משתמשת ברשת רק כדי להוסיף רווחים בין בלוקים.

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

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

הרכיב 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, כך שצאצאים ממורכזים אנכית ואופקית גם בפריסת עמודה אחת וגם בשתי עמודות.

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

חזרה על מינימום להתאמה אוטומטית

ב-<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 תוספות מיוחדות בפריסה שלנו, אם תשוו אותה לפריסה של אונה:

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

הפונקציה הנוספת min() מתוארת היטב על ידי Evan Minto בבלוג שלו, בפוסט Intrinsically רספונסיבי CSS Grid with minmax() ו-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 gap"? הנה גרסה מלאה יותר של איך הם נראים ברכיב הזה:

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, עם הפרק &#39;צבע 2: תפיסה&#39;
מידע על צבע תפיסה (ועוד!) בפודקאסט של 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 והטמעות דפדפנים.

לאה וורו

בקרות טפסים מותאמות עם ערכת צבעים

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

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

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

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

שירות 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;
    }
  }
}

כשאחד מצאצאי הרכיב הזה מתמקד ב:

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

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

בהתאם לרכיב הבא של קלט 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 זמין, אכלס את המאפיין המותאם אישית תוך כדי בחינת השינויים שהמשתמש ביצע, ומסנכרנים את המאפיין המותאם אישית עם הערך.

הנה פוסט נהדר על 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 הוא נתמך, צריך להכניס את תיבות הסימון האלה ללוח הצבעים של המותג.

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

חשוב לספק תוויות לתיבות סימון משתי סיבות. הראשון הוא כדי לייצג את מטרת השימוש של ערך תיבת הסימון, כדי להשיב על 'on or off for what?' (הפעלה או השבתה של מה?). הסיבה השנייה היא שחוויית המשתמש היא שהמשתמשים באינטרנט התרגלו לאינטראקציה עם תיבות סימון דרך התוויות המשויכות שלהם.

קלט
<input
  type="checkbox"
  id="text-notifications"
  name="text-notifications"
>
label
<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-space.

נגישות

הסרטון ב-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() , שבהן נתוני הטופס מוצגים בטבלה

סיכום

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

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

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

  • @toMayac עם הסגנון שלהן לגבי אזור העברת העכבר לתוויות של תיבות הסימון. בגרסה הזו אין פער העברת העכבר בין הרכיבים: הדגמה ומקור.