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
以外的元素移動動畫,可能會變慢。在以下範例中,我使用 transform
為 top
和 left
製作動畫,並獲得相同的視覺效果。
.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); } }
reduce
位元會替換為標準、無聊且可讀的 for 迴圈。
撰寫 Houdini 自訂屬性
以下是設定自訂屬性 (例如 CSS 變數) 的範例,但現在使用語法 (類型)、初始值 (備用) 和繼承布林值 (是否從父項繼承值)。目前的做法是透過 JavaScript 中的 CSS.registerProperty()
,但在 Chromium 85 以上版本中,CSS 檔案將支援 @property
語法:
CSS.registerProperty({ name: '--colorPrimary', syntax: '' , initialValue: 'magenta', inherits: false });
@property --colorPrimary { syntax: '' ; initial-value: magenta; inherits: false; }
您現在可以透過 var(--colorPrimary)
存取 --colorPrimary
,就像存取任何其他 CSS 自訂屬性一樣。不過,這裡的差異在於 --colorPrimary
不只是字串。它有資料!
CSS backdrop-filter
會將一或多個效果套用至半透明或透明的元素。請參考下列圖片,瞭解這項功能。

.frosty-glass-pane { backdrop-filter: blur(2px); }

.frosty-glass-pane { opacity: .9; backdrop-filter: blur(2px); }
左圖顯示,如果未使用或不支援 backdrop-filter
,重疊元素的算繪方式。右側圖片使用 backdrop-filter
套用模糊效果。請注意,除了 backdrop-filter
外,它還會使用 opacity
。如果沒有 opacity
,就沒有任何內容可套用模糊處理。不言可喻,如果 opacity
設為 1
(完全不透明),背景就不會受到影響。
不過,beforeunload
與 unload
不同,有合法的用途。舉例來說,如果您想警告使用者,如果離開頁面,他們會失去未儲存的變更,在這種情況下,建議您只在使用者有未儲存的變更時,才新增 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
應與一組連結水平移動,而這個標頭版面配置有助於設定該階段。這裡沒有絕對位置元素!
溫和的彈性調整是「只」以中心為準的策略。這項操作方式溫和輕柔,因為與 place-content: center
不同,在對齊期間,不會變更任何子項的方塊大小。盡可能讓所有項目堆疊、置中且間隔均勻。
.gentle-flex {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 1ch;
}
- 只處理對齊、方向和分布
- 編輯和維護作業都在同一個地方
- 間距可確保 n 個子項之間的間距相同
- 程式碼行數
適合宏觀和微觀版面配置。
用量
.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; }
間距可傳遞 2 個長度,用於列和欄。
.grid { display: grid; gap: 10px 5%; }
.grid { display: grid; row-gap: 10px; column-gap: 5%; }