למאפיין lang יכולה להיות משויכת שפה אחת בלבד. כלומר,
למאפיין <html>
יכולה להיות רק שפה אחת, גם אם יש בדף כמה שפות. מגדירים את lang
כשפה הראשית של הדף.
<html lang="ar,en,fr,pt">...</html>אין תמיכה במספר שפות.
<html lang="ar">...</html>הגדרת השפה הראשית בלבד של הדף. במקרה הזה, השפה היא ערבית.
קישורים
בדומה ללחצנים, קישורים מקבלים את השם הנגיש בעיקר מתוכן הטקסט. טריק נחמד ליצירת קישור הוא להוסיף את קטע הטקסט המשמעותי ביותר לקישור עצמו, במקום מילות מילוי כמו "כאן" או "קרא עוד".
Check out our guide to web performance <a href="/guide">here</a>.
Check out <a href="/guide">our guide to web performance</a>.
איך בודקים אם אנימציה מפעילה את הפריסה
אנימציה שמזיזה רכיב באמצעות רכיב שאינו transform
, צפויה להיות איטית.
בדוגמה הבאה הגעתי לאותה תוצאה חזותית עם אנימציה של top
ו-left
, ומשתמש ב-transform
.
.box { position: absolute; top: 10px; left: 10px; animation: move 3s ease infinite; } @keyframes move { 50% { top: calc(90vh - 160px); left: calc(90vw - 200px); } }
.box { position: absolute; top: 10px; left: 10px; animation: move 3s ease infinite; } @keyframes move { 50% { transform: translate(calc(90vw - 200px), calc(90vh - 160px)); } }
אפשר לבדוק זאת בעזרת שתי הדוגמאות הבאות של Glitch ולחקור את הביצועים באמצעות כלי פיתוח.
עם אותו תגי עיצוב, נוכל להחליף את: padding-top: 56.25%
ב-aspect-ratio: 16 / 9
, ולהגדיר את
aspect-ratio
ליחס קבוע של width
ל-height
.
.container { width: 100%; padding-top: 56.25%; }
.container { width: 100%; aspect-ratio: 16 / 9; }
השימוש ב-aspect-ratio
במקום ב-padding-top
הרבה יותר ברור, ולא משנה את מאפיין המרווח הפנימי כדי לבצע פעולות שחורגות מההיקף הרגיל שלו.
כן, נכון, אני משתמשת ב-reduce
כדי לשרשר רצף של הבטחות. אני כל כך חכם. אבל זה תכנות קצת כל כך חכם שעדיף בלי.
עם זאת, כשממירים את הערכים שלמעלה לפונקציה אסינכרונית, מפתה לעבור לרצף מדי:
async function logInOrder(urls) { for (const url of urls) { const response = await fetch(url); console.log(await response.text()); } }נראה הרבה יותר מסודר, אבל האחזור השני שלי מתחיל רק אחרי הקראה מלאה של האחזור הראשון, וכן הלאה. זה הרבה יותר איטי מדוגמה ההבטחה שמבצעת את האחזורים במקביל. למרבה המזל, יש כאן דרך אמצע אידיאלית.
function markHandled(...promises) { Promise.allSettled(promises); } async function logInOrder(urls) { // fetch all the URLs in parallel const textPromises = urls.map(async (url) => { const response = await fetch(url); return response.text(); }); markHandled(...textPromises); // log them in sequence for (const textPromise of textPromises) { console.log(await textPromise); } }בדוגמה הזו, כתובות ה-URL מאוחזרות וניתנות לקריאה במקביל, אבל הביט "חכם"
reduce
מוחלף בביט סטנדרטי, משעמם וקריא ל-לולאה.
כתיבת מאפיינים מותאמים אישית של Houdini
הנה דוגמה להגדרת נכס מותאם אישית (Think: משתנה CSS), אבל עכשיו עם תחביר (type), ערך ראשוני (fallback) וירושה בוליאנית (האם הוא יורש את הערך מההורה שלו או לא?). כרגע יש תמיכה בתחביר CSS.registerProperty()
ב-JavaScript, אבל ב-Chromium 85 ואילך יש תמיכה בתחביר @property
בקובצי ה-CSS:
CSS.registerProperty({ name: '--colorPrimary', syntax: '', initialValue: 'magenta', inherits: false });
@property --colorPrimary { syntax: ''; initial-value: magenta; inherits: false; }
מעכשיו אפשר לגשת אל --colorPrimary
כמו לכל נכס CSS מותאם אישית אחר, דרך var(--colorPrimary)
. עם זאת, ההבדל כאן הוא ש---colorPrimary
לא נקרא רק כמחרוזת. יש בו נתונים!
backdrop-filter
של CSS מחיל אפקט אחד או יותר על רכיב שקוף או שקוף. כדי להבין את זה, אפשר להיעזר בתמונות הבאות.
![משולש שמופיע מעל עיגול. לא ניתן לראות את העיגול דרך המשולש.](https://web.dev/static/examples/image/admin/LOqxvB3qqVkbZBmxMmKS.png?hl=he)
.frosty-glass-pane { backdrop-filter: blur(2px); }
![משולש שמופיע מעל עיגול. המשולש שקוף מאפשר לראות את העיגול באמצעותו.](https://web.dev/static/examples/image/admin/VbyjpS6Td39E4FudeiVg.png?hl=he)
.frosty-glass-pane { opacity: .9; backdrop-filter: blur(2px); }
התמונה שמימין מראה איך רכיבים חופפים יוצגו אם לא ייעשה שימוש ב-backdrop-filter
או אם הוא לא נתמך. בתמונה שמשמאל יופעל אפקט טשטוש באמצעות backdrop-filter
. לתשומת ליבך, היא משתמשת ב-opacity
בנוסף ל-backdrop-filter
. בלי opacity
לא תהיה שום אפשרות להחיל טשטוש. כמעט מיותר לציין שאם opacity
מוגדרת לערך 1
(אטום לחלוטין) לא תהיה כל השפעה על הרקע.
עם זאת, בניגוד לאירוע unload
, יש שימושים לגיטימיים
ב-beforeunload
. לדוגמה, כשרוצים להזהיר את המשתמש על כך שהשינויים שלא נשמרו, הם יאבדו אם הם יעזבו את הדף. במקרה כזה, מומלץ להוסיף פונקציות beforeunload
listener רק אם למשתמש יש שינויים שלא נשמרו, ולאחר מכן להסיר אותם מיד לאחר שהשינויים שלא נשמרו נשמרים.
window.addEventListener('beforeunload', (event) => { if (pageHasUnsavedChanges()) { event.preventDefault(); return event.returnValue = 'Are you sure you want to exit?'; } });הקוד שלמעלה מוסיף האזנה ל-
beforeunload
ללא תנאי.
function beforeUnloadListener(event) { event.preventDefault(); return event.returnValue = 'Are you sure you want to exit?'; }; // A function that invokes a callback when the page has unsaved changes. onPageHasUnsavedChanges(() => { window.addEventListener('beforeunload', beforeUnloadListener); }); // A function that invokes a callback when the page's unsaved changes are resolved. onAllChangesSaved(() => { window.removeEventListener('beforeunload', beforeUnloadListener); });בקוד שלמעלה, הוספת ה-listener מסוג
beforeunload
מתווספת רק כשצריך (ומסירים אותו כשאין צורך).
צמצום השימוש ב-Cache-Control: no-store
Cache-Control: no-store
היא כותרת HTTP ששרתי אינטרנט יכולים להגדיר בתשובות, שמורה לדפדפן לא לאחסן את התגובה במטמון HTTP כלשהו. צריך להשתמש באפשרות הזו למשאבים שמכילים מידע רגיש על המשתמש, לדוגמה, דפים שמחייבים התחברות.
הרכיב 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>
.
<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>
הרכיב 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); } } }
פריסה <header>
כרטיסיות
הפריסה הבאה כמעט זהה: השיטה גמישה משמשת ליצירת סדר אנכי.
<snap-tabs> <header> <nav></nav> <span class="snap-indicator"></span> </header> <section></section> </snap-tabs>
header { display: flex; flex-direction: column; }
ה-.snap-indicator
צריך לעבור בצורה אופקית עם קבוצת הקישורים, והפריסה של הכותרת עוזרת להגדיר את השלב הזה. אין כאן רכיבים ממוקמים מוחלטים!
Gentle Flex היא אסטרטגיית התמקדות בלבד אמיתית. הוא רך ועדין, כי בניגוד ל-place-content: center
, לא מתבצע שינוי במידות של קופסאות ילדים בזמן המרכוז. בצורה עדינה ככל האפשר, כל הפריטים מוערמים, ממורכזים ומרווחים.
.gentle-flex {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 1ch;
}
- מטפל רק ביישור, כיוון והתפלגות
- פעולות עריכה ותחזוקה מרוכזות במקום אחד
- הפער מבטיח ריווח שווה בין n ילדים
- רוב שורות הקוד
מעולה גם לפריסות מאקרו וגם לפריסות מיקרו.
Usage
gap
יכול לקבל כל length או percentage של CSS.
.gap-example {
display: grid;
gap: 10px;
gap: 2ch;
gap: 5%;
gap: 1em;
gap: 3vmax;
}
אפשר להעביר רווח באורך 1, שישמש גם לשורה וגם לעמודה.
.grid { display: grid; gap: 10px; }הגדרה של שורות ועמודות ביחד בו-זמנית
.grid { display: grid; row-gap: 10px; column-gap: 10px; }
ניתן להעביר פער של שני אורכים, שישמשו כשורה ועמודה.
.grid { display: grid; gap: 10px 5%; }מגדירים גם שורות וגם עמודות בנפרד בבת אחת
.grid { display: grid; row-gap: 10px; column-gap: 5%; }