למאפיין 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, ולבחון את הביצועים באמצעות DevTools.
באמצעות אותו סימון, אפשר להחליף את 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); } }
reduce "החכם" מוחלף בלולאת for רגילה, משעממת וקריאה.
כתיבת מאפיינים מותאמים אישית ב-Houdini
הנה דוגמה להגדרת מאפיין מותאם אישית (למשל: משתנה CSS), אבל עכשיו עם תחביר (סוג), ערך ראשוני (חלופה) וערכו של בוליאני בירושה (האם הוא יקבל בירושה את הערך מההורה או לא?). הדרך הנוכחית לעשות זאת היא באמצעות 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 לא נקרא רק כמחרוזת. יש בו נתונים!
ב-CSS backdrop-filter חל אפקט אחד או יותר על רכיב שקוף או שקוף למחצה. כדי להבין את זה, כדאי לעיין בתמונות הבאות.
.frosty-glass-pane { backdrop-filter: blur(2px); }
.frosty-glass-pane { opacity: .9; backdrop-filter: blur(2px); }
בתמונה שבצד ימין מוצגת עיבוד של רכיבים חופפים אם לא נעשה שימוש ב-backdrop-filter או אם הוא לא נתמך. בתמונה שבצד ימין הוחל אפקט טשטוש באמצעות backdrop-filter. שימו לב שהקוד משתמש ב-opacity בנוסף ל-backdrop-filter. בלי opacity, לא יהיה על מה להחיל טשטוש. מובן מאליו שאם opacity מוגדר כ-1 (אטום לחלוטין), לא תהיה השפעה על הרקע.
עם זאת, בניגוד לאירוע unload, יש שימושים לגיטימיים באירוע beforeunload. לדוגמה, כשרוצים להזהיר את המשתמש שיש לו שינויים שלא נשמרו, והם יאבדו אם הוא ייצא מהדף. במקרה כזה, מומלץ להוסיף מאזינים ל-beforeunload רק כשיש למשתמש שינויים שלא נשמרו, ואז להסיר אותם מיד אחרי שמירת השינויים שלא נשמרו.
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); });
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>
הפריסה הבאה דומה מאוד: אני משתמש ב-flex כדי ליצור סדר אנכי.
<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;
}
- מטפל רק בהתאמה, בכיוון ובהפצה
- עריכה ותחזוקה במקום אחד
- Gap מבטיח מרחקים שווים בין n צאצאים
- מספר שורות הקוד הגדול ביותר
מתאימות גם לפריסות מאקרו וגם לפריסות מיקרו.
שימוש
אפשר להשתמש ב-gap כערך של כל אורך או אחוז ב-CSS.
.gap-example {
display: grid;
gap: 10px;
gap: 2ch;
gap: 5%;
gap: 1em;
gap: 3vmax;
}
אפשר להעביר למאפיין Gap אורך של 1, והוא ישמש גם לשורה וגם לעמודה.
.grid { display: grid; gap: 10px; }
.grid { display: grid; row-gap: 10px; column-gap: 10px; }
אפשר להעביר ל-Gap 2 אורכי מחרוזות, שישמשו לשורה ולעמודה.
.grid { display: grid; gap: 10px 5%; }
.grid { display: grid; row-gap: 10px; column-gap: 5%; }