סקירה כללית בסיסית של תהליך היצירה של סרגל טעינה נגיש וגמיש לצבעים עם הרכיב <progress>
.
בפוסט הזה אני רוצה לשתף אתכם בחשיבה על האופן שבו ניתן ליצור אפקט צבעוני
סרגל טעינה נגיש עם הרכיב <progress>
. רוצים לנסות את
ההדגמה ו
source!
אם אתם מעדיפים סרטון, הנה גרסה של YouTube לפוסט:
סקירה כללית
<progress>
שמספק למשתמשים משוב ויזואלי וקולי לגבי ההשלמה. הזה
משוב חזותי הוא בעל ערך רב לתרחישים כמו: התקדמות בטופס,
הצגה או הורדה של מידע, או אפילו להציג
סכום ההתקדמות לא ידוע, אבל העבודה עדיין פעילה.
אתגר GUI הזה עבד עם
את רכיב ה-HTML הקיים <progress>
כדי לחסוך מאמץ מסוים בנגישות.
הצבעים והפריסות דוחפים את גבולות ההתאמה האישית של הרכיב המובנה,
לחדש את הרכיב ולהתאים אותו טוב יותר למערכות העיצוב.
![הכרטיסיות הבהירות והכהות בכל דפדפן מספקות
סקירה כללית של הסמל המותאם אישית מלמעלה למטה:
Safari, Firefox, Chrome.](https://web.developers.google.cn/static/articles/building/a-loading-bar-component/image/light-dark-tabs-each-br-cd04389a437d1.png?authuser=9&hl=he)
Markup
בחרתי לעטוף את הרכיב <progress>
<label>
כך
ניתן לדלג על מאפייני מערכת היחסים המשתמעים לטובת שינוי מרומז
יחסים רציפים.
גם סימנתי בתווית רכיב הורה שמושפע ממצב הטעינה, לכן המסך
טכנולוגיות קריאה יכולות להעביר את המידע הזה למשתמש.
<progress></progress>
אם אין value
, התקדמות הרכיב היא
לא קבוע.
ערך ברירת המחדל של המאפיין max
הוא 1, כך שההתקדמות היא בין 0 ל-1. מתבצעת הגדרה של max
ל-100, למשל, תגדיר את הטווח בין 0 ל-100. בחרתי לא לחרוג מהטווח של 0
ו-1 מגבלות, תרגום ערכי ההתקדמות ל-0.5 או ל-50%.
התקדמות האריזה של התווית
בקשר מרומז, רכיב התקדמות מוקף בתווית כזו:
<label>Loading progress<progress></progress></label>
בהדגמה שלי בחרתי לכלול את התווית לקוראי מסך
בלבד.
כדי לעשות את זה, גוזרים את הטקסט של התווית ב-<span>
ומחילים כמה סגנונות
כדי להציג אותו באופן אפקטיבי:
<label>
<span class="sr-only">Loading progress</span>
<progress></progress>
</label>
עם שירות ה-CSS הנלווה הבא מ-WebAIM:
.sr-only {
clip: rect(1px, 1px, 1px, 1px);
clip-path: inset(50%);
height: 1px;
width: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
}
האזור המושפע מהתקדמות הטעינה
אם יש לכם ראייה בריאה, אפשר לשייך בקלות אינדיקטור התקדמות
שמכיל רכיבים קשורים ואזורי דף קשורים, אבל למשתמשים עם ליקויי ראייה אין
כל כך ברור. כדי לשפר את זה, אפשר להקצות את
aria-busy
לאלמנט העליון ביותר שישתנה בסיום הטעינה.
כמו כן, יש לציין קשר בין ההתקדמות לאזור הטעינה
עם
aria-describedby
<main id="loading-zone" aria-busy="true">
…
<progress aria-describedby="loading-zone"></progress>
</main>
ב-JavaScript, מחליפים את המצב aria-busy
ל-true
בתחילת המשימה, ו-
false
.
תוספות של מאפיין אריה
למרות שהתפקיד המשתמע של רכיב <progress>
הוא
progressbar
, כתבתי את התוכן באופן בוטה
לדפדפנים שאין להם את התפקיד המשתמע הזה. כמו כן, הוספתי את המאפיין
indeterminate
כדי להעביר את הרכיב באופן מפורש למצב לא ידוע, כלומר
יותר ברור מצפייה ברכיב, לא הוגדרה לו value
.
<label>
Loading
<progress
indeterminate
role="progressbar"
aria-describedby="loading-zone"
tabindex="-1"
>unknown</progress>
</label>
כדאי להשתמש
tabindex="-1"
כדי שניתן יהיה להתמקד ברכיב ההתקדמות מ-JavaScript. זה חשוב כדי
את הטכנולוגיה של קורא המסך, מכיוון שהמיקוד הוא על סמך שינוי ההתקדמות,
המערכת תיידע את המשתמש לגבי השלב הנוכחי של ההתקדמות המעודכנת.
סגנונות
רכיב ההתקדמות קצת מסובך כשמדובר בעיצוב. HTML מובנה יש חלקים נסתרים מיוחדים שקשה לבחור ולרוב מציעה רק קבוצה מוגבלת של נכסים להגדרה.
פריסה
סגנונות הפריסה נועדו לאפשר גמישות מסוימת במהלך הגודל ומיקום התווית של הרכיב. יתווסף מצב השלמה מיוחד שיכול להיות סימן חזותי שימושי נוסף, אבל לא נדרש.
פריסה של <progress>
לא בוצעו שינויים ברוחב של רכיב ההתקדמות, כך שהוא יכול להתכווץ ולגדול
את השטח הנדרש בעיצוב. הסגנונות המובְנים מושמטים על ידי
הגדרה של appearance
ו-border
כ-none
. לעשות את זה כדי שהרכיב
מנורמלים לפי דפדפנים, כי לכל דפדפן יש סגנונות משלו
לרכיב מסוים.
progress {
--_track-size: min(10px, 1ex);
--_radius: 1e3px;
/* reset */
appearance: none;
border: none;
position: relative;
height: var(--_track-size);
border-radius: var(--_radius);
overflow: hidden;
}
הערך של 1e3px
עבור _radius
משתמש במספר מדעי
כדי לבטא
גדול, כך שה-border-radius
תמיד יעוגל. היא מקבילה ל-
1000px
אני אוהבת להשתמש בזה כי המטרה שלי היא להשתמש בערך גדול מספיק
אני יכול להגדיר את זה ולשכוח את זה (וכתיבה קצרה יותר מ-1000px
). כמו כן
קל להגדיל אותו במקרה הצורך: פשוט משנים את ה-3 ל-4, ואז 1e4px
מקביל ל-10000px
.
overflow: hidden
נמצא בשימוש והיה סגנון מעורר מחלוקת. עזר לי
לביצוע פעולות פשוטות, כמו שלא תצטרכו להעביר את ערכי border-radius
לעקוב אחר רכיבי מילוי ולעקוב אחריהם; אבל גם לא היו ילדים בהתקדמות
נמצאים מחוץ לאלמנט. איטרציה נוספת להתקדמות המותאמת אישית הזו
ניתן לבצע את האלמנט בלי overflow: hidden
והוא עשוי לפתוח
הזדמנויות לאנימציות או מצבי השלמה טובים יותר.
ההתקדמות הושלמה
הסלקטורים ב-CSS עושים את העבודה הקשה כאן: הם משווים את הערך המקסימלי לערך, ואם הם תואמים, ההתקדמות הושלמה. בסיום התהליך, נוצר פסאודו-אלמנט ומוצמד לסוף רכיב ההתקדמות, וכך הוא מספק סימן חזותי נוסף וחמוד לסיום.
progress:not([max])[value="1"]::before,
progress[max="100"][value="100"]::before {
content: "✓";
position: absolute;
inset-block: 0;
inset-inline: auto 0;
display: flex;
align-items: center;
padding-inline-end: max(calc(var(--_track-size) / 4), 3px);
color: white;
font-size: calc(var(--_track-size) / 1.25);
}
צבע
הדפדפן כולל צבעים משלו לרכיב ההתקדמות, והוא ניתן להתאמה בהיר כהה עם נכס CSS אחד בלבד. אפשר להתבסס עליהם בעזרת בוררים מיוחדים ספציפיים לדפדפן.
סגנונות דפדפן בהירים כהים
כדי להוסיף את האתר לרכיב <progress>
דינמי כהה ובהיר,
כל מה שצריך לעשות הוא color-scheme
.
progress {
color-scheme: light dark;
}
צבע מלא להתקדמות בנכס יחיד
כדי ליצור גוון של רכיב <progress>
, צריך להשתמש ב-accent-color
.
progress {
accent-color: rebeccapurple;
}
שימו לב שצבע הרקע של הטראק משתנה מבהיר לכהה בהתאם
accent-color
הדפדפן שומר על ניגודיות מתאימה: די מסודר.
צבעים בהירים כהים בהתאמה אישית
הגדרת שני מאפיינים מותאמים אישית לרכיב <progress>
, אחד לצבע הטראק
והשני לצבע ההתקדמות של הטראק. בתוך
prefers-color-scheme
שאילתת מדיה, צריך לציין ערכי צבע חדשים עבור הטראק ולעקוב אחרי ההתקדמות.
progress {
--_track: hsl(228 100% 90%);
--_progress: hsl(228 100% 50%);
}
@media (prefers-color-scheme: dark) {
progress {
--_track: hsl(228 20% 30%);
--_progress: hsl(228 100% 75%);
}
}
סגנונות מיקוד
מוקדם יותר נתנו לאלמנט אינדקס שלילי של Tab כדי שאפשר יהיה להשתמש בו באופן פרוגרמטי
ממוקד. כדאי להשתמש
:focus-visible
עד
כדאי להתאים אישית את המיקוד כדי לבחור בסגנון טבעת המיקוד החכמה יותר. כדי לעשות את זה,
לחיצה על 'מיקוד' לא תציג את טבעת המיקוד, אך לחיצות על המקלדת כן יוצגו.
סרטון ב-YouTube עוסק בנושא הזה לעומק
שכדאי לבדוק.
progress:focus-visible {
outline-color: var(--_progress);
outline-offset: 5px;
}
סגנונות מותאמים אישית בין דפדפנים
ניתן להתאים אישית את הסגנונות על ידי בחירת החלקים של רכיב <progress>
שכל אחד מהם
בדפדפן נחשף. השימוש ברכיב ההתקדמות הוא תג יחיד, אך הוא מורכב
מספר רכיבי צאצא שנחשפים באמצעות פסאודו-סלקטורים של CSS. כלי פיתוח ל-Chrome
אם תפעילו את ההגדרה, יוצגו הרכיבים הבאים:
- לוחצים לחיצה ימנית על הדף ובוחרים באפשרות בדיקת המרכיב כדי להציג את כלי הפיתוח.
- לוחצים על סמל גלגל השיניים של ההגדרות בפינה השמאלית העליונה של חלון כלי הפיתוח.
- מתחת לכותרת Elements, מאתרים את האפשרות הצגת הצל של סוכן משתמש ומפעילים אותה. DOM תיבת סימון.
הסגנונות של Safari ו-Chromium
דפדפנים מבוססי WebKit כמו Safari ו-Chromium לחשוף
::-webkit-progress-bar
ו-::-webkit-progress-value
, שמאפשרים קבוצת משנה של
שירות CSS. בינתיים, צריך להגדיר את background-color
באמצעות המאפיינים המותאמים אישית
שנוצרו קודם לכן, שמסתגלים לאור ולכהה.
/* Safari/Chromium */
progress[value]::-webkit-progress-bar {
background-color: var(--_track);
}
progress[value]::-webkit-progress-value {
background-color: var(--_progress);
}
סגנונות Firefox
Firefox חושף את הבורר ::-moz-progress-bar
רק
רכיב <progress>
. המשמעות היא גם שאנחנו לא יכולים לבצע את גוון הטראק באופן ישיר.
/* Firefox */
progress[value]::-moz-progress-bar {
background-color: var(--_progress);
}
לתשומת ליבך: ב-Firefox צבע הטראק מוגדר כ-accent-color
וב-Safari ב-iOS
יש טראק בצבע תכלת. אותו הדבר במצב כהה: ב-Firefox יש מסלול כהה
לא הצבע המותאם אישית שהגדרנו, והוא פועל בדפדפנים המבוססים על Webkit.
Animation
בזמן העבודה עם פסאודו-סלקטורים מובנים בדפדפן, בדרך כלל יש הגבלה על קבוצת מאפייני CSS מותרים.
הוספת אנימציה לטראק שמתמלא
הוספת מעבר אל
inline-size
מתוך
רכיב ההתקדמות פועל עבור Chromium אבל לא עבור Safari. גם Firefox
לא להשתמש בנכס מעבר ב-::-moz-progress-bar
.
/* Chromium Only 😢 */
progress[value]::-webkit-progress-value {
background-color: var(--_progress);
transition: inline-size .25s ease-out;
}
הצגת אנימציה של המצב :indeterminate
וכאן יש לי יותר יצירתי כדי שאוכל לספק אנימציה. פסאודו-אלמנט עבור Chromium נוצר והוחל הדרגתי עם אנימציה חוזרת בכל שלושת הדפדפנים.
המאפיינים המותאמים אישית
מאפיינים מותאמים אישית הם כלי מעולה בהרבה דברים, אבל אחד הדברים האהובים עליי פשוט
מתן שם לערך CSS בעל מראה קסום אחר. מעקב הוא די
מורכב
linear-gradient
אבל עם שם יפה. המטרה והתרחישים לדוגמה שלו ברורים בצורה ברורה.
progress {
--_indeterminate-track: linear-gradient(to right,
var(--_track) 45%,
var(--_progress) 0%,
var(--_progress) 55%,
var(--_track) 0%
);
--_indeterminate-track-size: 225% 100%;
--_indeterminate-track-animation: progress-loading 2s infinite ease;
}
מאפיינים מותאמים אישית גם יעזרו לקוד להישאר במצב DRY, כי שוב אנחנו לא יכולים לקבץ יחד את הבוררים הספציפיים לדפדפן.
תמונות המפתח
המטרה היא אנימציה אינסופית שהולכת הלוך וחזור. נקודת ההתחלה והסיום
תמונות המפתח יוגדרו ב-CSS. נדרשת תמונת מפתח אחת בלבד, תמונת המפתח האמצעית
ב-50%
, כדי ליצור אנימציה שחוזרת מאיפה שהיא התחילה,
שוב!
@keyframes progress-loading {
50% {
background-position: left;
}
}
טירגוט כל דפדפן
לא כל דפדפן מאפשר ליצור פסאודו אלמנטים ב<progress>
את הרכיב עצמו או מאפשר להוסיף אנימציה של סרגל ההתקדמות. תמיכה בדפדפנים נוספים
אני יוצר אנימציה של הטראק מאשר פסאודו-אלמנט, אז שדרגתי מפסאודו-אלמנטים
בסיס לפסים מונפשים.
רכיב מדומה של Chromium
ב-Chromium אפשר להשתמש בפסאודו-רכיב: ::after
עם מיקום לכיסוי
את הרכיב. המאפיינים הייחודיים המותאמים אישית משמשים את המאפיין
ואנימציה עובדת טוב מאוד.
progress:indeterminate::after {
content: "";
inset: 0;
position: absolute;
background: var(--_indeterminate-track);
background-size: var(--_indeterminate-track-size);
background-position: right;
animation: var(--_indeterminate-track-animation);
}
סרגל ההתקדמות של Safari
ב-Safari, המאפיינים המותאמים אישית ואנימציה יחולו על סרגל התקדמות של רכיב מדומה:
progress:indeterminate::-webkit-progress-bar {
background: var(--_indeterminate-track);
background-size: var(--_indeterminate-track-size);
background-position: right;
animation: var(--_indeterminate-track-animation);
}
סרגל ההתקדמות של Firefox
ב-Firefox, המאפיינים המותאמים אישית ואנימציה חלים גם על סרגל התקדמות של רכיב מדומה:
progress:indeterminate::-moz-progress-bar {
background: var(--_indeterminate-track);
background-size: var(--_indeterminate-track-size);
background-position: right;
animation: var(--_indeterminate-track-animation);
}
JavaScript
ל-JavaScript יש תפקיד חשוב ברכיב <progress>
. הוא שולט
את הערך שנשלח לאלמנט ומבטיח שיש מספיק מידע
למסמך לקוראי מסך.
const state = {
val: null
}
ההדגמה כוללת לחצנים לשליטה בהתקדמות. הם מעדכנים את state.val
ואז להפעיל פונקציה לעדכון
DOM.
document.querySelector('#complete').addEventListener('click', e => {
state.val = 1
setProgress()
})
setProgress()
הפונקציה הזו היא המקום שבו מתבצע התזמור של ממשק המשתמש או של חוויית המשתמש. כדי להתחיל, צריך ליצור
setProgress()
. לא נדרשים פרמטרים מאחר שיש לה גישה אל
אובייקט state
, רכיב התקדמות ואזור <main>
.
const setProgress = () => {
}
הגדרת סטטוס הטעינה באזור של <main>
הערך של <main>
הרלוונטי תלוי בשאלה אם ההתקדמות הושלמה או לא
צריך לעדכן את הרכיב
aria-busy
:
const setProgress = () => {
zone.setAttribute('aria-busy', state.val < 1)
}
ניקוי המאפיינים אם סכום הטעינה לא ידוע
אם הערך לא ידוע או לא מוגדר, null
בשימוש הזה, צריך להסיר את value
וגם
aria-valuenow
מאפיינים. הפעולה הזו תהפוך את <progress>
לקבוע.
const setProgress = () => {
zone.setAttribute('aria-busy', state.val < 1)
if (state.val === null) {
progress.removeAttribute('aria-valuenow')
progress.removeAttribute('value')
progress.focus()
return
}
}
פתרון בעיות במתמטיקה עם ספרות עשרוניות ב-JavaScript
מאחר שבחרתי להישאר עם ברירת המחדל להתקדמות בשיעור מקסימום של 1, ההדגמה
פונקציות של הגדלה והקטנה משתמשות במתמטיקה עשרונית. JavaScript ועוד
שפות שונות, לא תמיד מוצלחות
זאת.
הנה פונקציית roundDecimals()
לחתוך את החריגה מהמתמטיקה
תוצאה:
const roundDecimals = (val, places) =>
+(Math.round(val + "e+" + places) + "e-" + places)
עגלו את הערך כך שיהיה קריא:
const setProgress = () => {
zone.setAttribute('aria-busy', state.val < 1)
if (state.val === null) {
progress.removeAttribute('aria-valuenow')
progress.removeAttribute('value')
progress.focus()
return
}
const val = roundDecimals(state.val, 2)
const valPercent = val * 100 + "%"
}
הגדרת ערך לקוראי מסך ולמצב הדפדפן
הערך משמש בשלושה מיקומים ב-DOM:
- המאפיין
value
של הרכיב<progress>
. - המאפיין
aria-valuenow
. - תוכן הטקסט הפנימי
<progress>
.
const setProgress = () => {
zone.setAttribute('aria-busy', state.val < 1)
if (state.val === null) {
progress.removeAttribute('aria-valuenow')
progress.removeAttribute('value')
progress.focus()
return
}
const val = roundDecimals(state.val, 2)
const valPercent = val * 100 + "%"
progress.value = val
progress.setAttribute('aria-valuenow', valPercent)
progress.innerText = valPercent
}
מתמקדים בהתקדמות
כשהערכים יתעדכנו, משתמשים שיראו את השינויים יבחינו בהתקדמות, אבל
משתמשי קוראים עדיין לא מקבלים הודעה על שינוי. התמקדות
<progress>
, והדפדפן יכריז על העדכון.
const setProgress = () => {
zone.setAttribute('aria-busy', state.val < 1)
if (state.val === null) {
progress.removeAttribute('aria-valuenow')
progress.removeAttribute('value')
progress.focus()
return
}
const val = roundDecimals(state.val, 2)
const valPercent = val * 100 + "%"
progress.value = val
progress.setAttribute('aria-valuenow', valPercent)
progress.innerText = valPercent
progress.focus()
}
סיכום
עכשיו, אחרי שהסברתי איך עשיתי את זה, איך היית? 🙂
אני בהחלט יש כמה שינויים שארצה לעשות אם תהיה לי הזדמנות נוספת. לדעתי יש מקום למחוק את הרכיב הנוכחי, ואפשר גם לנסות ליצור רכיב כזה בלי הגבלות הסגנון של הרכיב <progress>
. כדאי להתנסות!
בואו לגוון את הגישות שלנו ונלמד את כל הדרכים לבניית אתרים באינטרנט.
אפשר ליצור הדגמה, לשלוח לי קישורים של שלחו לי ציוץ ואני אוסיף אותם לקטע 'רמיקסים' של הקהילה שבהמשך.