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

Just for gap
הפריסה הנפוצה ביותר:
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(). אונה קראבטס פרסמה פוסט מצוין בבלוג בנושא הזה, וקראה לו RAM.
יש 3 תוספות מיוחדות בפריסה שלנו, בהשוואה לזו של אונה:
- אנחנו מעבירים פונקציית
min()נוספת. - אנחנו מציינים את
align-items: flex-start. - יש סגנון
max-width: 89vw.
הפונקציה הנוספת min() מתוארת היטב על ידי אוון מינטו בבלוג שלו בפוסט 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 נראה די טוב!
זוכרים את הפריסה הקודמת, "רק בשביל הרווח"? הנה גרסה מלאה יותר של האופן שבו הם נראים ברכיב הזה:
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). זה יתרון משמעותי, כי לבני אדם קל יותר לכתוב את זה, ובני אדם אחרים יבינו את ההתאמות האלה.
היום, בהדגמה הזו, נתמקד בתחביר ובערכים שאני מחליף כדי ליצור מצב בהיר וכהה. בואו נסתכל על משטח אחד וצבע טקסט אחד:
: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 שהעיצוב שלכם משתמש בהם.
הדוגמה שלמעלה ממחישה את ההשפעה של המאפיין מהחלונית Styles בכלי הפיתוח. בהדגמה נעשה שימוש בתג HTML, שלדעתי הוא בדרך כלל מיקום טוב יותר:
<meta name="color-scheme" content="dark light">
תומאס סטיינר מסביר על כך בפירוט color-schemeבמאמר הזה. יש עוד הרבה דברים שאפשר להרוויח,
ולא רק תיבות סימון כהות.
CSS accent-color
לאחרונה, accent-color הופיע ברכיבי טפסים, כסגנון CSS יחיד שיכול לשנות את הגוון שבו נעשה שימוש ברכיב הקלט של הדפדפנים. מידע נוסף זמין כאן ב-GitHub. הוספתי אותו לסגנונות
של הרכיב הזה. כשהדפדפנים יתמכו בזה, תיבות הסימון שלי יהיו יותר תואמות לעיצוב עם הבלטות הצבעים בוורוד ובסגול.
input[type="checkbox"] {
accent-color: var(--brand);
}

הבלטת צבעים עם שינויי צבע הדרגתיים קבועים ומיקוד פנימי
הצבע בולט הכי הרבה כשמשתמשים בו בצורה מתונה, ואחת הדרכים שאני אוהב להשיג את זה היא באמצעות אינטראקציות צבעוניות בממשק המשתמש.
בסרטון שלמעלה יש הרבה שכבות של משוב ואינטראקציה בממשק המשתמש, שעוזרות להוסיף אופי לאינטראקציה:
- הדגשת ההקשר.
- הצגת משוב בממשק המשתמש לגבי "כמה מלא" הערך בטווח.
- מתן משוב בממשק המשתמש על כך ששדה מקבל קלט.
כדי לספק משוב כשמתבצעת אינטראקציה עם רכיב, 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;
}
}
}
כשאחד מהצאצאים של הרכיב הזה נמצא במיקוד:
- לרקע של
.fieldset-itemמוקצה צבע משטח עם ניגודיות גבוהה יותר. - ה-
svgהפנימי ממולא בלבן כדי ליצור ניגודיות גבוהה יותר. - ה-
<picture>clip-pathהמקונן מתרחב למעגל מלא והרקע מתמלא בשיפוע הקבוע הבהיר.
טווח מותאם אישית
בהתאם לרכיב הקלט הבא ב-HTML, אראה לכם איך התאמתי אישית את המראה שלו:
<input type="range">
יש 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, אבל הן דורשות שרכיב ה-thumb יהיה באותו גובה כמו ה-track, ולא הצלחתי למצוא הרמוניה בתוך המגבלות האלה.
/* 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;
}
}
המטרה הייתה ליצור הדגשה חזותית מונפשת וקלה לניהול של משוב מהמשתמשים. באמצעות צללית תיבה, אני יכול להימנע מהפעלת פריסה עם האפקט. כדי לעשות את זה, אני יוצר צל לא מטושטש שתואם לצורה המעגלית של רכיב ה-thumb. אחר כך אני משנה את גודל הפיזור של הצל במעבר עם העכבר.
אם רק אפקט ההדגשה היה כל כך קל בתיבות סימון…
בוררים בדפדפנים שונים
גיליתי שהייתי צריך את הסלקטורים -webkit- ו--moz- כדי להשיג עקביות בין דפדפנים:
input[type="range"] {
&::-webkit-slider-runnable-track {}
&::-moz-range-track {}
&::-webkit-slider-thumb {}
&::-moz-range-thumb {}
}
תיבת סימון בהתאמה אישית
בהתאם לרכיב הקלט הבא ב-HTML, אראה לכם איך התאמתי אישית את המראה שלו:
<input type="checkbox">
יש 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, אני רוצה שתיבות הסימון האלה יהיו בערכת הצבעים של המותג.
תוויות של תיבות סימון
חשוב לספק תוויות לתיבות סימון משתי סיבות. הראשון הוא לייצג את השימוש בערך של תיבת הסימון, כדי לענות על השאלה "מופעל או מושבת בשביל מה?" הסיבה השנייה קשורה לחוויית המשתמש: משתמשים באינטרנט התרגלו ללחוץ על התוויות שמשויכות לתיבות הסימון כדי לסמן אותן.
<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);
})
בכל פעם שמשתמשים בטופס ומשנים אותו, המסוף מתעד את הטופס כאובייקט בטבלה כדי שיהיה קל לבדוק אותו לפני השליחה לשרת.

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