The CSS Podcast – 003: Mức độ cụ thể
Giả sử bạn đang làm việc với HTML và CSS sau đây:
<button class="branding">Hello, Specificity!</button>
.branding {
color: blue;
}
button {
color: red;
}
Có 2 quy tắc nhắm đến cùng một phần tử ở đây. Mỗi quy tắc chứa một khai báo muốn đặt màu cho nút: một quy tắc cố gắng tô màu nút thành màu đỏ và quy tắc còn lại cố gắng tô màu nút thành màu xanh dương. Khai báo nào được áp dụng cho phần tử?
Hiểu rõ thuật toán về độ ưu tiên của CSS là chìa khoá để hiểu cách CSS quyết định giữa các khai báo cạnh tranh.
Độ đặc hiệu là một trong những giai đoạn riêng biệt của tầng, được đề cập trong mô-đun cuối cùng, trên tầng.
Tính điểm mức độ cụ thể
Mỗi quy tắc chọn trong một origin sẽ được tính điểm. Bạn có thể coi độ cụ thể là tổng điểm và mỗi loại bộ chọn sẽ được cộng điểm vào tổng điểm đó. Các khai báo từ những quy tắc có độ cụ thể cao nhất sẽ giành chiến thắng.
Với tính cụ thể trong một dự án thực tế, việc cân bằng là đảm bảo các quy tắc CSS mà bạn muốn áp dụng thực sự được áp dụng, đồng thời thường xuyên giữ điểm số ở mức thấp để tránh sự phức tạp. Tính cụ thể chỉ nên cao đến mức cần thiết, thay vì nhắm đến tính cụ thể cao nhất có thể. Trong tương lai, có thể bạn cần áp dụng một số CSS quan trọng hơn. Nếu chọn độ đặc hiệu cao nhất, bạn sẽ gặp khó khăn trong việc này.
Độ đặc hiệu không phải là số thập phân mà là một bộ ba gồm 3 thành phần: A, B và C.
A: mức độ cụ thể tương tự như mã nhận dạngB: độ đặc hiệu giống như lớpC: độ đặc hiệu giống như phần tử
Đường thẳng này thường được biểu thị bằng ký hiệu (A,B,C). Ví dụ: (1,0,2).
Ký hiệu A-B-C thay thế cũng thường được dùng.
Cách so sánh độ cụ thể
Độ cụ thể được so sánh bằng cách so sánh 3 thành phần theo thứ tự: độ cụ thể có giá trị A lớn hơn sẽ cụ thể hơn; nếu 2 giá trị A bằng nhau, thì độ cụ thể có giá trị B lớn hơn sẽ cụ thể hơn; nếu 2 giá trị B cũng bằng nhau, thì độ cụ thể có giá trị C lớn hơn sẽ cụ thể hơn; nếu tất cả các giá trị đều bằng nhau, thì 2 độ cụ thể sẽ bằng nhau.
Ví dụ: (1,0,0) được coi là có độ đặc hiệu cao hơn (0,4,3) vì giá trị A trong (1,0,0) (là 1) lớn hơn giá trị A trong (0,4,3) (là 0).
Bộ chọn ảnh hưởng đến độ cụ thể
Mỗi phần trong bộ ba tính cụ thể bắt đầu bằng giá trị 0, vì vậy, tính cụ thể mặc định là (0,0,0).
Mỗi phần của bộ chọn sẽ làm tăng độ cụ thể, tuỳ thuộc vào loại bộ chọn, hãy tăng giá trị của A, B hoặc C.
Bộ chọn chung
Bộ chọn chung (*) không thêm độ đặc hiệu, giữ nguyên giá trị ở độ đặc hiệu ban đầu là (0,0,0).
* {
color: red;
}
Bộ chọn phần tử hoặc bộ chọn phần tử giả
Bộ chọn phần tử (loại) hoặc giả phần tử sẽ thêm độ đặc hiệu giống như phần tử, giúp tăng thành phần C thêm 1.
Các ví dụ sau đây có độ đặc hiệu tổng thể là (0,0,1).
Bộ chọn loại
div {
color: red;
}
Bộ chọn phần tử giả
::selection {
color: red;
}
Bộ chọn lớp, bộ chọn giả lớp hoặc bộ chọn thuộc tính
Bộ chọn lớp, giả lớp hoặc thuộc tính sẽ thêm độ đặc hiệu giống như lớp, giúp tăng thành phần B thêm 1.
Các ví dụ sau đây có độ đặc hiệu là (0,1,0).
Bộ chọn lớp
.my-class {
color: red;
}
Bộ chọn lớp giả
:hover {
color: red;
}
Bộ chọn thuộc tính
[href='#'] {
color: red;
}
Bộ chọn mã nhận dạng
Bộ chọn mã nhận dạng sẽ thêm độ cụ thể giống như mã nhận dạng, giúp tăng thành phần A thêm 1, miễn là bạn sử dụng bộ chọn mã nhận dạng (#myID) chứ không phải bộ chọn thuộc tính ([id="myID"]).
Trong ví dụ sau, độ đặc hiệu là (1,0,0)
#myID {
color: red;
}
Bộ chọn khác
CSS có nhiều bộ chọn. Không phải từ nào cũng giúp tăng tính cụ thể.
Ví dụ: bản thân lớp giả :not() không thêm gì vào phép tính độ cụ thể.
Độ đặc hiệu của lớp giả :not() được thay thế bằng độ đặc hiệu của bộ chọn cụ thể nhất trong đối số bộ chọn được phân tách bằng dấu phẩy; cung cấp độ đặc hiệu tương tự như khi bạn viết :not(:is(argument)).
div:not(.my-class) {
color: red;
}
Bản thân lớp giả :is() cũng không được thêm vào phép tính độ đặc hiệu. Giống như :not(), nó lấy độ đặc hiệu của đối số cụ thể nhất.
:is(h1, h2, h3) {
color: blue;
}
Mẫu này có độ đặc hiệu là (0,0,1) vì chỉ có một loại bộ chọn (type).
Khi thêm id, độ đặc hiệu sẽ tăng lên (1,0,0).
:is(h1, h2, h3, #my-heading) {
color: blue;
}
Lớp giả :where() có sự khác biệt. Bất kể mức độ cụ thể của bất kỳ đối số nào, nó luôn có mức độ cụ thể là (0,0,0).
:where(h1, h2, h3, #my-heading) {
color: blue;
}
Các kiểu có độ đặc hiệu thấp được áp dụng bằng :where() cho phép bạn ghi đè các kiểu này bằng các bộ chọn cơ bản sau này trong biểu định kiểu:
:where(#my-content) {
color: red;
}
p {
color: blue;
}
Mặc dù :where() có id trong danh sách đối số, nhưng nó vẫn chỉ có độ đặc hiệu là (0, 0, 0), vì vậy, bộ chọn p cơ bản sẽ ghi đè bộ chọn này và văn bản sẽ là blue.
Kiểm tra kiến thức của bạn
Kiểm tra kiến thức của bạn về tính năng tính điểm độ đặc hiệu
Độ đặc hiệu của a[href="#"] là bao nhiêu?
(0,0,1)a có giá trị là (0,0,1), nhưng [href="#"] có giá trị là (0,1,0).(0,1,0)a có giá trị là (0,0,1), nhưng [href="#"] có giá trị là (0,1,0).(0,1,1)a có giá trị là (0,0,1) và [href="#"] có giá trị là (0,1,0), tổng độ đặc hiệu là (0,1,1).Các yếu tố không ảnh hưởng đến độ cụ thể
Có một số quan niệm sai lầm thường gặp về những yếu tố sau đây ảnh hưởng đến mức độ cụ thể.
Thuộc tính kiểu cùng dòng
CSS được áp dụng trực tiếp cho thuộc tính style của một phần tử, không ảnh hưởng đến độ cụ thể vì đây là một bước khác trong thứ tự xếp tầng được đánh giá trước độ cụ thể.
<div style="color: red"></div>
Để ghi đè khai báo này trong một biểu định kiểu, bạn phải dùng đến việc nhận được khai báo trong một bước trước đó của thứ tự xếp tầng.
Ví dụ: bạn có thể thêm !important vào đó
để trở thành một phần của nguồn gốc !important do người dùng tạo.
!important khai báo
Ký tự !important ở cuối một khai báo CSS không ảnh hưởng đến độ cụ thể nhưng đặt khai báo đó vào một nguồn gốc khác, cụ thể là Được tác giả !important.
Trong ví dụ sau, độ đặc hiệu của .my-class không liên quan đến việc khai báo !important để giành chiến thắng.
.my-class {
color: red !important;
color: white;
}
Khi hai khai báo là !important, thì độ cụ thể sẽ lại có tác dụng, vì bước nguồn gốc từ tầng không thể xác định người chiến thắng.
.branding {
color: blue !important;
}
button {
color: red !important;
}
Độ đặc hiệu trong bối cảnh
Khi một bộ chọn phức tạp hoặc bộ chọn kết hợp được sử dụng, mỗi phần của bộ chọn đó sẽ cộng vào độ cụ thể. Hãy xem xét ví dụ về HTML này:
<a class="my-class another-class" href="#">A link</a>
Đường liên kết này có 2 lớp học.
Quy tắc trong CSS sau đây có độ cụ thể là (0,0,1):
a {
color: red;
}
Nếu bạn tham chiếu một trong các lớp trong bộ chọn, thì lớp đó hiện có độ cụ thể là (0,1,1):
a.my-class {
color: green;
}
Thêm lớp kia vào bộ chọn, giờ lớp đó có độ cụ thể là (0,2,1):
a.my-class.another-class {
color: rebeccapurple;
}
Thêm thuộc tính href vào bộ chọn, bộ chọn này hiện có độ đặc hiệu là (0,3,1):
a.my-class.another-class[href] {
color: goldenrod;
}
Cuối cùng,hãy thêm một giả lớp :hover vào tất cả những điều đó, bộ chọn sẽ kết thúc với độ đặc hiệu là (0,4,1):
a.my-class.another-class[href]:hover {
color: lightgrey;
}
Kiểm tra kiến thức của bạn
Kiểm tra kiến thức của bạn về tính năng tính điểm độ đặc hiệu
Bộ chọn nào sau đây có độ đặc hiệu là (0,2,1)?
article > section(0,0,2).article.card.dark(0,2,1).article:hover a[href](0,0,1)), một bộ chọn thuộc tính (trị giá (0,1,0)) và một bộ chọn lớp (trị giá (0,1,0)). Điều này khiến bộ chọn này có độ cụ thể tổng cộng là (0,2,2).Tăng tính cụ thể một cách thực tế
Giả sử bạn có một số CSS như sau:
.my-button {
background: blue;
}
button[onclick] {
background: grey;
}
Với HTML có dạng như sau:
<button class="my-button" onclick="alert('hello')">Click me</button>
Nút này có nền màu xám, vì bộ chọn thứ hai có độ đặc hiệu là (0,1,1).
Nguyên nhân là vì bộ chọn này có một bộ chọn kiểu (button), đó là (0,0,1) và một bộ chọn thuộc tính ([onclick]), đó là (0,1,0).
Quy tắc trước đó – .my-button – bằng (0,1,0) vì quy tắc này có một bộ chọn lớp, có độ cụ thể thấp hơn (0,1,1).
Nếu muốn tăng cường quy tắc này, bạn có thể lặp lại bộ chọn lớp như sau:
.my-button.my-button {
background: blue;
}
button[onclick] {
background: grey;
}
Giờ đây, nút này sẽ có nền màu xanh dương, vì bộ chọn mới có độ cụ thể (0,2,0)
Nếu có mức độ cụ thể bằng nhau, thì sẽ chuyển sang bước tiếp theo trong tầng
Tiếp tục với ví dụ về nút, hãy chuyển CSS thành:
.my-button {
background: blue;
}
[onclick] {
background: grey;
}
Nút này có nền màu xám, vì cả hai bộ chọn đều có độ đặc hiệu giống hệt nhau là (0,1,0).
Nếu bạn chuyển đổi các quy tắc theo thứ tự nguồn, thì nút này sẽ chuyển sang màu xanh dương.
[onclick] {
background: grey;
}
.my-button {
background: blue;
}
Nguyên nhân là do cả hai bộ chọn đều có độ đặc hiệu như nhau. Trong trường hợp này, thác sẽ quay lại bước thứ tự xuất hiện.