1. Trước khi bắt đầu

Ngày nay, người dùng đã chỉ định nhiều lựa chọn ưu tiên trên thiết bị của họ. Họ muốn hệ điều hành và ứng dụng có giao diện và trải nghiệm phù hợp với họ. Giao diện thích ứng với người dùng là giao diện sẵn sàng sử dụng các lựa chọn ưu tiên này để nâng cao trải nghiệm người dùng, giúp người dùng cảm thấy thoải mái hơn, như thể đó là giao diện của riêng họ. Nếu được thực hiện đúng cách, người dùng có thể không bao giờ biết trải nghiệm người dùng đang điều chỉnh hoặc đã điều chỉnh.
Lựa chọn ưu tiên của người dùng
Lựa chọn phần cứng thiết bị là một lựa chọn ưu tiên, hệ điều hành là một lựa chọn, màu sắc của ứng dụng và hệ điều hành là lựa chọn ưu tiên, còn ngôn ngữ của tài liệu trong ứng dụng và hệ điều hành là lựa chọn ưu tiên. Số lượng lựa chọn ưu tiên của người dùng dường như chỉ tăng lên. Trang web không thể truy cập vào mọi thứ và có lý do chính đáng.
Dưới đây là một vài ví dụ về lựa chọn ưu tiên của người dùng mà CSS có thể sử dụng:
- Kích thước khung nhìn của thiết bị
- Hướng thiết bị (dọc | ngang)
- Cỡ chữ
- Trực tuyến/ngoại tuyến
- Chất lượng mạng
- Bảng phối màu (sáng | tối)
- Ảnh động trên giao diện (bật | giảm)
- Chất lượng đầu vào (chuột | thao tác chạm | bút cảm ứng)
- Hướng tài liệu và chế độ viết (từ trái sang phải, từ trên xuống dưới, v.v.)
- Chế độ hiển thị (toàn màn hình | độc lập | giao diện người dùng tối giản | trình duyệt)
Dưới đây là một vài ví dụ về lựa chọn ưu tiên của người dùng sắp ra mắt trong CSS:
- Giảm dữ liệu/chế độ thu gọn
- Dải màu
- Độ tương phản (giảm | tăng | giảm)
- Màu sắc (buộc màu của người dùng vào trang)
- Độ trong suốt (bật | giảm)
Truy vấn đa phương tiện
CSS và web cho phép điều chỉnh và thích ứng thông qua truy vấn phương tiện, một điều kiện khai báo chứa một tập hợp các kiểu nếu điều kiện đó là đúng. Phổ biến nhất là điều kiện về kích thước khung nhìn của thiết bị: nếu kích thước nhỏ hơn 800 pixel, thì đây là một số kiểu phù hợp hơn cho trường hợp đó.
Thích ứng với người dùng
Giao diện không thích ứng là giao diện không thay đổi gì khi người dùng truy cập, về cơ bản là mang lại một trải nghiệm cho mọi người mà không có khả năng điều chỉnh. Giao diện thích ứng với người dùng có thể có 5 giao diện và kiểu khác nhau cho 5 người dùng khác nhau. Chức năng vẫn giữ nguyên, nhưng tính thẩm mỹ được cải thiện và khả năng hữu dụng của giao diện sẽ dễ dàng hơn cho những người dùng có thể điều chỉnh giao diện người dùng.
Điều kiện tiên quyết
- Kiến thức về HTML và CSS
- Kiến thức về các công cụ cho nhà phát triển, chẳng hạn như Công cụ cho nhà phát triển Google Chrome
Sản phẩm bạn sẽ tạo ra
Trong lớp học lập trình này, bạn sẽ xây dựng một biểu mẫu thích ứng với người dùng, có thể điều chỉnh theo những yếu tố sau:
- Lựa chọn ưu tiên về bảng màu của hệ thống bằng cách cung cấp bảng phối màu sáng và tối cho các thành phần điều khiển biểu mẫu và các phần tử trên giao diện người dùng xung quanh
- Lựa chọn ưu tiên về chuyển động của hệ thống bằng cách cung cấp nhiều loại ảnh động
- Khung nhìn thiết bị nhỏ và lớn để mang đến trải nghiệm trên thiết bị di động và máy tính
- Nhiều loại đầu vào như bàn phím, trình đọc màn hình, thao tác chạm và chuột
- Ngôn ngữ bất kỳ và chế độ đọc/ghi

Kiến thức bạn sẽ học được
Trong lớp học lập trình này, bạn sẽ tìm hiểu về các tính năng web hiện đại để giúp bạn xây dựng biểu mẫu thích ứng với người dùng. Bạn sẽ tìm hiểu cách:
- Tạo giao diện sáng và Giao diện tối
- Xây dựng biểu mẫu có ảnh động và dễ tiếp cận
- Biểu mẫu thích ứng Layout
- Sử dụng các đơn vị tương đối và thuộc tính logic

Lớp học lập trình này tập trung vào giao diện thích ứng với người dùng. Các khái niệm và khối mã không liên quan được tinh chỉnh và cung cấp cho bạn, chỉ cần sao chép và dán.
Bạn cần có
- Google Chrome 89 trở lên hoặc trình duyệt bạn muốn dùng

