Thêm game tại WuGames.ioTài trợKhám phá kho game trình duyệt miễn phí — chơi ngay, không tải, không đăng ký.Chơi ngay

Máy Tính CSS Specificity

Tính CSS specificity cho mọi selector. Phân tách màu, so sánh nhiều selector, xử lý :is, :not, :has, :where theo chuẩn W3C.

Selector CSS (mỗi dòng một selector)
Mỗi dòng một selector. Các rule cách bằng dấu phẩy tính là một dòng input.
Bảng Tham Chiếu Specificity
Thành PhầnVí DụTrọng Số
a ID#header, #main(1, 0, 0)
b Class / Thuộc tính / Pseudo-class.btn, [type="text"], :hover, :nth-child(2)(0, 1, 0)
c Type / Pseudo-elementdiv, p, ::before, ::placeholder(0, 0, 1)
*, :where(...), +, >, ~(0, 0, 0)
:is(A, B), :not(A), :has(A)max của đối số

Máy Tính CSS Specificity — Phân Tích Selector, Tính (a, b, c)

Dán bất kỳ selector CSS nào — đơn giản hay phức hợp, có combinator, pseudo-class, pseudo-element, hoặc :is/:not/:where/:has hiện đại — và máy tính trả về bộ ba specificity W3C. Phần phân tách cho thấy từng token đóng góp vào slot nào, và chế độ so sánh xếp hạng nhiều selector để bạn nhìn thấy ngay rule nào thắng cascade.

CSS specificity là gì trong một đoạn?

Khi hai rule CSS cùng đặt một thuộc tính trên cùng phần tử, trình duyệt cần luật phân định. Luật đầu tiên là *origin và importance* (user-agent < author < user, rồi !important đảo lại). Sau đó là *specificity*: mỗi selector có một trọng số biểu diễn bằng ba số — (a, b, c) — và tuple lớn hơn thắng, so sánh từ trái sang phải.

Ba slot đếm:

- **a** — số ID selector (`#foo`)
- **b** — số class selector (`.bar`), attribute selector (`[type=text]`), và pseudo-class (`:hover`)
- **c** — số type selector (`div`) và pseudo-element (`::before`)

Một selector như `#nav .item a:hover` có một ID, hai mục class/pseudo-class, và một type — specificity (1, 2, 1). Nó thắng `.menu .item a:focus` (0, 3, 1) vì slot đầu thắng bất chấp các slot sau cao thế nào.

`:is()`, `:not()`, và `:has()` ảnh hưởng specificity thế nào?

Cả ba đều đóng góp specificity *lớn nhất* của các đối số, không phải 0, không phải tổng.

Ví dụ:

```
:is(.btn, #primary) { color: red; }
```

Specificity được quyết định bởi `#primary` (1, 0, 0), không phải `.btn` (0, 1, 0). Toàn bộ token `:is(...)` đóng góp (1, 0, 0).

Cùng quy tắc áp dụng cho `:not(...)` và `:has(...)` — chúng lấy selector nặng nhất trong dấu ngoặc. Đó là lý do `:not(#admin)` là selector nặng dù nhìn vô hại; nó là specificity (1, 0, 0) tự thân.

Hành vi này định nghĩa trong CSS Selectors Level 4. `:not()` cũ hơn (Level 3, dạng đơn) theo cùng quy tắc, nên hầu hết trình duyệt luôn đồng thuận.

Còn `:where(...)` thì sao?

`:where(...)` là cánh cửa thoát: nó đóng góp **specificity bằng không** bất kể bên trong là gì.

```
:where(#header, .nav, h1) { color: blue; }
```

Specificity = (0, 0, 0). Điều này có chủ ý. `:where()` cho phép bạn viết một style cơ sở mà các selector gộp chia sẻ mà không khóa các override trong tương lai — bất cứ thứ gì target cùng phần tử với dù chỉ một class cũng sẽ thắng.

Mẫu phổ biến là bọc các rule reset hoặc mặc định trong `:where(...)` để chúng thực tế không có trọng số specificity, trong khi style component do tác giả vẫn tự do ghi đè bằng selector thông thường. Được thêm trong CSS Selectors Level 4 (2018) và ship trong mọi trình duyệt evergreen vào 2021.

Tại sao đôi khi thấy `(a, b, c, d)` với bốn slot?

Bài viết cũ thêm slot thứ tư ở đầu cho **inline style** (thuộc tính `style="..."`), cho (1, 0, 0, 0) cho bất kỳ khai báo inline nào. W3C đã bỏ điều này khỏi tuple specificity chính thức vì inline style là một lớp origin riêng biệt — nó thắng mọi quyết định cascade ở mức author trước khi specificity được so sánh.

