Giới thiệu
Trong nhiều năm qua, việc thay đổi giữa chế độ sáng và tối là đỉnh cao của việc tạo chủ đề thân thiện với người dùng. Tuy nhiên, thiết kế web hiện đại yêu cầu nhiều hơn thế. Người dùng mong đợi những giao diện có khả năng thích ứng không chỉ với sở thích hệ thống của họ mà còn với những sở thích cá nhân—cho dù đó là tông màu xanh dịu, chủ đề độ tương phản cao cho khả năng tiếp cận, hay thậm chí là màu sắc thương hiệu yêu thích của họ.
Chìa khóa để xây dựng những chủ đề động, có thể tùy chỉnh bởi người dùng nằm ở một tính năng CSS hiện đại mạnh mẽ: CSS Custom Properties (còn được gọi là CSS Variables). Bài viết này sẽ hướng dẫn bạn vượt ra ngoài một công tắc nhị phân đơn giản để triển khai một hệ thống chủ đề đa dạng và mạnh mẽ.
Tại sao CSS Custom Properties hoàn hảo cho việc tạo chủ đề?
Khác với các biến trong preprocessor (như SASS hoặc LESS) được biên dịch thành mã tĩnh, CSS Custom Properties là các biến sống trong trình duyệt. Điều này có nghĩa là giá trị của chúng có thể được cập nhật động tại thời gian chạy bằng JavaScript, khiến chúng trở thành nền tảng lý tưởng cho bất kỳ chức năng chuyển đổi chủ đề nào.
Lợi ích chính bao gồm:
- Cập nhật động: Thay đổi giá trị của một biến và sự thay đổi sẽ lập tức lan tỏa đến tất cả các phần tử sử dụng nó.
- Phạm vi: Các biến có thể được định nghĩa toàn cầu hoặc chỉ trong các thành phần cụ thể, cho phép hệ thống thiết kế tinh vi hơn.
- Thứ tự và Kế thừa: Chúng tuân theo các quy tắc giống như các thuộc tính CSS khác, cung cấp cách quản lý phong cách dự đoán và mạnh mẽ.
Bước 1: Định nghĩa bảng màu chủ đề của bạn với Custom Properties
Bước đầu tiên là từ bỏ các giá trị màu cố định. Thay vì viết color: #333; ở mọi nơi, chúng ta định nghĩa một tập hợp các biến ngữ nghĩa đại diện cho mục đích của một màu.
Chúng ta thường định nghĩa các biến này trên phần tử :root để làm cho chúng có sẵn toàn cầu.
css
:root {
/* Màu chính */
--color-primary: 56, 73, 214; /* Định dạng RGB để linh hoạt với kênh alpha */
--color-secondary: 255, 196, 0;
/* Màu trung tính */
--color-background: 253, 253, 253;
--color-surface: 255, 255, 255;
--color-text: 10, 10, 10;
--color-text-muted: 115, 115, 115;
/* Khoảng cách và các token khác */
--border-radius: 0.75rem;
--spacing-unit: 1rem;
}
Để sử dụng các biến này, chúng ta sử dụng hàm var(). Lưu ý cách chúng ta sử dụng các giá trị RGB; điều này cho phép chúng ta dễ dàng kiểm soát độ mờ với rgba().
css
body {
background-color: rgb(var(--color-background));
color: rgb(var(--color-text));
font-family: sans-serif;
padding: var(--spacing-unit);
}
.card {
background-color: rgb(var(--color-surface));
padding: calc(var(--spacing-unit) * 2);
border-radius: var(--border-radius);
border: 1px solid rgba(var(--color-text), 0.1);
}
.button {
background-color: rgba(var(--color-primary), 1);
color: white;
padding: 0.5rem 1rem;
border: none;
border-radius: var(--border-radius);
cursor: pointer;
}
.button:hover {
background-color: rgba(var(--color-primary), 0.8);
}
Bước 2: Tạo nhiều định nghĩa chủ đề
Một công tắc chế độ sáng/tối đơn giản chỉ là một trường hợp đặc biệt của hệ thống này. Chúng ta có thể định nghĩa nhiều chủ đề bằng cách ghi đè giá trị biến trong một lớp hoặc bộ chọn thuộc tính.
Phương pháp 1: Sử dụng một lớp (ví dụ: .theme-dark)
css
/* Chủ đề mặc định là chủ đề sáng (được định nghĩa trong :root) */
:root {
--color-primary: 56, 73, 214;
--color-background: 253, 253, 253;
--color-surface: 255, 255, 255;
--color-text: 10, 10, 10;
}
/* Chủ đề tối */
.theme-dark {
--color-background: 10, 10, 20;
--color-surface: 30, 30, 45;
--color-text: 245, 245, 245;
}
/* Chủ đề độ tương phản cao */
.theme-high-contrast {
--color-background: 255, 255, 255;
--color-surface: 255, 255, 255;
--color-text: 0, 0, 0;
--color-primary: 0, 0, 0;
}
Phương pháp 2: Sử dụng thuộc tính dữ liệu (ví dụ: [data-theme="dark"])
Phương pháp này thường được ưa chuộng vì tính rõ ràng và cụ thể của nó.
css
[data-theme="dark"] {
--color-background: 10, 10, 20;
--color-surface: 30, 30, 45;
--color-text: 245, 245, 245;
}
[data-theme="high-contrast"] {
--color-background: 255, 255, 255;
--color-surface: 255, 255, 255;
--color-text: 0, 0, 0;
}
Vẻ đẹp của cách tiếp cận này là CSS của các thành phần không bao giờ thay đổi. Các phong cách của .card và .button vẫn giữ nguyên; chúng tự động thích ứng vì chúng tham chiếu đến các biến.
Bước 3: Phép màu: Chuyển đổi chủ đề với JavaScript
Áp dụng chủ đề chỉ là một vấn đề của việc chuyển đổi lớp hoặc thuộc tính dữ liệu trên phần tử HTML. Đây là một thao tác JavaScript đơn giản và gọn gàng.
javascript
// Lấy phần tử chọn chủ đề (ví dụ: một dropdown)
const themeSelector = document.getElementById('theme-selector');
// Hàm để chuyển đổi chủ đề
function setTheme(themeName) {
// Phương pháp 1: Sử dụng một lớp
// document.documentElement.className = themeName;
// Phương pháp 2: Sử dụng thuộc tính dữ liệu (Đề xuất)
document.documentElement.setAttribute('data-theme', themeName);
// Tùy chọn: Lưu sở thích của người dùng vào localStorage
localStorage.setItem('selectedTheme', themeName);
}
// Listener sự kiện cho phần chọn chủ đề
themeSelector.addEventListener('change', (e) => {
setTheme(e.target.value);
});
// Khi tải trang, kiểm tra sở thích chủ đề đã lưu
window.addEventListener('DOMContentLoaded', () => {
const savedTheme = localStorage.getItem('selectedTheme') || 'light'; // mặc định là 'light'
setTheme(savedTheme);
// Đặt giá trị cho dropdown tương ứng
themeSelector.value = savedTheme;
});
Bước 4: Nâng cao: Bộ chọn màu do người dùng điều khiển
Sức mạnh thực sự là cho phép người dùng định nghĩa một phần của chủ đề cho riêng mình. Hãy thêm một bộ chọn màu để cho phép người dùng chọn màu chính của họ.
HTML:
html
<label for="primary-color-picker">Chọn màu chính của bạn:</label>
<input type="color" id="primary-color-picker" value="#3849d6">
JavaScript:
javascript
const colorPicker = document.getElementById('primary-color-picker');
colorPicker.addEventListener('input', (e) => {
// Chuyển đổi màu hex sang chuỗi RGB
const hexToRgb = (hex) => {
const r = parseInt(hex.slice(1, 3), 16);
const g = parseInt(hex.slice(3, 5), 16);
const b = parseInt(hex.slice(5, 7), 16);
return `${r}, ${g}, ${b}`;
};
const newRgbValue = hexToRgb(e.target.value);
// Cập nhật CSS Custom Property trực tiếp trên phần tử root
document.documentElement.style.setProperty('--color-primary', newRgbValue);
// Lưu màu tùy chỉnh
localStorage.setItem('customPrimaryColor', newRgbValue);
});
// Tải màu tùy chỉnh khi tải trang
const savedColor = localStorage.getItem('customPrimaryColor');
if (savedColor) {
document.documentElement.style.setProperty('--color-primary', savedColor);
// Cập nhật giá trị của bộ chọn màu (chuyển đổi RGB sang Hex, bỏ qua để đơn giản)
}
Kết luận: Nền tảng cho các giao diện người dùng biểu cảm
Bằng cách tận dụng CSS Custom Properties, chúng ta có thể vượt xa một công tắc nhị phân đơn giản. Chúng ta có thể tạo ra một hệ thống chủ đề:
- Dễ bảo trì: Tất cả các token thiết kế được định nghĩa tại một nơi logic.
- Mở rộng: Thêm một chủ đề mới chỉ đơn giản là thêm một khối CSS mới.
- Trao quyền cho người dùng: Người dùng có thể cá nhân hóa trải nghiệm của họ, dẫn đến sự tham gia và khả năng tiếp cận cao hơn.
Cách tiếp cận này tạo thành xương sống của các hệ thống thiết kế hiện đại được sử dụng bởi các công ty như Google, Apple và GitHub. Bắt đầu triển khai nó trong các dự án của bạn để xây dựng các giao diện web động, linh hoạt và thân thiện với người dùng hơn.
Nguồn Tài Nguyên và Đọc Thêm
Nếu bạn hào hứng với việc khai thác sức mạnh đầy đủ của CSS hiện đại như Custom Properties, Grid, Flexbox và Animations, tôi rất khuyến khích bạn tìm hiểu sâu hơn với các tài nguyên có cấu trúc.
Để giúp bạn trong hành trình này, hãy xem eBook của tôi, "CSS Unleashed: Hướng Dẫn Hiện Đại Về Thiết Kế Đáp Ứng và Thanh Lịch." Nó được thiết kế để đưa bạn từ các nguyên tắc cơ bản đến các kỹ thuật nâng cao, với các ví dụ thực tế và các phương pháp tốt nhất mà bạn có thể áp dụng ngay lập tức vào các dự án của mình.
👉 Nhận bản sao của "CSS Unleashed" tại đây!
Chúc bạn lập trình vui vẻ!