2. Bắt đầu thiết lập
Lấy mã nguồn
Mọi thứ bạn cần cho dự án này đều có trong kho lưu trữ GitHub. Để bắt đầu, bạn cần lấy mã và mở mã đó trong môi trường phát triển mà bạn muốn. Ngoài ra, bạn có thể phân nhánh Codepen này và làm việc từ đó.
Nên dùng: Codepen
- Mở một thẻ trình duyệt mới.
- Truy cập vào https://codepen.io/argyleink/pen/abBMeeq.
- Nếu bạn chưa có tài khoản, hãy tạo một tài khoản để lưu công việc.
- Nhấp vào Fork (Phân nhánh).
Cách khác: Làm việc trên máy cục bộ
Nếu muốn tải mã xuống và làm việc trên máy, bạn cần có Node.js phiên bản 12 trở lên và một trình soạn thảo mã đã được thiết lập và sẵn sàng hoạt động.
Sử dụng Git
- Truy cập https://github.com/argyleink/Google-IO-2021-Workshop_User-Adaptive-Interfaces
- Sao chép kho lưu trữ vào một thư mục.
- Lưu ý rằng nhánh mặc định là
beginning.
Sử dụng tệp
- Giải nén tệp zip đã tải xuống vào một thư mục.
Chạy dự án
Sử dụng thư mục dự án được thiết lập ở một trong các bước trên, sau đó:
- Chạy
npm installđể cài đặt các phần phụ thuộc cần thiết nhằm chạy máy chủ. - Chạy
npm startđể khởi động máy chủ trên cổng 3000. - Mở một thẻ trình duyệt mới.
- Truy cập vào http://localhost:3000.
Giới thiệu về HTML
Bài học này sẽ đề cập đến các khía cạnh của HTML dùng để hỗ trợ khả năng tương tác thích ứng với người dùng. Hội thảo này tập trung cụ thể vào CSS. Bạn nên xem lại đoạn mã HTML được cung cấp nếu mới bắt đầu tạo biểu mẫu hoặc trang web. Việc lựa chọn phần tử HTML có thể rất quan trọng khi nói đến khả năng hỗ trợ tiếp cận và bố cục.
Khi bạn đã sẵn sàng bắt đầu, đây là khung sườn mà bạn sẽ chuyển đổi thành trải nghiệm người dùng linh động và thích ứng.

3. Tương tác thích ứng
Nhánh Git: beginning
Khi kết thúc phần này, biểu mẫu cài đặt của bạn sẽ thích ứng với:
- Tay điều khiển trò chơi + bàn phím
- Chuột + cảm ứng
- Trình đọc màn hình hoặc công nghệ hỗ trợ tương tự
Thuộc tính cho HTML
HTML được cung cấp trong mã nguồn là một điểm khởi đầu tuyệt vời vì các phần tử ngữ nghĩa giúp nhóm, sắp xếp và gắn nhãn cho dữ liệu đầu vào của biểu mẫu đã được chọn.
Biểu mẫu thường là điểm tương tác chính của doanh nghiệp, vì vậy, điều quan trọng là biểu mẫu có thể thích ứng với nhiều loại dữ liệu đầu vào mà web có thể hỗ trợ. Ví dụ: có thể bạn cần có một biểu mẫu có thể sử dụng trên thiết bị di động bằng thao tác chạm. Trong phần này, trước khi bố cục và tạo kiểu, bạn cần đảm bảo khả năng hữu dụng của phương thức nhập thích ứng.
Nhóm dữ liệu đầu vào
Phần tử <fieldset> trong HTML dùng để nhóm các thông tin đầu vào và chế độ điều khiển tương tự nhau. Trong biểu mẫu, bạn có hai nhóm, một nhóm cho âm lượng và một nhóm cho thông báo. Điều này rất quan trọng đối với trải nghiệm người dùng, vì vậy, bạn có thể bỏ qua toàn bộ các phần.
Sắp xếp các phần tử
Thứ tự của các phần tử được cung cấp theo thứ tự logic. Điều này rất quan trọng đối với trải nghiệm người dùng, nhờ đó, thứ tự trải nghiệm hình ảnh sẽ giống hoặc tương tự nhau đối với tay điều khiển trò chơi, bàn phím hoặc công nghệ trình đọc màn hình.
Tương tác bằng bàn phím
Người dùng web đã quen với việc di chuyển qua các biểu mẫu bằng phím tab. May mắn là trình duyệt sẽ xử lý việc này nếu bạn cung cấp các phần tử HTML dự kiến. Khi bạn sử dụng các phần tử như <button>, <input>, <h2> và <label>, các phần tử này sẽ tự động trở thành đích đến của bàn phím hoặc trình đọc màn hình.

