Chào anh em coder! Chắc hẳn không ít lần anh em vò đầu bứt tai, tự hỏi: "Rõ ràng mình đã code CSS cho cái nút này màu xanh, sao nó cứ trơ trơ ra màu đỏ vậy?". Yên tâm, bạn không cô đơn đâu. Đây là vấn đề kinh điển mà hầu hết những ai làm việc với CSS đều từng gặp phải. Thủ phạm chính là một khái niệm nghe có vẻ khô khan nhưng lại cực kỳ quan trọng: Thứ tự ưu tiên của CSS (hay còn gọi là CSS Specificity).
Bài viết này sẽ mổ xẻ vấn đề này một cách dễ hiểu nhất, giúp bạn làm chủ cuộc chơi và không còn phải "đoán mò" xem trình duyệt sẽ áp dụng style nào nữa.
Tại sao phải quan tâm đến thứ tự ưu tiên?
Tưởng tượng bạn đang xây một ngôi nhà. Có nhiều đội thợ cùng tham gia: đội sơn tường, đội lắp cửa, đội đi dây điện. Mỗi đội đều có bản thiết kế riêng. Nếu không có một "kiến trúc sư trưởng" quyết định cái nào làm trước, cái nào quan trọng hơn, ngôi nhà của bạn sẽ thành một mớ hỗn độn.
Trong thế giới CSS, trình duyệt chính là ông "kiến trúc sư trưởng" đó. Khi bạn viết nhiều đoạn code CSS khác nhau để định dạng cho cùng một phần tử HTML, trình duyệt cần một bộ quy tắc rõ ràng để quyết định sẽ "nghe" theo lời khuyên của ai. Bộ quy tắc đó chính là thứ tự ưu tiên.
Hiểu được nó, bạn sẽ:
- Code chính xác hơn: Viết đâu ăn đó, không phải sửa tới sửa lui.
- Gỡ lỗi (debug) nhanh hơn: Khi gặp lỗi hiển thị, bạn biết ngay phải tìm ở đâu.
- Viết code gọn gàng, dễ bảo trì: Tránh việc phải dùng đến những cách "ép" style một cách vô tội vạ.
Các quy tắc của độ ưu tiên CSS
Trình duyệt quyết định độ ưu tiên dựa trên một hệ thống tính điểm khá logic. Cứ nhớ theo thứ tự từ cao xuống thấp như sau nhé.
1. Important - Ông trùm tuyệt đối
Có thể nói đây là "lá bài tẩy", là "quyền lực tối thượng". Khi bạn thêm !important
vào cuối một thuộc tính CSS, nó sẽ gần như ngay lập tức được ưu tiên cao nhất, bất chấp mọi quy tắc khác.
p {
color: blue !important; /* Tôi sẽ màu xanh, bất kể anh viết gì khác! */
}
#special-paragraph {
color: red;
}
Dù thẻ <p>
có ID là special-paragraph
(mà ID thường có độ ưu tiên rất cao), nó vẫn sẽ hiển thị màu xanh vì có !important
.
Nhưng khoan đã! Nghe có vẻ hay ho, nhưng lạm dụng !important
là một thói quen cực kỳ xấu. Nó giống như việc bạn dùng "luật rừng" để giải quyết vấn đề. Nó phá vỡ toàn bộ trật tự tự nhiên của CSS, khiến cho việc bảo trì và gỡ lỗi sau này trở thành một cơn ác mộng. Chỉ dùng nó khi thực sự không còn cách nào khác, ví dụ như cần ghi đè một style từ thư viện bên ngoài mà bạn không thể can thiệp vào code gốc.
2. Inline Style - Viết thẳng vào thẻ HTML
Đây là cách bạn viết CSS trực tiếp vào thuộc tính style
của một thẻ HTML. Cách này có độ ưu tiên rất cao, chỉ đứng sau !important
.
<p style="color: green;">Đoạn văn này chắc chắn màu xanh.</p>
Dù bạn có định nghĩa màu cho thẻ <p>
ở file CSS bên ngoài bằng ID hay class đi chăng nữa, style inline này vẫn sẽ thắng.
Khi nào nên dùng? Cách này hữu ích trong một vài trường hợp đặc thù, ví dụ như khi bạn muốn áp dụng một style động bằng JavaScript, hoặc cho các email HTML (vì nhiều trình duyệt mail không hỗ trợ tốt file CSS ngoài). Còn lại, hãy hạn chế dùng vì nó làm cho code HTML và CSS lẫn lộn, khó quản lý.
3. Selectors - Cuộc đua tính điểm
Đây là phần quan trọng và phổ biến nhất. Trình duyệt sẽ "chấm điểm" cho từng bộ chọn (selector) của bạn để quyết định ai mạnh hơn. Cứ nhớ quy tắc tính điểm đơn giản sau:
- ID
#
: 100 điểm - "Đại ca" trong các bộ chọn. Mỗi ID là duy nhất trên một trang, nên nó có tính đặc hiệu rất cao. - Class
.
, thuộc tính[ ]
, và pseudo-class:hover, :first-child...
: 10 điểm - Nhóm này linh hoạt và được sử dụng nhiều nhất. - Tên thẻ
p, div, h1...
và pseudo-element::before, ::after...
: 1 điểm - Nhóm cơ bản nhất, có độ ưu tiên thấp nhất.
Cách tính điểm:
Trình duyệt sẽ cộng điểm của các thành phần trong bộ chọn của bạn. Ai cao điểm hơn, người đó thắng.
Ví dụ cho dễ hiểu:
/* ---- CÁC BỘ CHỌN ---- */
#main-content p {
color: purple; /* Điểm: 100 (ID) + 1 (p) = 101 điểm */
}
div.content p {
color: orange; /* Điểm: 1 (div) + 10 (class) + 1 (p) = 12 điểm */
}
.content p {
color: brown; /* Điểm: 10 (class) + 1 (p) = 11 điểm */
}
p {
color: gray; /* Điểm: 1 điểm */
}
Trong trường hợp này, dù bạn viết p { color: gray; }
ở dòng cuối cùng, thì đoạn văn bản <p>
nằm trong thẻ có ID là main-content
vẫn sẽ có màu tím (purple) vì bộ chọn của nó có điểm số cao nhất (101 điểm).
Nếu điểm bằng nhau thì sao? Nếu hai bộ chọn có cùng điểm số, thì luật cuối cùng sẽ thắng. Tức là, CSS nào được trình duyệt đọc sau cùng sẽ được áp dụng.
.highlight {
color: blue; /* Được đọc trước */
}
.highlight {
color: red; /* Cùng điểm, nhưng đọc sau -> Thắng! */
}
Phần tử có class highlight
sẽ có màu đỏ.
4. Inheritance - Kế thừa
Một số thuộc tính CSS có khả năng "di truyền" từ phần tử cha sang phần tử con.
Ví dụ, nếu bạn đặt color
, font-family
, font-size
cho thẻ <body>
, thì tất cả các thẻ con bên trong như <p>
, <h1>
, <li>
... sẽ tự động được thừa hưởng các thuộc tính đó mà không cần bạn phải viết lại.
<body style="color: #333; font-family: Arial;">
<h1>Đây là tiêu đề</h1>
<p>Đây là một đoạn văn.</p>
</body>
Tuy nhiên, sự kế thừa có độ ưu tiên rất thấp. Bất kỳ một quy tắc nào bạn viết trực tiếp cho phần tử con, ví dụ p { color: blue; }
, sẽ ngay lập tức ghi đè lên giá trị được kế thừa.
Tổng kết lại bằng sơ đồ
Để dễ học dễ nhớ, bạn cứ hình dung thứ tự ưu tiên như một cái thác nước (CSS là viết tắt của Cascading Style Sheets mà), nước chảy từ trên xuống dưới, cái nào ở trên có sức mạnh lớn hơn:
- Important (Nguồn nước mạnh nhất)
- Inline Styles (Viết thẳng trong thẻ HTML)
- Selectors (Tính điểm):
- ID
#
- Class
.
, Attribute[ ]
, Pseudo-class:
- Element
p
, Pseudo-element::
- ID
- Luật cuối cùng (Nếu điểm bằng nhau)
- Kế thừa (Giá trị từ thẻ cha)
- Style mặc định của trình duyệt (Yếu nhất)
Lời khuyên thực tế
- Viết CSS theo thứ tự từ tổng quát đến chi tiết: Bắt đầu với các style chung cho
body
,p
,h1
, sau đó mới đến cácclass
cụ thể, và cuối cùng nếu cần mới dùng đếnID
. - Ưu tiên dùng Class: Class là cách linh hoạt và dễ tái sử dụng nhất. Hãy tập thói quen dùng class để định kiểu thay vì lạm dụng ID.
- Tránh xa Important: Chỉ rút "lá bài tẩy" này ra khi thực sự, thực sự cần thiết.
- Sử dụng công cụ của trình duyệt: "Inspect Element" (hoặc nhấn F12) trên Chrome, Firefox là người bạn thân nhất của bạn. Nó cho bạn thấy chính xác style nào đang được áp dụng lên một phần tử và style nào đang bị ghi đè.
Hi vọng qua bài viết này, anh em đã có một cái nhìn rõ ràng và "thấm" hơn về thứ tự ưu tiên trong CSS. Nắm vững quy tắc này, bạn sẽ thấy việc viết CSS trở nên logic và thú vị hơn rất nhiều, không còn là một cuộc chiến may rủi nữa.
Chúc anh em code vui!