bộ màu css variables export: từ Figma token tới globals.css có dark mode
· Tác giả: Trường — Founder Webchốt
bộ màu css variables export là cách để designer và dev nói cùng một “ngôn ngữ” trong repo: thay vì rải rác hex, bạn có --color-primary và --color-surface. bộ màu css variables export thực hành tốt nhất khi css custom property được nhóm theo semantic (text, border, surface) rồi alias về scale (blue-500). Bài viết mô tả cấu trúc file, fallback trình duyệt cũ và cách tránh xung đột với thư viện component. Team lớn nên cố định một “token RFC” ngắn: ai đề xuất tên mới phải mở issue và cập nhật bảng tra cứu — tránh biến màu phình ra vô hạn. Xem thêm dịch vụ triển khai, giá và liên hệ 0905 151 701 khi cần migrate theme lớn.
semantic trước, scale sau — đổi brand ít đụng component | Nguồn: webchot.com
css custom property: naming convention và namespace
css custom property nên có prefix dự án hoặc dùng chuẩn Open Props/Tailwind bridge để tránh va chạm --spacing từ lib khác. Một pattern phổ biến: --color-{semantic}-{state} ví dụ --color-border-hover.
Với SSR Next.js, đặt biến trong layout.tsx import globals.css sớm; tránh flash sai theme bằng cách set data-theme trên html từ cookie hoặc header. Nếu dùng middleware edge rewrite subdomain, đảm bảo cookie theme đọc đúng trước khi stream HTML — lỗi nhỏ này hay bị bỏ qua trên staging chỉ có một hostname.
Khi component third-party chèn style inline, isolate bằng wrapper class và unset các property conflict nếu tài liệu cho phép.
Với App Router Next.js 15+, thứ tự import CSS module và global ảnh hưởng cascade — nên document trong CONTRIBUTING.md rằng mọi file mới phải wrap bằng layer @layer base/components để override có dự đoán được. Khi dùng radix/shadcn, kiểm tra CSS variables mặc định của lib trước khi map token — một số component dùng --background trùng tên bạn muốn.
Trường hợp micro-frontend: iframe hoặc module federation cần inject stylesheet theo mount — tránh hai :root cạnh tranh bằng prefix tenant.
Tổ chức file: _tokens.css, themes và layer Tailwind
Chia nhỏ file giúp review PR rõ ràng: _tokens primitives, _semantic mapping, dark.css override.
- Điểm 1: Giữ primitives ít thay đổi — semantic reference primitives.
- Điểm 2: Dùng hsl(h s l / a) cho dễ chỉnh alpha từ runtime.
- Điểm 3: Tránh duplicate hex giữa light/dark — map semantic khác nhau.
- Điểm 4: Document ý nghĩa từng token trong Storybook hoặc MDX.
Storybook nên có story “kitchen sink” hiển thị toàn bộ trạng thái với theme switch — giảm bug “quên đổi token sidebar”. Với Tailwind v4 @theme, đồng bộ tên biến với designer theo bảng alias để không phải dịch blue-500 sang cả tiếng Anh và tiếng mã.
Bảng so sánh: hex cứng, SCSS variable và CSS var runtime
Chọn chiến lược export theo tốc độ đổi theme và kích thước bundle.
| Tiêu chí | Lựa chọn A | Lựa chọn B | Khuyên dùng |
|---|---|---|---|
| Đổi theme live | Hex build-time | CSS var | CSS var + toggle class |
| Bundle size nhỏ | Strip unused | Runtime theme | Hybrid: core hex, accent var |
| Hỗ trợ IE11 legacy | Polyfill ít | var() không | Build fallback layer riêng |
| Multi-tenant SaaS | Branch build | Token DB → CSS | Generate per-tenant CSS |
Sau bảng: SaaS white-label thường cần pipeline generate :root từ API — đừng hardcode mọi tenant trong một file.
Chiến lược hybrid phổ biến: giữ neutral và typography build-time, chỉ expose accent runtime qua admin panel — giảm attack surface JSON inject. Khi tenant nhập hex “lạ”, validate contrast server-side trước khi ghi stylesheet.
Quy trình 5 bước export token lên production
- Bước 1: Xuất JSON từ Figma Tokens hoặc penpot tương đương.
- Bước 2: Transform qua Style Dictionary thành CSS + types TS.
- Bước 3: Áp vào globals + kiểm tra snapshot visual.
- Bước 4: Thêm prefers-color-scheme và forced dark class.
- Bước 5: Tag release token semver và changelog cho design.
Khi lỗi contrast, rollback token version nhanh hơn revert cả component.
Sau merge, chạy axe hoặc Pa11y trên các route có form và bảng — thay đổi nhỏ ở token surface có thể phá AA mà không lộ trên story đơn lẻ.
Cuối quy trình, lưu bản checksum file CSS để CI so sánh drift không chủ ý giữa các phiên bản.
Xuất palette trên Webchốt rồi dán vào dự án
Với team nhỏ chưa có Style Dictionary, thử color palette trên nền tảng Webchốt để copy block :root sẵn format. Cần template marketing đồng màu: xem template và nhắn liên hệ để ghép brand guide.
bộ màu css variables export chỉ bền khi có code review — đừng paste token từ chat vào main.
Nếu bạn đã có monorepo, hãy publish package tokens nội bộ với semver — app marketing và app admin dùng chung nguồn, giảm drift màu giữa subdomain.
Sai lầm khiến theme “trôi” giữa các sprint
Các anti-pattern phá tính nhất quán UI.
- Sai lầm 1: Trộn hex trực tiếp trong JSX lẫn var() trong CSS — khó grep.
- Sai lầm 2: Không có dark token cho shadow — box-shadow đen trên nền đen mất depth.
- Sai lầm 3: Đặt tên --red thay vì --color-danger — đổi hue brand đỏ sang cam bị kẹt tên.
- Sai lầm 4: Quên fallback: color: var(--text, #111) khi SSR partial.
Bổ sung: import order trong bundler có thể làm biến “nhảy” giữa hai chunk — nếu gặp hiện tượng lạ chỉ trên production, kiểm tra splitChunks và sideEffects trong package.json của file token.
FAQ — bộ màu css variables export
CSS variable có animate được không?
Một số trình duyệt hỗ trợ transition trên custom property kiểu màu — với keyframe phức tạp, cân nhắc FLIP hoặc canvas. Kiểm tra Safari version tối thiểu của bạn. Với hero gradient động, có thể interpolate qua JS requestAnimationFrame rồi gán var() — nhớ throttle khi tab ẩn.
Nên lưu token trong env hay static file?
Public theme có thể static; tenant-specific nên fetch server-side inject style tag hoặc link stylesheet generated — không lộ secret trong client bundle. ENV chỉ nên chứa URL build pipeline, không chứa toàn bộ palette dạng JSON nếu không mã hóa.
Flash của wrong theme khi hydration?
Dùng inline script blocking nhỏ set class trước paint hoặc default theme trùng system. Đo với Lighthouse. Một số site lưu theme trong localStorage — đọc sync trong head trước body để tránh nháy.
Component library wrap CSS Modules?
Pass variable qua wrapper hoặc dùng :where để specificity thấp; test import order trong Next.js app router. Nếu lib dùng shadow DOM, phải forward token bằng style link hoặc constructable stylesheet — đừng kỳ vọng var() tự thấu từ :root.
Webchốt hỗ trợ migrate từ styled-components?
Có roadmap tùy scale — 0905 151 701 hoặc hi@webchot.com để khảo sát bundle hiện tại. Thường tách phần dynamic style sang CSS module + var trước, giữ styled chỗ hiếm để giảm rủi ro một lần.
Liên Hệ Webchốt
bộ màu css variables export là điểm chạm giữa design và performance: đúng token giảm CSS thừa và giảm tranh luận review. Webchốt giúp bạn ship Next.js gọn và có thể tái theme. Gọi 0905 151 701 hoặc email hi@webchot.com. Khi gửi brief, đính kèm danh sách route cần snapshot để team ưu tiên visual test đúng chỗ nóng.
- Hotline / Zalo: 0905 151 701 — gặp anh Trường (founder/dev).
- Chat Zalo: zalo.me/0905151701 — phản hồi nhanh.
- Email: hi@webchot.com — phản hồi <12h làm việc.
- Studio: 262/1/93 Phan Anh, Phường Phú Thạnh, TP.HCM (T2–T7, 9h–18h).
Tham khảo thêm: 17 template Next.js · 10 dịch vụ web chuyên sâu · bảng giá Webchốt 2026 · 12 công cụ kế toán/tài chính miễn phí.
Reference: Next.js docs · web.dev Core Web Vitals.