Video trên minh hoạ cách phím tab và các phím mũi tên có thể di chuyển qua giao diện và thực hiện thay đổi. Tuy nhiên, đường viền màu xanh dương lại rất hẹp xung quanh các phần tử đầu vào, hãy thêm các kiểu sau để tạo khoảng trống cho hoạt động tương tác này.
style.css
input {
outline-offset: 5px;
}
Những điều nên thử
- Xem xét các phần tử HTML được dùng trong
index.html. - Nhấp vào trang minh hoạ trong trình duyệt.
- Nhấn phím
tabvà phímshift+tabđể di chuyển tiêu điểm của phần tử qua biểu mẫu. - Sử dụng bàn phím để thay đổi giá trị của thanh trượt và hộp đánh dấu.
- Kết nối tay điều khiển trò chơi Bluetooth và di chuyển tiêu điểm của phần tử qua biểu mẫu.
Tương tác bằng chuột
Người dùng web đã quen với việc tương tác với biểu mẫu bằng chuột. Hãy thử dùng chuột trên biểu mẫu. Thanh trượt và hộp đánh dấu có hiệu quả, nhưng bạn có thể làm tốt hơn. Các hộp đánh dấu đó khá nhỏ để nhấp chuột.

Bạn có thấy hai tính năng trải nghiệm người dùng để kết nối nhãn và dữ liệu đầu vào không?
Tính năng đầu tiên là có các lựa chọn để tương tác và nhãn dễ nhắm mục tiêu bằng chuột hơn nhiều so với một hình vuông nhỏ.
Tính năng thứ hai là biết chính xác nhãn dành cho dữ liệu đầu vào nào. Nếu không có CSS, bạn sẽ khó xác định nhãn nào dành cho hộp đánh dấu nào, trừ phi bạn cung cấp một số thuộc tính.
Mối liên kết rõ ràng này cũng cải thiện trải nghiệm cho trình đọc màn hình, được đề cập trong phần tiếp theo.
Không liên kết: không có thuộc tính nào kết nối các phần tử
<input type="checkbox">
<label>...</label>
Liên kết: các thuộc tính kết nối các phần tử
<input type="checkbox" id="voice-notifications" name="voice-notifications">
<label for="voice-notifications">...</label>
HTML được cung cấp đã phân bổ tất cả dữ liệu đầu vào và nhãn. Bạn nên tìm hiểu thêm nếu đây là một khái niệm mới đối với bạn.
Những điều nên thử
- Di chuột qua một nhãn và chú ý đến phần đánh dấu của hộp đánh dấu.
- Kiểm tra phần tử nhãn bằng Công cụ cho nhà phát triển Chrome để hình dung diện tích bề mặt có thể nhấp vào để chọn hộp đánh dấu.
Tương tác với trình đọc màn hình
Công nghệ hỗ trợ có thể tương tác với biểu mẫu này và chỉ với một vài thuộc tính HTML, công nghệ này có thể giúp người dùng có trải nghiệm mượt mà hơn.

Đối với người dùng đang thao tác trên biểu mẫu hiện tại bằng trình đọc màn hình trong Chrome, có một điểm dừng không cần thiết ở phần tử <picture> (không dành riêng cho Chrome). Người dùng sử dụng trình đọc màn hình có thể là do họ bị khiếm thị, vì vậy, việc dừng lại ở một bức ảnh sẽ không giúp ích gì. Bạn có thể ẩn các phần tử khỏi trình đọc màn hình bằng một thuộc tính.
index.html
<picture aria-hidden="true">
Giờ đây, trình đọc màn hình sẽ bỏ qua phần tử chỉ mang tính hình ảnh.

Phần tử thanh trượt input[type="range"] có một thuộc tính ARIA đặc biệt: aria-labelledby="media-volume". Thao tác này cung cấp hướng dẫn đặc biệt để trình đọc màn hình sử dụng nhằm nâng cao trải nghiệm người dùng.
Những điều nên thử
- Sử dụng công nghệ trình đọc màn hình của hệ điều hành để di chuyển tiêu điểm qua biểu mẫu.
- Tải xuống và thử một số phần mềm trình đọc màn hình trên biểu mẫu.
4. Bố cục thích ứng (Adaptive Layouts)
Nhánh Git: layouts
Khi kết thúc phần này, trang cài đặt sẽ:
- Tạo hệ thống giãn cách bằng các thuộc tính tuỳ chỉnh và đơn vị tương đối của người dùng
- Viết CSS Grid để căn chỉnh và giãn cách linh hoạt, thích ứng
- Sử dụng thuộc tính logic cho bố cục thích ứng trên toàn cầu
- Viết truy vấn phương tiện để điều chỉnh giữa bố cục thu gọn và bố cục rộng rãi