Thực tế:

1. Khai báo `!important` thắng (lớp origin).
2. Inline style thắng mọi selector không có `!important`.
3. Selector sau đó xếp theo (a, b, c) — ID, class/attr/pseudo-class, type/pseudo-element.
4. Nếu specificity hòa, rule khai báo cuối cùng trong source order thắng.

Máy tính này theo quy ước ba slot hiện đại. Nếu so với tutorial cũ, hãy thêm số 0 đầu — `(0, 1, 2, 1)` và `(1, 2, 1)` mô tả cùng một selector.

Hai quy tắc của tôi hòa specificity — quy tắc nào thật sự thắng?

Đây là lỗi CSS thực tế phổ biến nhất: hai selector cùng tác động lên một phần tử với bộ ba specificity *giống hệt*, ví dụ cả `.card .title` lẫn `.panel .heading` đều (0, 2, 0). Riêng specificity không phá được thế hòa, nên trình duyệt chuyển sang bước tiếp theo của cascade.

Thứ tự phân định, một khi specificity bằng nhau, là:

1. **Tầng cascade** (`@layer`) — khai báo ở tầng được khai báo sau sẽ thắng tầng trước, và style không tầng thắng style có tầng. Điều này ghi đè hoàn toàn specificity trong phạm vi origin tác giả.
2. **Thứ tự nguồn** — nếu cả hai quy tắc cùng tầng (hoặc không dùng tầng), quy tắc khai báo *sau cùng* thắng. Cái sau thắng.

Đó là lý do bảng so sánh của máy tính này giờ có cột **Người Thắng Trong Tầng Xếp Chồng**: dán các selector bị hòa theo đúng thứ tự chúng xuất hiện trong stylesheet, công cụ sẽ đánh dấu nhóm cùng specificity và chỉ ra người thắng theo thứ tự nguồn (dòng cuối). Vậy nếu `.card .title` ở dòng 12 và `.panel .heading` ở dòng 30, dòng 30 thắng — công cụ nói rõ thay vì để bạn tự nhớ quy tắc.

Lưu ý công cụ chỉ mô phỏng phá hòa theo *thứ tự nguồn*; nó không phân tích `@layer` hay `!important`, vốn nằm trên thứ tự nguồn trong cascade. Nếu các quy tắc ở các tầng khác nhau, thứ tự tầng quyết định bất kể dòng nào nằm sau.

Máy Tính CSS Specificity — Tính CSS specificity cho mọi selector. Phân tách màu, so sánh nhiều selector, xử lý :is, :not, :has, :where theo chuẩn W
Máy Tính CSS Specificity

Làm sao thắng được khai báo style inline `style="..."`?

Thuộc tính style inline vượt trên *bất kỳ* quy tắc dựa trên selector nào không dùng `!important`, dù specificity của nó cao đến đâu. `style="color:red"` thắng cả `#a#b#c.d.e div { color: blue; }` vì style inline nằm ở slot cao hơn của cascade so với specificity selector thông thường.

Các lựa chọn của bạn, theo thứ tự ưu tiên:

1. **Bỏ style inline** — cách sạch nhất. Style inline thường do một script hoặc template cũ chèn vào; hãy chuyển giá trị vào một quy tắc stylesheet.
2. **Dùng `!important`** trong quy tắc stylesheet — một khai báo `!important` của tác giả thắng style inline *không* phải `!important`. Đây là cách dùng `!important` chính đáng mà nhiều kỹ sư chọn ở đây.
3. **`!important` inline** (`style="color:red !important"`) thắng `!important` của stylesheet — lúc đó bạn lại phải sửa markup.

Specificity không bao giờ tham gia cuộc chiến này: bạn không thể vượt style inline chỉ bằng selector. Máy tính này chấm điểm selector, nên style inline nằm ngoài phạm vi theo thiết kế — nhưng biết chúng thắng ở tầng này là thiết yếu khi gỡ lỗi vì sao một quy tắc không áp dụng.

Universal selector `*` hay combinator có thêm specificity không?

Không. Không có cái nào sau đây đóng góp specificity:

- `*` (universal selector)
- ` ` (descendant combinator, viết bằng khoảng trắng)
- `>` (child combinator)
- `+` (adjacent sibling combinator)
- `~` (general sibling combinator)
- `||` (column combinator, cho bảng — Level 4)

Một selector như `* > * + *` có specificity (0, 0, 0) — ba universal và hai combinator, đều không trọng số. Combinator mô tả *quan hệ*, không phải cái được match, nên không thêm trọng số.

