Thuộc tính lang chỉ có thể liên kết với một ngôn ngữ. Điều này có nghĩa là thuộc tính <html>
chỉ có thể có một ngôn ngữ, ngay cả khi có nhiều ngôn ngữ trên trang. Đặt lang
thành ngôn ngữ chính của trang.
<html lang="ar,en,fr,pt">...</html>
<html lang="ar">...</html>
Liên kết
Tương tự như các nút, đường liên kết chủ yếu lấy tên hỗ trợ tiếp cận từ nội dung văn bản. Một mẹo hay khi tạo đường liên kết là đặt đoạn văn bản có ý nghĩa nhất vào chính đường liên kết đó, thay vì các từ đệm như "Tại đây" hoặc "Đọc thêm".
Check out our guide to web performance <a href="/guide">here</a>.
Check out <a href="/guide">our guide to web performance</a>.
Kiểm tra xem ảnh động có kích hoạt bố cục hay không
Ảnh động di chuyển một phần tử bằng cách sử dụng một thành phần khác ngoài transform
có thể sẽ bị chậm.
Trong ví dụ sau, tôi đã đạt được kết quả hình ảnh tương tự khi tạo ảnh động top
và left
và sử dụng 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)); } }
Bạn có thể kiểm thử điều này trong hai ví dụ sau về Glitch và khám phá hiệu suất bằng DevTools.
Với cùng một mã đánh dấu, chúng ta có thể thay thế: padding-top: 56.25%
bằng aspect-ratio: 16 / 9
, đặt aspect-ratio
thành tỷ lệ width
/ height
đã chỉ định.
.container { width: 100%; padding-top: 56.25%; }
.container { width: 100%; aspect-ratio: 16 / 9; }
Việc sử dụng aspect-ratio
thay vì padding-top
rõ ràng hơn nhiều và không làm thay đổi thuộc tính khoảng đệm để thực hiện một việc gì đó nằm ngoài phạm vi thông thường.
Vâng, đúng vậy, tôi đang sử dụng reduce
để tạo chuỗi các lời hứa. Tôi rất thông minh. Tuy nhiên, đây là một cách lập trình quá thông minh mà bạn nên tránh.
Tuy nhiên, khi chuyển đổi mã trên thành một hàm không đồng bộ, bạn có thể sẽ quá tuần tự:
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
"thông minh" được thay thế bằng một vòng lặp for-loop tiêu chuẩn, nhàm chán và dễ đọc.
Viết thuộc tính tuỳ chỉnh Houdini
Sau đây là ví dụ về cách thiết lập thuộc tính tuỳ chỉnh (ví dụ: biến CSS), nhưng giờ đây, thuộc tính này có cú pháp (loại), giá trị ban đầu (phương thức dự phòng) và boolean kế thừa (có kế thừa giá trị từ thuộc tính mẹ hay không?). Cách hiện tại để thực hiện việc này là thông qua CSS.registerProperty()
trong JavaScript, nhưng trong Chromium 85 trở lên, cú pháp @property
sẽ được hỗ trợ trong các tệp CSS:
CSS.registerProperty({ name: '--colorPrimary', syntax: '' , initialValue: 'magenta', inherits: false });
@property --colorPrimary { syntax: '' ; initial-value: magenta; inherits: false; }
Giờ đây, bạn có thể truy cập vào --colorPrimary
như mọi thuộc tính tuỳ chỉnh CSS khác thông qua var(--colorPrimary)
. Tuy nhiên, điểm khác biệt ở đây là --colorPrimary
không chỉ được đọc dưới dạng chuỗi. Nó có dữ liệu!
CSS backdrop-filter
áp dụng một hoặc nhiều hiệu ứng cho một phần tử mờ hoặc trong suốt. Để hiểu điều đó, hãy xem xét các hình ảnh bên dưới.

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