Giãn cách
Chìa khoá để có một bố cục đẹp là một bảng màu giới hạn các lựa chọn về khoảng cách. Điều này giúp nội dung có được sự hài hoà và nhất quán tự nhiên.
Thuộc tính tuỳ chỉnh
Hội thảo này dựa trên một tập hợp gồm 7 kích thước thuộc tính tuỳ chỉnh.
- Đặt các dòng này ở đầu tệp
style.css:
style.css
:root {
--space-xxs: .25rem;
--space-xs: .5rem;
--space-sm: 1rem;
--space-md: 1.5rem;
--space-lg: 2rem;
--space-xl: 3rem;
--space-xxl: 6rem;
}
Cách đặt tên này gần giống với cách mọi người thường dùng để mô tả không gian. Bạn cũng chỉ sử dụng đơn vị rem để định cỡ toàn bộ đơn vị sao cho dễ đọc, thích ứng và phù hợp với lựa chọn ưu tiên của người dùng.
Kiểu trang
Tiếp theo, bạn cần đặt một số kiểu tài liệu, xoá lề khỏi các phần tử và đặt phông chữ thành sans-serif đẹp mắt.
- Thêm những người và ứng dụng sau vào
style.css:
style.css
* {
box-sizing: border-box;
margin: 0;
}
html {
block-size: 100%;
}
body {
min-block-size: 100%;
padding-block-start: var(--space-xs);
padding-block-end: var(--space-xs);
}
Đó là lần đầu tiên bạn sử dụng các thuộc tính tuỳ chỉnh về khoảng cách! Hành trình khám phá không gian của bạn bắt đầu từ đây.
Kiểu chữ
Phông chữ cho bố cục này có thể thích ứng. Từ khoá system-ui sẽ sử dụng bất kỳ phông chữ giao diện nào mà hệ điều hành của người dùng cho là tối ưu.
body {
font-family: system-ui, sans-serif;
}
h1,h2,h3 {
font-weight: 500;
}
small {
line-height: 1.5;
}
Kiểu cho h1, h2 và h3 là kiểu nhỏ và mang tính phong cách. Tuy nhiên, phần tử small cần thêm line-height khi văn bản xuống dòng tự động. Nếu không, các thành phần sẽ bị dồn lại quá nhiều.
Thuộc tính logic
Lưu ý rằng padding trên body đang sử dụng các thuộc tính logic (block-start, block-end) để chỉ định cạnh. Các thuộc tính logic sẽ được sử dụng rộng rãi trong phần còn lại của lớp học lập trình. Giống như đơn vị rem, các đơn vị này cũng thích ứng với người dùng. Bạn có thể dịch bố cục này sang một ngôn ngữ khác và đặt bố cục này theo hướng viết và hướng tài liệu tự nhiên mà người dùng quen thuộc trong ngôn ngữ mẹ đẻ của họ. Các thuộc tính logic hỗ trợ việc này chỉ bằng một định nghĩa về không gian, hướng hoặc căn chỉnh.

Lưới và flexbox đã liên quan đến luồng, nghĩa là các kiểu được viết cho một ngôn ngữ sẽ theo ngữ cảnh và được áp dụng phù hợp cho các ngôn ngữ khác. Hướng thích ứng; nội dung hiển thị theo hướng của tài liệu.
Thuộc tính logic giúp bạn tiếp cận nhiều người dùng hơn mà không cần viết nhiều kiểu.
Bố cục lưới CSS
Thuộc tính CSS grid là một công cụ bố cục mạnh mẽ với nhiều tính năng để xử lý các tác vụ phức tạp. Bạn sẽ xây dựng một vài bố cục lưới đơn giản và một bố cục phức tạp. Bạn cũng sẽ làm việc từ ngoài vào trong, từ bố cục vĩ mô đến bố cục vi mô. Các thuộc tính tuỳ chỉnh về khoảng cách sẽ trở nên quan trọng, không chỉ là giá trị khoảng đệm hoặc lề, mà còn là kích thước cột, bán kính đường viền, v.v.
Dưới đây là ảnh chụp màn hình của Chrome DevTools phủ lên từng bố cục lưới CSS cùng một lúc:

