Trước đây, việc tuỳ chỉnh các phần tử biểu mẫu HTML chuẩn như hộp đánh dấu và nút chọn thường rất khó khăn. Nhà phát triển thường phải lựa chọn giữa việc sử dụng chế độ mặc định của trình duyệt hoặc xây dựng các thành phần tuỳ chỉnh từ đầu. Việc tạo các thành phần điều khiển tuỳ chỉnh tốn nhiều thời gian và có thể dễ dàng dẫn đến các vấn đề về hỗ trợ tiếp cận hoặc thiếu trạng thái (chẳng hạn như trạng thái không xác định cho hộp đánh dấu).
Thuộc tính CSS accent-color cung cấp một cách đơn giản để đưa màu thương hiệu của bạn vào dữ liệu đầu vào biểu mẫu HTML tích hợp sẵn bằng một dòng CSS duy nhất mà không làm mất khả năng hỗ trợ tiếp cận hoặc các tính năng tích hợp sẵn của trình duyệt.
Cách triển khai
Cách áp dụng màu thương hiệu cho các thành phần điều khiển biểu mẫu:
- Xác định màu sắc thương hiệu: Chọn một màu sắc đại diện cho thương hiệu của bạn.
- Áp dụng thuộc tính
accent-color: Thêmaccent-colorvào phần tử hoặc phần tử vùng chứa (nhưbodyhoặc một biểu mẫu cụ thể) trong CSS. - Hỗ trợ Chế độ tối (Không bắt buộc nhưng nên dùng): Sử dụng
color-schemeđể cho trình duyệt biết trang web của bạn hỗ trợ chế độ tối và điều chỉnhaccent-colornếu cần để có độ tương phản tốt hơn.
Mã ví dụ: Các chế độ kiểm soát biểu mẫu nhất quán với thương hiệu
:root {
--brand-color: #6200ee;
}
/* Apply accent-color to the body or a specific container */
body {
accent-color: var(--brand-color);
}
/* Optional: Adjust for dark mode if needed */
@media (prefers-color-scheme: dark) {
:root {
--brand-color: #bb86fc; /* A lighter shade for dark mode */
}
}
<form>
<!-- Checkbox -->
<label for="subscribe">
<input type="checkbox" id="subscribe" checked>
Subscribe to newsletter
</label>
<!-- Radio Buttons -->
<label for="plan-monthly">
<input type="radio" id="plan-monthly" name="plan" value="monthly">
Monthly
</label>
<label for="plan-yearly">
<input type="radio" id="plan-yearly" name="plan" value="yearly" checked>
Yearly
</label>
<!-- Range Slider -->
<label for="volume">Volume:</label>
<input type="range" id="volume" min="0" max="100" value="70">
<!-- Progress Bar -->
<label for="file">Upload Progress:</label>
<progress id="file" max="100" value="70">70%</progress>
</form>
Triển khai chiến lược và các phương pháp hay nhất
- NÊN sử dụng
accent-colorđể dễ dàng tạo giao diện cho các thành phần điều khiển biểu mẫu sao cho phù hợp với thương hiệu của bạn. - KHÔNG tin tưởng hoàn toàn vào trình duyệt để xử lý độ tương phản. Mặc dù các trình duyệt được cho là tự động xác định màu tương phản phù hợp, nhưng các lỗi đã biết trong quá trình triển khai như Safari (lỗi WebKit 244233) và Android Chrome (lỗi Chromium 343503163) có thể không đảo ngược được màu của dấu kiểm, dẫn đến các chế độ điều khiển không hiển thị hoặc khó nhìn thấy khi sử dụng màu không có đủ độ tương phản so với nền (ví dụ: màu sáng ở chế độ sáng hoặc màu tối ở chế độ tối).
- NÊN kết hợp
accent-colorvớicolor-scheme: light darkđể đảm bảo các thành phần điều khiển biểu mẫu trông đẹp mắt ở cả giao diện sáng và Giao diện tối. - KHÔNG sử dụng màu quá gần với màu nền, mặc dù các trình duyệt cố gắng đảm bảo độ tương phản, nhưng tốt nhất là bạn nên cung cấp màu có độ tương phản cơ bản tốt.
- KHÔNG giả định rằng
accent-colorhoạt động trên tất cả các phần tử biểu mẫu. Hiện tại, thuộc tính này chỉ phủ màu cho các phần tửcheckbox,radio,rangevàprogress.
Chiến lược dự phòng
Đối với các trình duyệt không hỗ trợ accent-color, các chế độ điều khiển biểu mẫu sẽ quay lại giao diện mặc định của trình duyệt. Để đảm bảo tính nhất quán hoàn toàn về thương hiệu và độ tin cậy cao trên mọi môi trường, bạn PHẢI triển khai chiến lược dự phòng tuỳ chỉnh bằng kỹ thuật "đầu vào ẩn trực quan" đã thiết lập.
Cải tiến tăng dần bằng @supports not
Bạn PHẢI sử dụng quy tắc @supports not để chỉ áp dụng kiểu dự phòng tuỳ chỉnh khi không hỗ trợ accent-color. Điều này đảm bảo bạn tận dụng được tính đơn giản của accent-color cho các trình duyệt hiện đại, đồng thời đảm bảo trải nghiệm nhất quán về thương hiệu cho các trình duyệt cũ.
1. Cấu trúc HTML
Đảm bảo nhãn của bạn gói văn bản trong <span> để cho phép các bộ chọn đồng cấp trong CSS:
<label for="subscribe-fallback">
<input type="checkbox" id="subscribe-fallback" class="visually-hidden" checked>
<span>Subscribe to newsletter</span>
</label>
2. Dự phòng CSS
Áp dụng kiểu tuỳ chỉnh trong khối @supports not:
/* Fallback for older browsers without accent-color */
@supports not (accent-color: var(--brand-color)) {
/* Visually hide the native input using the canonical accessible recipe */
form input[type="checkbox"].visually-hidden {
position: absolute !important;
clip-path: inset(50%) !important;
overflow: hidden !important;
width: 1px !important;
height: 1px !important;
margin: -1px !important;
padding: 0 !important;
border: 0 !important;
white-space: nowrap !important;
}
/* Style the wrapper label */
label {
position: relative;
padding-left: 2rem;
cursor: pointer;
display: inline-flex;
align-items: center;
}
/* Custom box for checkbox */
input[type="checkbox"] + span::before {
content: "";
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
width: 1.2rem;
height: 1.2rem;
border: 2px solid #ccc;
background: white;
border-radius: 4px;
box-sizing: border-box;
transition: all 0.2s ease;
}
/* Ensure custom checkbox shows focus for keyboard users */
input[type="checkbox"]:focus-visible + span::before {
outline: 2px solid #000;
outline-offset: 2px;
}
/* Checked State */
input[type="checkbox"]:checked + span::before {
background-color: var(--brand-color, #6200ee);
border-color: var(--brand-color, #6200ee);
}
/* Checkmark (Unicode) */
input[type="checkbox"]:checked + span::after {
content: "✓";
position: absolute;
left: 0.25rem;
top: 50%;
transform: translateY(-50%);
color: white;
font-weight: bold;
font-size: 0.9rem;
}
/* Fallback for Range Slider */
input[type="range"] {
-webkit-appearance: none;
appearance: none;
background: transparent;
}
/* Webkit (Chrome, Safari, Edge) */
input[type="range"]::-webkit-slider-runnable-track {
width: 100%;
height: 8px;
/* Use gradient to show progress for a static value (e.g., 70%) or update with JS */
background: linear-gradient(to right, var(--brand-color, #6200ee) 70%, #ccc 70%);
border-radius: 4px;
}
input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
height: 16px;
width: 16px;
border-radius: 50%;
background: var(--brand-color, #6200ee);
cursor: pointer;
margin-top: -4px; /* Center vertically */
}
/* Firefox */
input[type="range"]::-moz-range-track {
width: 100%;
height: 8px;
background: #ccc;
border-radius: 4px;
}
input[type="range"]::-moz-range-thumb {
height: 16px;
width: 16px;
border-radius: 50%;
background: var(--brand-color, #6200ee);
cursor: pointer;
}
/* Firefox specific progress bar */
input[type="range"]::-moz-range-progress {
background-color: var(--brand-color, #6200ee);
height: 8px;
border-radius: 4px;
}
/* Fallback for Progress Bar */
progress {
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
border: none;
background: #ccc;
height: 8px;
border-radius: 4px;
}
progress::-webkit-progress-bar {
background-color: #ccc;
border-radius: 4px;
}
progress::-webkit-progress-value {
background-color: var(--brand-color, #6200ee);
border-radius: 4px;
}
progress::-moz-progress-bar {
background-color: var(--brand-color, #6200ee);
border-radius: 4px;
}
}
Tiến trình dải động trong Webkit Fallback
Để thanh tiến trình di chuyển cùng với nút kéo trên thanh trượt dải ô trong trình duyệt Webkit (không có accent-color), bạn có thể sử dụng một biến CSS và một lượng nhỏ JavaScript.
Cập nhật CSS: Sử dụng biến CSS cho điểm dừng chuyển màu:
input[type="range"]::-webkit-slider-runnable-track { background: linear-gradient(to right, var(--brand-color) var(--progress, 0%), #ccc var(--progress, 0%)); }Thêm JavaScript: Cập nhật biến trong sự kiện
input:
if (!CSS.supports('accent-color')) {
const slider = document.getElementById('volume');
slider.addEventListener('input', (e) => {
e.target.style.setProperty('--progress', `${e.target.value}%`);
});
}