Đổi màu giao diện với Preact và TailwindCSS
Màu ngẫu nhiên rất vui, nhưng trong sản phẩm thực tế, ngẫu nhiên cần đi kèm tính nhất quán. Thay vì sinh mã hex bất kỳ, việc sử dụng dải màu chuẩn của TailwindCSS giúp giao diện luôn hài hòa, dễ đọc và không phá vỡ hệ thống thiết kế. Khi kết hợp Preact và TypeScript, ngay cả một ví dụ nhỏ cũng trở nên gọn gàng và đáng tin cậy.
Có một giai đoạn tôi rất thích đổi màu nền ngẫu nhiên. Bấm nút, màu thay đổi, cảm giác như đang chơi với giao diện. Nhưng càng làm nhiều, tôi càng nhận ra: không phải màu nào cũng dùng được. Có những màu nhìn rất gắt, có màu khiến chữ gần như biến mất, có màu hoàn toàn lạc lõng với phần còn lại của ứng dụng.
TailwindCSS giải quyết vấn đề này theo một cách rất tinh tế: nó đưa ra sẵn một dải màu đã được cân chỉnh. Khi dùng chính những màu đó để random, bạn vẫn có sự bất ngờ, nhưng không bao giờ rơi vào cảm giác sai sai.
Khi màu sắc trở thành một phần của hệ thống
Khác với việc sinh màu hex tự do, sử dụng màu từ Tailwind buộc bạn phải suy nghĩ theo hướng hệ thống. Màu không còn là một chuỗi ký tự, mà là một lựa chọn có tên, có cấp độ sáng tối, và có ngữ cảnh sử dụng.
Trong ví dụ này, tôi chọn một tập màu quen thuộc của Tailwind. Mỗi màu đi kèm một mức độ cố định để đảm bảo độ tương phản ổn định khi hiển thị chữ. Việc này nghe có vẻ hạn chế, nhưng thực tế lại giúp code dễ đọc hơn rất nhiều.
Component Preact viết bằng TypeScript
TypeScript phát huy tác dụng ngay cả trong ví dụ nhỏ. Nó giúp ta mô tả rõ ràng: màu là gì, có thể nhận những giá trị nào, và tránh những lỗi vô tình khi mở rộng code sau này.
import { h } from 'preact';
import { useState } from 'preact/hooks';
type TailwindColour =
| 'bg-blue-500'
| 'bg-emerald-500'
| 'bg-violet-500'
| 'bg-rose-500'
| 'bg-amber-500'
| 'bg-indigo-500'
| 'bg-cyan-500'
| 'bg-fuchsia-500'
| 'bg-teal-500';
const COLOURS: TailwindColour[] = [
'bg-blue-500',
'bg-emerald-500',
'bg-violet-500',
'bg-rose-500',
'bg-amber-500',
'bg-indigo-500',
'bg-cyan-500',
'bg-fuchsia-500',
'bg-teal-500',
];
export default function App() {
const [colour, setColour] = useState<TailwindColour>('bg-blue-500');
const changeColour = (): void => {
// Đảm bảo màu mới luôn khác màu cũ
let next: TailwindColour;
do {
next = COLOURS[Math.floor(Math.random() * COLOURS.length)];
} while (next === colour);
setColour(next);
};
return (
<div
class={`min-h-screen flex flex-col items-center justify-center transition-colors duration-500 ease-in-out ${colour}`}
>
<div class="text-center p-8 bg-black/10 backdrop-blur-md rounded-2xl border border-white/20">
<h1 class="text-5xl font-black mb-2 text-white tracking-tight capitalize">
{colour.replace('bg-', '').replace('-500', '')}
</h1>
<p class="text-white/80 font-medium mb-8">Tailwind Design System</p>
<button
onClick={changeColour}
class="px-8 py-4 rounded-xl bg-white text-gray-900 font-bold shadow-xl hover:shadow-white/20 hover:-translate-y-1 active:scale-95 transition-all duration-200"
>
Đổi màu mới
</button>
</div>
</div>
);
}Ở đây, không có inline style cho màu nền. Toàn bộ việc đổi màu được thực hiện thông qua class của TailwindCSS. Component chỉ cần đổi state, phần còn lại tự động được render lại.
Vì sao cách này đáng tin hơn random hex?
Điểm khác biệt lớn nhất nằm ở cảm giác khi sử dụng. Dù bấm nút bao nhiêu lần, giao diện vẫn giữ được sự cân đối:
- Chữ luôn đọc rõ: Vì chúng ta chỉ chọn dải
-500, độ tương phản với chữ trắng/đen gần như đã được tính toán sẵn. - Tính nhất quán: Các màu trong Tailwind có cùng một độ rực, tạo ra cảm giác chúng thuộc về cùng một bộ sưu tập.
- Dễ bảo trì: Nếu muốn đổi sang tông màu tối hơn (Dark mode), bạn chỉ cần đổi text thành
-900hoặc-950một cách đồng loạt.
Tối ưu trải nghiệm (UX Tip)
Để việc đổi màu không bị gắt, tôi đã sử dụng transition-colors duration-500 ease-in-out. Điều này tạo ra hiệu ứng hòa quyện khi chuyển tiếp giữa các kênh màu, làm cho giao diện cảm giác mượt và cao cấp hơn.
Ngoài ra, việc sử dụng một lớp overlay bg-black/10 backdrop-blur-md giúp nội dung chính luôn nổi bật bất kể màu nền phía sau là gì. Đây là một kỹ thuật nhỏ nhưng cực kỳ hiệu quả trong thiết kế UI hiện đại.
Lời kết
Đổi màu vẫn có thể vui. Nhưng khi đặt nó trong bối cảnh của một hệ thống giao diện, niềm vui đó cần được kiểm soát. Sử dụng dải màu của TailwindCSS giúp bạn giữ được tính nhất quán, còn Preact và TypeScript giúp mọi thứ luôn rõ ràng, dễ hiểu.
Một ví dụ nhỏ như thế này đủ để thấy: Frontend hiện đại không chỉ là làm cho chạy được, mà là làm sao để mỗi quyết định, dù nhỏ như chọn màu, đều có lý do tồn tại. Và khi bạn bắt đầu suy nghĩ theo hướng hệ thống, mã nguồn của bạn cũng sẽ trưởng thành và chuyên nghiệp hơn theo thời gian.