- Hãy làm theo hướng dẫn bằng cách thêm từng kiểu sau đây vào
style.css:
<main>
main {
display: grid;
gap: var(--space-xl);
place-content: center;
padding: var(--space-sm);
}
Theo mặc định, Grid sẽ đặt từng phần tử con vào hàng riêng, giúp bạn dễ dàng xếp chồng các phần tử. Ngoài ra, bạn còn có thể sử dụng gap. Trước đó, bạn đã đặt margin: 0 trên tất cả các phần tử bằng bộ chọn *. Điều này hiện rất quan trọng vì bạn sử dụng gap cho khoảng cách. Khoảng trống không chỉ là một nơi duy nhất để quản lý không gian trong vùng chứa, mà còn là luồng tương đối của vùng chứa đó.
<form>
form {
max-width: 89vw;
display: grid;
gap: var(--space-xl) var(--space-xxl);
align-items: flex-start;
grid-template-columns:
repeat(auto-fit, minmax(min(10ch, 100%), 35ch));
}
Đây là bố cục lưới phức tạp nhất của thiết kế, nhưng lại là khía cạnh thích ứng thú vị nhất:
max-widthcung cấp một giá trị cho thuật toán bố cục để sử dụng khi quyết định kích thước của nó.gapđang sử dụng các thuộc tính tuỳ chỉnh và truyền mộtrow-gapkhác vớicolumn-gap.align-itemsđược đặt thànhflex-startđể không kéo giãn chiều cao của mục.grid-template-columnscó một số cú pháp phức tạp, nhưng mục tiêu rất ngắn gọn; giữ cho các cột có chiều rộng35chvà không bao giờ nhỏ hơn10ch, đồng thời đặt mọi thứ vào các cột nếu có chỗ, nếu không thì các hàng sẽ phù hợp.
- Thử đổi kích thước trình duyệt. Hãy xem biểu mẫu thu gọn thành các hàng trong khung nhìn nhỏ, nhưng lại chuyển sang các cột mới nếu có chỗ, thích ứng mà không cần truy vấn đa phương tiện. Chiến lược này về kiểu thích ứng không có truy vấn đa phương tiện đặc biệt hữu ích cho các thành phần hoặc bố cục lấy nội dung làm trung tâm.
<section>
section {
display: grid;
gap: var(--space-md);
}
Mỗi phần phải là một lưới gồm các hàng có khoảng cách trung bình giữa các phần tử con.
<header>
header {
display: grid;
gap: var(--space-xxs);
}
Mỗi tiêu đề phải là một lưới các hàng có khoảng cách rất nhỏ giữa các phần tử con.
<fieldset>
fieldset {
padding: 0;
display: grid;
gap: 1px;
border-radius: var(--space-sm);
overflow: hidden;
}
Bố cục này chịu trách nhiệm tạo giao diện giống như thẻ và nhóm các dữ liệu đầu vào lại với nhau. overflow: hidden và gap: 1px sẽ trở nên rõ ràng khi bạn thêm màu trong phần tiếp theo.
.fieldset-item
.fieldset-item {
display: grid;
grid-template-columns: var(--space-lg) 1fr;
gap: var(--space-md);
padding: var(--space-sm) var(--space-md);
}
Bố cục này chịu trách nhiệm căn giữa biểu tượng và hộp đánh dấu bằng các nhãn và chế độ điều khiển liên quan. Cột đầu tiên của mẫu lưới, var(--space-lg), tạo một cột rộng hơn biểu tượng, vì vậy, phần tử con có một vị trí để căn giữa.
Bố cục này minh hoạ số lượng quyết định thiết kế đã được đưa ra trong các thuộc tính tuỳ chỉnh. Khoảng đệm, khoảng trống và cột đều được định cỡ hài hoà với hệ thống bằng cách sử dụng các giá trị mà bạn đã xác định.
.fieldset-item <picture>
.fieldset-item > picture {
block-size: var(--space-xl);
inline-size: var(--space-xl);
clip-path: circle(50%);
display: inline-grid;
place-content: center;
}
Bố cục này chịu trách nhiệm về các chế độ cài đặt, kích thước của vòng tròn biểu tượng, tạo hình dạng vòng tròn và căn giữa hình ảnh trong đó.
<picture> và [checkbox] căn chỉnh
.fieldset-item > :is(picture, input[type="checkbox"]) {
place-self: center;
}
Bố cục này tách biệt việc căn giữa với các phần tử hình ảnh và hộp đánh dấu bằng cách sử dụng bộ chọn giả :is.
- Thay thế bộ chọn
picture > svgbằng.fieldset-item svgnhư sau:
.fieldset-item <svg>
.fieldset-item svg {
block-size: var(--space-md);
}
Thao tác này sẽ đặt kích thước biểu tượng svg thành một giá trị trong hệ thống kích thước.
.sm-stack
.sm-stack {
display: grid;
gap: var(--space-xs);
}
Lớp tiện ích này dành cho các phần tử nhãn hộp đánh dấu để tạo khoảng cách cho văn bản trợ giúp của hộp đánh dấu.
input[type="checkbox"]
input[type="checkbox"] {
inline-size: var(--space-sm);
block-size: var(--space-sm);
}
Các kiểu này tăng kích thước của hộp đánh dấu bằng cách sử dụng các giá trị trong tập hợp khoảng cách.
Những điều nên thử
- Mở Công cụ cho nhà phát triển Chrome và tìm huy hiệu Lưới trên HTML trong bảng điều khiển Elements (Phần tử). Nhấp vào các nút này để bật công cụ gỡ lỗi.
- Mở Công cụ cho nhà phát triển Chrome rồi di chuột qua một khoảng trống trong ngăn Kiểu.
- Mở Công cụ cho nhà phát triển Chrome, chuyển đến ngăn Styles (Kiểu) rồi chuyển từ Styles (Kiểu) sang Layouts (Bố cục). Khám phá khu vực này bằng cách bật/tắt các chế độ cài đặt và bật bố cục.
Truy vấn đa phương tiện
CSS sau đây điều chỉnh kiểu dựa trên kích thước và hướng của khung nhìn, nhằm điều chỉnh khoảng cách hoặc cách sắp xếp sao cho tối ưu dựa trên bối cảnh của khung nhìn.
<main>
@media (min-width: 540px) {
main {
padding: var(--space-lg);
}
}
@media (min-width: 800px) {
main {
padding: var(--space-xl);
}
}
Hai truy vấn đa phương tiện này cung cấp cho main nhiều khoảng đệm hơn khi có nhiều không gian khung nhìn hơn. Điều này có nghĩa là ban đầu, thành phần này có khoảng đệm nhỏ, gọn, nhưng giờ đây sẽ ngày càng rộng rãi hơn khi có thêm không gian.
<form>
form {
--repeat: auto-fit;
grid-template-columns:
repeat(var(--repeat), minmax(min(10ch, 100%), 35ch));
}
@media (orientation: landscape) and (min-width: 640px) {
form {
--repeat: 2;
}
}
Biểu mẫu đã thích ứng với kích thước khung nhìn bằng auto-fit, nhưng khi thử nghiệm trên thiết bị di động, việc xoay thiết bị sang ngang không đặt hai nhóm biểu mẫu cạnh nhau. Điều chỉnh cho phù hợp với bối cảnh ngang này bằng truy vấn nội dung nghe nhìn orientation và kiểm tra chiều rộng khung nhìn. Bây giờ, nếu thiết bị ở chế độ ngang và rộng ít nhất 640 pixel, hãy buộc hai cột bằng cách chuyển thuộc tính tuỳ chỉnh --repeat thành một số thay vì từ khoá auto-fit.
.fieldset-item
@media (min-width: 540px) {
.fieldset-item {
grid-template-columns: var(--space-xxl) 1fr;
gap: var(--space-xs);
padding: var(--space-md) var(--space-xl) var(--space-md) 0;
}
}
Truy vấn đa phương tiện này là một cách mở rộng khoảng cách khác khi có thêm không gian khung nhìn. Mẫu lưới mở rộng cột đầu tiên bằng cách sử dụng thuộc tính tuỳ chỉnh lớn hơn (var(--space-xxl)) trong mẫu. Khoảng đệm cũng được tăng lên cho các thuộc tính tuỳ chỉnh lớn hơn.
Những điều nên thử
- Mở rộng và thu nhỏ trình duyệt, đồng thời xem không gian điều chỉnh.
- Xem trước trên thiết bị di động
- Xem trước trên thiết bị di động ở chế độ ngang
5. Màu thích ứng
Nhánh Git: colors
Khi kết thúc phần này, biểu mẫu cài đặt của bạn sẽ:
- Thích ứng với lựa chọn ưu tiên về màu tối và sáng
- Có bảng phối màu bắt nguồn từ mã màu thập lục phân của thương hiệu
- Có màu sắc dễ tiếp cận

