Selector và specificity trong CSS: vì sao style của tôi không ăn?

  • author-image

    Nguyễn Đình Cường

  • blog-tag
  • blog-comment 0 comment
  • created-date 09 Nov, 2026
blog-thumbnail

Bạn viết một quy tắc CSS rất đúng, lưu file, tải lại trang và... không có gì thay đổi. Gần như lúc nào nguyên nhân cũng là một quy tắc khác "mạnh" hơn đang thắng. Hiểu specificity (độ ưu tiên của selector) là cách nhanh nhất để thoát khỏi vòng lặp thêm !important mỗi khi gặp rắc rối.

Cascade quyết định như thế nào?

Khi nhiều quy tắc cùng nhắm vào một phần tử và cùng đặt một thuộc tính, trình duyệt xét lần lượt:

  1. Nguồn và !important: quy tắc có !important thường thắng.
  2. Specificity: selector cụ thể hơn thắng.
  3. Thứ tự xuất hiện: nếu mọi thứ bằng nhau, quy tắc nằm sau thắng.

Phần lớn rắc rối nằm ở bước hai.

Cách tính specificity

Hãy hình dung specificity là ba con số (a, b, c):

  • a: số selector id (như #header).
  • b: số class, thuộc tính, pseudo-class (như .card, [type='text'], :hover).
  • c: số thẻ và pseudo-element (như p, div, ::before).

So sánh từ trái sang phải: a lớn hơn là thắng, nếu bằng thì so b, rồi đến c. Style viết trực tiếp trong thuộc tính style của thẻ còn mạnh hơn cả id.

Một vài ví dụ:

p                    /* (0,0,1) */
.note                 /* (0,1,0) */
p.note               /* (0,1,1) */
#intro                /* (1,0,0) */
nav ul li a:hover     /* (0,1,4) */
.card .title.active   /* (0,3,0) */

Chú ý rằng 11 class không thể "vượt" được một id, vì các cột không tràn sang nhau. Mỗi cột được so sánh riêng.

Tình huống kinh điển

.button { background: blue; }
#sidebar .button { background: gray; }

Nút trong sidebar có màu xám dù bạn thêm class mới sau đó, vì selector thứ hai có id nên mạnh hơn. Muốn thắng mà không dùng !important, bạn có thể tăng độ cụ thể hợp lý, hoặc tốt hơn là đơn giản hóa selector ban đầu.

Nguyên tắc viết selector tốt

  • Ưu tiên class: class có độ ưu tiên vừa phải, tái sử dụng được. Tránh dùng id để tạo kiểu.
  • Giữ selector phẳng: .card-title tốt hơn main section .card h3, vì dễ đọc, dễ ghi đè và ít phụ thuộc cấu trúc HTML.
  • Tránh !important: mỗi lần dùng nó là một lần bạn khiến lần sau phải dùng thêm. Chỉ nên dành cho các lớp tiện ích rất đặc thù.
  • Dùng quy ước đặt tên: các quy ước như BEM (.card__title--large) giúp giữ độ ưu tiên đều nhau và tránh xung đột.
  • Sắp xếp CSS có thứ tự: quy tắc chung đặt trước, quy tắc cụ thể đặt sau.

Kế thừa không phải specificity

Một số thuộc tính như color và font-family được kế thừa từ phần tử cha, nhưng giá trị kế thừa có độ ưu tiên thấp hơn bất kỳ quy tắc nào nhắm trực tiếp vào phần tử đó. Nếu bạn đặt màu cho body nhưng một quy tắc a { color: ... } tồn tại, liên kết sẽ lấy màu của quy tắc đó chứ không lấy từ body.

Công cụ giúp bạn gỡ rối

Mở DevTools, chọn phần tử rồi xem tab Styles. Các quy tắc được liệt kê từ mạnh nhất đến yếu nhất, và những thuộc tính bị ghi đè sẽ bị gạch ngang. Bạn thấy ngay quy tắc nào đang thắng và nằm ở file nào dòng nào. Hiện nay CSS cũng có tính năng cascade layers (@layer) giúp kiểm soát thứ tự ưu tiên giữa các nhóm quy tắc, đáng tìm hiểu khi dự án lớn dần.

Ví dụ gỡ rối từng bước

Giả sử đoạn văn có class .lead không đổi được màu:

.article p { color: #444; }       /* (0,1,1) */
.lead { color: #0a5; }              /* (0,1,0) */

Selector đầu có (0,1,1) cao hơn (0,1,0), nên đoạn văn vẫn màu xám. Có ba hướng sửa: đổi thành .article .lead để (0,2,0) thắng, hạ độ cụ thể của quy tắc đầu xuống bằng cách viết .article-text thay vì lồng thẻ, hoặc dùng :where(), vì pseudo-class này luôn có specificity bằng không:

:where(.article) p { color: #444; }  /* (0,0,1) */

Hướng thứ ba rất hữu ích khi viết CSS nền tảng mà bạn muốn các quy tắc sau dễ dàng ghi đè. Chọn cách nào tùy dự án, miễn là bạn hiểu lý do và thống nhất trong nhóm.

Kết luận

Khi style không ăn, đừng thêm !important ngay. Hãy mở DevTools, tìm quy tắc đang thắng, so sánh specificity và sửa tận gốc bằng selector đơn giản, phẳng và nhất quán.

Nếu bạn muốn có người hướng dẫn qua các tình huống CSS thực tế như thế này, hãy khám phá danh sách khóa học tại codebem.com.

author_photo
Nguyễn Đình Cường

0 comment