Skip to content

Viết CSS trong dự án

Phần lớn giao diện đã do component C* lo. CSS của dự án chỉ nên là lớp mỏng: sắp xếp bố cục, vài khối đặc thù nghiệp vụ. Trang này là luật chơi cho lớp mỏng đó.

Ba quy tắc

  1. Màu, bo góc, khoảng cách, font — chỉ dùng var(--tasco-*). Không hardcode #1e3a8a, không rgba(0,0,0,.65).
  2. Cần một giá trị chưa có token? Thêm token vào @tasco/theme trước (mở issue/MR với core), đừng đặt hằng số màu riêng trong dự án.
  3. CSS luôn scoped. Style global chỉ dùng khi phải ghi đè antd, và đặt tập trung một chỗ.

Lý do của quy tắc 1: chế độ tối chỉ đổi giá trị các biến. Màu viết cứng sẽ giữ nguyên khi chuyển sang tối, và đó là cách nhanh nhất để có chữ đen trên nền đen.

Token hay dùng

NhómBiến
Màu chính--tasco-color-primary, -hover, -active, -soft
Màu nhấn--tasco-color-accent, -soft, -text
Trạng thái--tasco-color-{success,warning,error,info}, kèm -soft; success/warning/accent có thêm -text
Chữ--tasco-color-text, -secondary, -muted, -subtle
Nền--tasco-color-surface, -elevated, -muted, --tasco-color-page
Viền--tasco-color-border, -strong
Bo góc--tasco-radius, --tasco-radius-lg
Khoảng cách--tasco-spacing-unit
Chữ--tasco-font-family, --tasco-font-family-heading, --tasco-font-size
Đổ bóng--tasco-shadow-card, --tasco-shadow-raised

Bảng đầy đủ kèm giá trị sáng/tối và tỉ lệ tương phản: Màu & tương phản.

css
.don-hang__tom-tat {
  padding: calc(var(--tasco-spacing-unit) * 2);
  background: var(--tasco-color-surface);
  border: 1px solid var(--tasco-color-border);
  border-radius: var(--tasco-radius-lg);
  color: var(--tasco-color-text);
}

Chọn đúng cặp chữ / nền

Không phải cặp màu nào cũng đủ tương phản. Quy tắc nhanh:

  • accent, success, warningmàu nền. Làm chữ trên nền sáng thì dùng biến -text tương ứng (--tasco-color-success-text).
  • primary, error, info dùng làm màu chữ được ngay trên surface và trên -soft.
  • Chữ trắng chỉ đặt trên --tasco-color-primary-active hoặc --tasco-gradient-danger.

Bảng tỉ lệ tương phản của từng cặp có ở Màu & tương phản — cặp nào cũng phải đạt tối thiểu 4.5:1.

Đặt tên class

BEM với tiền tố theo nghiệp vụ của dự án:

.don-hang__tieu-de
.don-hang__tom-tat--noi-bat

Đừng dùng tiền tố c- (dành cho @tasco/ui) hay tasco- (dành cho layer) — trùng tên sẽ ghi đè nhầm khi core đổi style.

Ghi đè component antd

Component antd dùng cssinjs với độ ưu tiên cao, nên ghi đè từ scoped thường không ăn. Hai cách, theo thứ tự ưu tiên:

1. Dùng prop có sẵn. CCard type="primary", CTable borderless, CButton variant="text" — kiểm tra API component trước khi viết CSS.

2. :deep() trong phạm vi hẹp, khi chỉ muốn đổi trong một trang:

vue
<style scoped>
.don-hang :deep(.ant-table-cell) {
  vertical-align: top;
}
</style>

Cần đổi cho toàn app (mật độ, padding, chiều cao control) thì đó là việc của @tasco/theme/base.css — báo core, đừng nhân bản rule global ở từng dự án.

!important là dấu hiệu, không phải giải pháp

Phải viết !important để thắng cssinjs nghĩa là đang chạm vào thứ lẽ ra thuộc về theme chung. Ghi lại lý do trong comment và gửi yêu cầu cho core.

Chế độ tối

Không viết @media (prefers-color-scheme: dark) và cũng không tự đặt bảng màu tối: chế độ tối do người dùng chọn (lưu trong cookie tasco:theme), và mọi biến --tasco-* đã tự đổi giá trị.

Cần một khác biệt thật sự theo chế độ (ví dụ ảnh nền khác) thì bám thuộc tính trên thẻ html:

css
[data-theme='dark'] .don-hang__banner {
  background-image: url('/banner-dark.svg');
}

Ảnh và icon

  • Icon: dùng @tabler/icons-vue đã có sẵn; icon kế thừa currentColor nên đổi màu bằng color.
  • SVG nội tuyến cho hình đơn giản; ảnh bitmap đặt trong public/ và luôn có alt.
  • Không thêm bộ icon thứ hai vào dự án — hai bộ icon trong một app là hai phong cách nét vẽ.

Danh sách rà soát

  • [ ] Không có mã màu viết cứng trong .vue.css của dự án.
  • [ ] <style>scoped, trừ file override tập trung.
  • [ ] Class có tiền tố riêng của dự án.
  • [ ] Đã thử chế độ tối trước khi mở MR.
  • [ ] Không có !important nào thiếu comment giải thích.

Liên quan