HSL
Trong phần tiếp theo, bạn sẽ tạo một hệ thống màu bằng HSL để giúp bạn tạo giao diện sáng và Giao diện tối. Nó được xây dựng dựa trên khái niệm cốt lõi này trong CSS: calc().
HSL là viết tắt của sắc độ, độ rực màu và độ sáng. Sắc độ là một góc, giống như một điểm trên đồng hồ, còn độ bão hoà và độ sáng là tỷ lệ phần trăm. calc() có thể tính toán tỷ lệ phần trăm và góc. Bạn có thể thực hiện các phép tính độ sáng và độ bão hoà trên các tỷ lệ phần trăm đó trong CSS. Kết hợp các phép tính kênh màu với các thuộc tính tuỳ chỉnh, bạn sẽ có một bảng phối màu hiện đại, linh động, trong đó các biến thể được tính toán từ một màu cơ bản, giúp bạn tránh phải quản lý nhiều màu trong mã.

Thuộc tính tuỳ chỉnh
Trong phần này, bạn sẽ tạo một tập hợp các thuộc tính tuỳ chỉnh để sử dụng trong các kiểu còn lại. Tương tự như bộ giãn cách bạn đã tạo trước đó trong thẻ :root, bạn sẽ thêm màu sắc.
Giả sử màu thương hiệu cho ứng dụng của bạn là #0af. Nhiệm vụ đầu tiên của bạn là chuyển đổi giá trị mã màu hex này thành giá trị màu HSL: hsl(200 100% 50%). Phép chuyển đổi này cho biết các kênh màu của thương hiệu theo HSL, nhờ đó bạn có thể sử dụng calc() để tính toán nhiều màu sắc hỗ trợ cho thương hiệu.
Bạn nên thêm từng khối mã sau đây trong phần này vào cùng một bộ chọn :root.
Kênh thương hiệu
:root {
--hue: 200;
--saturation: 100%;
--lightness: 50%;
}
Ba kênh HSL đã được trích xuất và đặt vào các thuộc tính tuỳ chỉnh riêng.
- Sử dụng cả ba thuộc tính như hiện tại và tạo lại màu thương hiệu.
Thương hiệu
:root {
--brand: hsl(
var(--hue)
calc(var(--saturation) / 2)
var(--lightness)
);
}
Vì bảng phối màu của bạn là tối theo mặc định, nên bạn nên giảm độ bão hoà màu để sử dụng trên các nền tối (nếu không, chúng có thể gây mỏi mắt hoặc không thể truy cập được). Để giảm độ bão hoà của màu thương hiệu, bạn sử dụng sắc độ và độ sáng như hiện tại, nhưng giảm một nửa độ bão hoà bằng một số phép chia: calc(var(--saturation) / 2). Giờ đây, màu thương hiệu của bạn đã phù hợp với giao diện, nhưng đã được khử bão hoà để sử dụng.
Văn bản
:root {
--text1: hsl(var(--hue) 15% 85%);
--text2: hsl(var(--hue) 15% 65%);
}
Đối với văn bản đọc trong giao diện tối, bạn sử dụng sắc độ của thương hiệu làm màu cơ bản, nhưng tạo ra các màu gần như trắng từ sắc độ đó. Nhiều người dùng sẽ nghĩ văn bản có màu trắng, trong khi thực tế văn bản có màu xanh dương rất nhạt. Việc giữ nguyên sắc độ là một cách hiệu quả để tạo ra sự hài hoà trong thiết kế. --text1 có 85% màu trắng và --text2 có 65% màu trắng, cả hai đều có độ bão hoà rất thấp.
- Sau khi thêm mã vào dự án, hãy mở Công cụ cho nhà phát triển Chrome và khám phá cách thay đổi các giá trị kênh này. Cảm nhận cách HSL và các kênh của nó tương tác với nhau. Có thể bạn muốn độ bão hoà cao hơn hoặc thấp hơn.
Surface
:root {
--surface1: hsl(var(--hue) 10% 10%);
--surface2: hsl(var(--hue) 10% 15%);
--surface3: hsl(var(--hue) 5% 20%);
--surface4: hsl(var(--hue) 5% 25%);
}
Văn bản có màu rất sáng vì các nền tảng sẽ có màu tối trong chế độ tối. Khi màu văn bản sử dụng giá trị độ sáng cao (85% trở lên), các nền tảng sẽ sử dụng giá trị thấp hơn (30% trở xuống). Việc có khoảng cách phù hợp giữa các dải độ sáng giữa nền và văn bản sẽ giúp đảm bảo màu sắc dễ tiếp cận để người dùng đọc.
- Hãy lưu ý cách màu sắc bắt đầu ở màu xám đậm nhất với độ sáng 10% và độ bão hoà 10%, sau đó giảm độ bão hoà khi màu sắc trở nên sáng hơn. Mỗi bề mặt mới nhẹ hơn 5% so với bề mặt trước đó. Độ bão hoà cũng giảm một chút ở các bề mặt sáng hơn. Hãy thử đặt độ bão hoà của tất cả các bề mặt thành 10%. Bạn thích hay không thích?
Giao diện sáng
Sau khi có một bộ màu văn bản và màu nền phù hợp cho giao diện tối, bạn cần điều chỉnh cho phù hợp với lựa chọn ưu tiên về giao diện sáng bằng cách cập nhật các thuộc tính tuỳ chỉnh màu trong truy vấn đa phương tiện prefers-color-scheme.
Bạn sẽ sử dụng cùng một kỹ thuật để duy trì sự khác biệt lớn về giá trị độ sáng giữa màu nền và màu văn bản để giữ cho màu sắc tương phản tốt.
Thương hiệu
@media (prefers-color-scheme: light) {
:root {
--brand: hsl(
var(--hue)
var(--saturation)
var(--lightness)
);
}
}
Đầu tiên là màu sắc của thương hiệu. Cần khôi phục độ bão hoà về mức tối đa.
Văn bản
@media (prefers-color-scheme: light) {
:root {
--text1: hsl(
var(--hue)
var(--saturation)
10%
);
--text2: hsl(
var(--hue)
calc(var(--saturation) / 2)
30%
);
}
}
Tương tự như cách giao diện tối có màu văn bản xanh dương rất nhạt, trong giao diện sáng, màu văn bản là màu xanh dương rất đậm. Khi thấy 10% và 30% là giá trị độ sáng cho màu HSL, bạn sẽ biết rằng đây là những màu tối.
Surface
@media (prefers-color-scheme: light) {
:root {
--surface1: hsl(var(--hue) 20% 90%);
--surface2: hsl(var(--hue) 10% 99%);
--surface3: hsl(var(--hue) 10% 96%);
--surface4: hsl(var(--hue) 10% 85%);
}
}
Những màu nền này là những màu đầu tiên phá vỡ các mẫu. Những gì có vẻ khá hợp lý và tuyến tính cho đến nay giờ đã bị phá vỡ. Điều thú vị là bạn có thể thử nghiệm các tổ hợp màu giao diện sáng HSL ngay tại đây trong mã, đồng thời điều chỉnh độ sáng và độ bão hoà để tạo ra một bảng phối màu sáng đẹp mắt, không quá lạnh hoặc quá xanh.
Sử dụng hệ thống màu
Giờ đây, khi đã xác định được màu sắc, bạn có thể sử dụng chúng. Bạn có một màu nhấn nổi bật cho thương hiệu, hai màu văn bản và bốn màu nền.
- Đối với các phần mã sau, hãy tìm bộ chọn phù hợp và thêm CSS màu vào khối mã hiện có.
<body>
body {
background: var(--surface1);
color: var(--text1);
}
Màu chính của trang là màu nền và màu văn bản đầu tiên bạn tạo, đồng thời cũng đặt độ tương phản mặc định ở mức tối đa. Bạn có thể bắt đầu thử nghiệm tính năng bật/tắt chế độ sáng và tối!
<fieldset>
fieldset {
border: 1px solid var(--surface4);
background: var(--surface4);
}
Đây là phần tử giống như thẻ trong thiết kế của bạn. Đường viền 1 pixel và khoảng trống 1 pixel có cùng màu và đại diện cho bề mặt phía sau mỗi .fieldset-item. Điều này tạo ra sự hài hoà về hình ảnh và dễ duy trì.
.fieldset-item
.fieldset-item {
background: var(--surface3);
}
Mỗi dữ liệu đầu vào của biểu mẫu đều nằm trên một nền tảng riêng. Hy vọng bạn thấy được cách các màu này kết hợp với nhau và cách các biến thể độ sáng xếp lớp với nhau.
.fieldset-item > picture
.fieldset-item > picture {
background: var(--surface4);
}
Đây là một lựa chọn về kiểu dáng để thể hiện hình tròn bao quanh biểu tượng. Lý do sẽ trở nên rõ ràng khi bạn thêm các lượt tương tác trong phần tiếp theo.
.fieldset-item svg
.fieldset-item svg {
fill: var(--text2);
}
Các biểu tượng trong biểu mẫu được đặt để sử dụng văn bản thay thế --text2. Thiết kế có biểu tượng được tô màu nền sáng hơn một chút so với văn bản sẽ giúp biểu tượng không bị quá đậm.
.fieldset-item:focus-within svg
.fieldset-item:focus-within svg {
fill: var(--brand);
}
Bộ chọn này khớp với phần tử vùng chứa dữ liệu đầu vào khi một trong các dữ liệu đầu vào bên trong đang được tương tác và nhắm mục tiêu SVG để làm nổi bật dữ liệu đó bằng màu nhấn thương hiệu của bạn. Điều này mang lại trải nghiệm người dùng tốt cho biểu mẫu, trong đó việc tương tác với dữ liệu đầu vào sẽ làm nổi bật biểu tượng liên quan.
<small>
small {
color: var(--text2);
}
Đó là chữ nhỏ. Nội dung này nên được làm mờ đi một chút so với tiêu đề và đoạn văn (nội dung chính).
Chế độ tối cho các thành phần điều khiển biểu mẫu
:root {
color-scheme: dark light;
}
Bước hoàn thiện này cho trình duyệt biết rằng trang này hỗ trợ cả giao diện tối và sáng. Trình duyệt sẽ thưởng cho chúng ta bằng các chế độ điều khiển biểu mẫu tối.
6. Ảnh động thích ứng
Nhánh Git: animations
Khi kết thúc phần này, trang cài đặt sẽ:
- Điều chỉnh theo lựa chọn ưu tiên về chuyển động của người dùng
- Phản hồi hoạt động tương tác của người dùng