Đó là lý do `body > main p` (0, 0, 3) hòa với `h1 ~ h2 ~ p` (0, 0, 3) — cùng ba type selector, khác combinator, cùng specificity. Cascade rồi quyết theo source order.

Khác nhau giữa pseudo-class và pseudo-element là gì?

**Pseudo-class** mô tả một trạng thái của phần tử:

- `:hover`, `:focus`, `:active`, `:checked`, `:disabled`
- `:nth-child(2)`, `:nth-of-type(odd)`, `:first-child`
- `:lang(en)`, `:dir(rtl)`, `:state(custom)`

Chúng đóng góp vào slot **b** — cùng trọng số class selector.

**Pseudo-element** mô tả một phần con ảo của phần tử:

- `::before`, `::after`, `::first-line`, `::first-letter`
- `::placeholder`, `::marker`, `::backdrop`, `::selection`

Chúng đóng góp vào slot **c** — cùng trọng số type selector.

Khác biệt cú pháp là một dấu hai chấm (`:hover`) so với hai dấu hai chấm (`::before`). CSS2 dùng một dấu hai chấm cho bốn pseudo-element cổ nhất (`:before`, `:after`, `:first-line`, `:first-letter`) — máy tính này chấp nhận cả hai dạng và phân loại bốn cái đó là pseudo-element trong cả hai trường hợp.

Làm sao giảm specificity khi đang đấu với stylesheet khác?

Vài kỹ thuật theo mức độ tăng dần:

1. **Dùng `:where()`** — bọc phần nặng của selector trong `:where()` để chúng không đóng góp gì. `:where(.legacy) .button` → (0, 1, 0) thay vì (0, 2, 0). Tốt nhất cho stylesheet reset.
2. **Bỏ ID khỏi selector** — refactor `#nav .item` thành `.nav .item` nếu markup cho phép. ID là thành phần nặng nhất.
3. **Dùng một class duy nhất** — selector phẳng như `.btn-primary` thắng vì hòa ở (0, 1, 0) với hầu hết style của tác giả, để source order quyết.
4. **Nhân đôi class** — `.btn.btn` (0, 2, 0) là một hack quen thuộc để tăng specificity *mà không* cần ID.
5. **Dùng cascade layer** — `@layer base, components, utilities;` cho phép kiểm soát file nào thắng bất kể specificity. Layer khai báo sau thắng, không tranh cãi.
6. **Dùng `!important`** — biện pháp cuối. Nó hoạt động nhưng tạo chuỗi override mong manh.

Quy tắc hiện đại là: tối thiểu hóa specificity trong CSS component (class đơn), bọc rule legacy/reset trong `:where()`, và dùng cascade layer cho tách tooling/utility.

Máy tính này có riêng tư và offline không?

Có. Mọi thứ được tính cục bộ trong trình duyệt bởi vài trăm dòng JavaScript:

- Parser selector viết tay, không gọi CSS engine ngoài.
- Không telemetry, không analytics cho phép tính này.
- Nút Ví Dụ điền textarea bằng chuỗi nội bộ; không tải gì.
- Trang chia sẻ asset thông thường của site (Bootstrap CSS, icon) nhưng không API bên thứ ba nào được liên lạc cho phép toán specificity thực tế.

Bạn có thể kiểm tra bằng DevTools → Network và quan sát khi gõ hoặc bấm Tính — không request nào nổ. Điều này cũng có nghĩa máy tính chạy offline sau khi trang đã tải, tiện khi audit stylesheet trên máy bay hoặc môi trường tín hiệu yếu.

Tính Năng Chính

  • Tuple (a, b, c) đúng chuẩn W3C cho mọi selector CSS
  • Phân tách màu làm nổi bật token nào đóng góp vào slot nào
  • Chế độ so sánh nhiều selector, sắp xếp theo specificity giảm dần
  • Xử lý đúng :is(), :not(), :has() — specificity max của đối số
  • :where(...) được nhận diện là specificity bằng không
  • Pseudo-element (::before, ::after, ::first-line) phân loại tách khỏi pseudo-class
  • Chấp nhận pseudo-element CSS2 một dấu hai chấm cổ (:before, :after)
  • Universal selector * và combinator (>, +, ~, khoảng trắng) tính đúng là không
  • Attribute selector, bao gồm [attr=value] và [attr^=value]
  • Functional pseudo-class :nth-child(), :nth-of-type(), :lang(), :dir()
  • Preset Ví Dụ tải 10 selector đại diện để so sánh tức thì
  • Phát hiện hòa — làm nổi bật selector có specificity bằng nhau
  • JavaScript thuần, không CSS engine ngoài
  • Hoạt động offline sau lần tải đầu
  • 100% phía client — selector của bạn ở trong trình duyệt