.frosty-glass-pane { opacity: .9; backdrop-filter: blur(2px); }
Hình ảnh bên trái cho thấy cách các phần tử chồng chéo sẽ được kết xuất nếu không sử dụng hoặc không hỗ trợ backdrop-filter
. Hình ảnh ở bên phải áp dụng hiệu ứng làm mờ bằng backdrop-filter
. Lưu ý rằng lớp này sử dụng opacity
ngoài backdrop-filter
. Nếu không có opacity
, bạn sẽ không thể áp dụng hiệu ứng làm mờ. Hầu như không cần phải nói rằng nếu bạn đặt opacity
thành 1
(độ mờ hoàn toàn), thì nền sẽ không bị ảnh hưởng.
Tuy nhiên, không giống như sự kiện unload
, có những cách sử dụng hợp pháp cho beforeunload
. Ví dụ: khi bạn muốn cảnh báo người dùng rằng họ có các thay đổi chưa lưu và sẽ mất nếu rời khỏi trang. Trong trường hợp này, bạn chỉ nên thêm trình nghe beforeunload
khi người dùng có các thay đổi chưa lưu, sau đó xoá các trình nghe đó ngay sau khi lưu các thay đổi chưa lưu.
window.addEventListener('beforeunload', (event) => { if (pageHasUnsavedChanges()) { event.preventDefault(); return event.returnValue = 'Are you sure you want to exit?'; } });
beforeunload
một cách vô điều kiện.
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
khi cần (và xoá trình nghe đó khi không cần).
Hạn chế tối đa việc sử dụng Cache-Control: no-store
Cache-Control: no-store
là một tiêu đề HTTP mà máy chủ web có thể đặt trên các phản hồi hướng dẫn trình duyệt không lưu trữ phản hồi trong bất kỳ bộ nhớ đệm HTTP nào. Bạn nên sử dụng phương thức này cho các tài nguyên chứa thông tin nhạy cảm của người dùng, chẳng hạn như các trang sau khi đăng nhập.
Phần tử fieldset
chứa từng nhóm đầu vào (.fieldset-item
) đang sử dụng gap: 1px
để tạo đường viền mảnh giữa các phần tử. Không có giải pháp đường viền phức tạp!
.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); } } }
Tự xuống dòng theo lưới
Bố cục phức tạp nhất cuối cùng là bố cục vĩ mô, hệ thống bố cục logic giữa <main>
và <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>
Phần tử fieldset
chứa từng nhóm đầu vào (.fieldset-item
) đang sử dụng gap: 1px
để tạo đường viền mảnh giữa các phần tử. Không có giải pháp đường viền phức tạp!
.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); } } }
Bố cục <header>
của thẻ
Bố cục tiếp theo gần giống như vậy: Tôi sử dụng flex để tạo thứ tự dọc.
<snap-tabs> <header> <nav></nav> <span class="snap-indicator"></span> </header> <section></section> </snap-tabs>
header { display: flex; flex-direction: column; }
.snap-indicator
sẽ di chuyển theo chiều ngang với nhóm đường liên kết và bố cục tiêu đề này sẽ giúp thiết lập giai đoạn đó. Không có phần tử có vị trí tuyệt đối nào ở đây!
Gentle Flex là chiến lược chỉ căn giữa đúng nghĩa hơn. Cách này mềm mại và nhẹ nhàng, vì không giống như place-content: center
, không có kích thước hộp nào của phần tử con cháu thay đổi trong quá trình căn giữa. Tất cả các mục được xếp chồng, căn giữa và giãn cách một cách nhẹ nhàng nhất có thể.
.gentle-flex {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 1ch;
}
- Chỉ xử lý việc căn chỉnh, hướng và phân phối
- Tất cả nội dung chỉnh sửa và bảo trì đều ở cùng một nơi
- Gap đảm bảo khoảng cách bằng nhau giữa n phần tử con
- Hầu hết các dòng mã
Phù hợp với cả bố cục vĩ mô và vi mô.
Cách sử dụng
gap
chấp nhận mọi độ dài hoặc tỷ lệ phần trăm CSS làm giá trị.
.gap-example {
display: grid;
gap: 10px;
gap: 2ch;
gap: 5%;
gap: 1em;
gap: 3vmax;
}
Bạn có thể truyền 1 độ dài cho Gap. Độ dài này sẽ được dùng cho cả hàng và cột.
.grid { display: grid; gap: 10px; }
.grid { display: grid; row-gap: 10px; column-gap: 10px; }
Bạn có thể truyền 2 độ dài cho Gap, các độ dài này sẽ được dùng cho hàng và cột.
.grid { display: grid; gap: 10px 5%; }
.grid { display: grid; row-gap: 10px; column-gap: 5%; }