Giảm chuyển động so với không chuyển động
Lựa chọn ưu tiên của người dùng về chuyển động trong hệ điều hành không cung cấp giá trị không có ảnh động. Lựa chọn này là giảm chuyển động. Ảnh động mờ dần, chuyển đổi màu sắc và nhiều hiệu ứng khác vẫn là lựa chọn phù hợp cho những người dùng thích giảm chuyển động.
Trong trang cài đặt này, không có nhiều chuyển động trên màn hình. Chuyển động này giống như hiệu ứng điều chỉnh tỷ lệ, như thể phần tử đang di chuyển về phía người dùng. Việc điều chỉnh mã CSS để phù hợp với chế độ giảm chuyển động là rất đơn giản, bạn chỉ cần giảm hiệu ứng chuyển đổi tỷ lệ.
Kiểu tương tác
<fieldset>
fieldset {
transition: box-shadow .3s ease;
}
fieldset:focus-within {
box-shadow: 0 5px 20px -10px hsl(0 0% 0% / 50%);
}
Khi người dùng tương tác với dữ liệu đầu vào của một trong các phần tử giống như thẻ <fieldset>, hiệu ứng nâng sẽ được thêm vào. Giao diện đang đẩy một phần tử về phía trước, giúp người dùng tập trung khi nhóm biểu mẫu theo bối cảnh được đưa về phía người dùng.
.fieldset-item
.fieldset-item {
transition: background .2s ease;
}
.fieldset-item:focus-within {
background: var(--surface2);
}
Khi người dùng tương tác với một mục nhập, nền của lớp mục cụ thể sẽ thay đổi thành màu nền được làm nổi bật. Đây là một tính năng giao diện hỗ trợ khác giúp thu hút sự chú ý của người dùng và báo hiệu rằng mục nhập đang được nhận. Trong hầu hết các trường hợp, bạn không cần phải giảm hiệu ứng chuyển màu.
.fieldset-item > picture
@media (prefers-reduced-motion: no-preference) {
.fieldset-item > picture {
clip-path: circle(40%);
transition: clip-path .3s ease;
}
.fieldset-item:focus-within picture {
clip-path: circle(50%);
}
}
Dưới đây là ảnh động clip-path mà bạn chỉ sử dụng nếu người dùng không có lựa chọn ưu tiên nào về việc giảm chuyển động. Bộ chọn và kiểu đầu tiên thu hẹp đường dẫn của đoạn video hình tròn 10% và đặt một số tham số chuyển đổi. Bộ chọn và kiểu thứ hai chờ người dùng tương tác với một dữ liệu đầu vào, sau đó tăng tỷ lệ vòng tròn của biểu tượng. Một hiệu ứng tinh tế nhưng gọn gàng khi mọi thứ đều ổn.
7. Xin chúc mừng
Nhánh Git: complete
Xin chúc mừng, bạn đã tạo thành công một giao diện thích ứng với người dùng!
Giờ đây, bạn đã biết các bước quan trọng cần thiết để tạo giao diện thích ứng với nhiều tình huống và chế độ cài đặt của người dùng.