Pseudo-class là gì
Pseudo-class là một từ khóa đứng sau dấu hai chấm, chọn phần tử theo vị trí trong tài liệu hoặc theo trạng thái của nó. Bạn gắn nó vào một selector thông thường: li:first-child, input:focus, a:hover.
Các pseudo-class trạng thái cho liên kết và chuột (:hover, :active, :visited) có trang riêng, CSS hover.
:nth-child() và công thức an+b
:nth-child() nhận một con số, một từ khóa, hoặc công thức an+b. Trình duyệt thử n = 0, 1, 2, ... và khớp với mọi vị trí mà công thức tạo ra (vị trí bắt đầu từ 1).
| Công thức | Khớp vị trí | Ý nghĩa |
|---|---|---|
3 | 3 | Phần tử con thứ ba |
odd hoặc 2n+1 | 1, 3, 5, ... | Các hàng lẻ |
even hoặc 2n | 2, 4, 6, ... | Các hàng chẵn |
3n | 3, 6, 9, ... | Cứ ba phần tử lấy một |
n+4 | 4, 5, 6, ... | Từ phần tử thứ tư trở đi |
-n+3 | 1, 2, 3 | Ba phần tử đầu tiên |
3n+1 | 1, 4, 7, ... | Cứ ba phần tử lấy một, bắt đầu từ phần tử đầu |
Gõ một công thức và xem những mục nào khớp:
Hãy thử odd, even, 4, n+7, -n+5 và 2n+3. Công thức không hợp lệ sẽ không khớp gì cả.
Phiên bản đếm từ cuối là :nth-last-child(): li:nth-last-child(-n+2) chọn hai mục cuối cùng.
nth-child và nth-of-type
:nth-child() đếm mọi phần tử anh em, bất kể thẻ gì, rồi mới kiểm tra phần còn lại của selector. :nth-of-type() chỉ đếm các phần tử anh em cùng thẻ. Khác biệt lộ ra ngay khi các phần tử anh em có nhiều loại thẻ:
Các cặp tương tự cũng có cho hai đầu: :first-child / :first-of-type, :last-child / :last-of-type, :only-child / :only-of-type.
:not(), :is() và :where()
| Pseudo-class | Ví dụ | Khớp với |
|---|---|---|
:not(X) | li:not(.done) | Các phần tử không khớp X |
:is(X, Y) | :is(h1, h2, h3) a | Các phần tử khớp bất kỳ mục nào trong danh sách |
:where(X, Y) | :where(ul, ol) li | Giống :is(), nhưng độ ưu tiên bằng 0 |
:has(X) | li:has(> input:checked) | Các phần tử chứa một phần tử khớp X |
:not() là cái được dùng hằng ngày, ví dụ để đặt dấu phân cách giữa các mục nhưng không đặt sau mục cuối:
Pseudo-class trạng thái: focus, checked, disabled, invalid
| Pseudo-class | Khớp với |
|---|---|
:focus | Phần tử đang được focus bằng bàn phím hoặc chuột |
:focus-visible | Đang được focus, và trình duyệt quyết định cần hiện vòng focus (thường là khi focus bằng bàn phím) |
:focus-within | Phần tử chứa phần tử đang được focus |
:checked | Checkbox, nút radio đã được chọn hoặc <option> đã được chọn |
:disabled / :enabled | Các điều khiển biểu mẫu bị (hoặc không bị) vô hiệu hóa |
:required / :optional | Ô nhập có hoặc không có required |
:invalid / :valid | Ô nhập có giá trị không qua hoặc qua được kiểm tra hợp lệ |
:user-invalid | Không hợp lệ, nhưng chỉ sau khi người dùng đã tương tác với nó |
:placeholder-shown | Ô nhập đang hiện placeholder |
:empty | Phần tử không có phần tử con nào, kể cả chữ |
:target | Phần tử có id khớp với #fragment của URL |
Bấm vào ô email: nhãn của nó chuyển sang màu xanh nhờ :focus-within. Gõ thứ gì đó không phải email rồi rời ô: :user-invalid đổi viền sang màu hổ phách. Nếu chỉ dùng :invalid, ô bắt buộc còn trống đã bị tô màu hổ phách trước cả khi bạn chạm vào.
Dù bạn làm gì với :focus, hãy luôn giữ một kiểu focus nhìn thấy được. Xóa outline mà không có gì thay thế khiến người dùng bàn phím không biết mình đang ở đâu.
:has(), selector cho phần tử cha
:has() khớp với một phần tử dựa trên những gì nó chứa. Đây chính là "selector cho phần tử cha" được mong đợi từ lâu, và nó hoạt động trong Chrome, Firefox và Safari hiện nay.
Chọn gói còn lại: cả thẻ thay đổi theo nút radio, không cần JavaScript.
Lỗi thường gặp
- Có dấu cách trước dấu hai chấm.
li :first-childnghĩa là "phần tử con đầu tiên bên trong một li". Hãy viếtli:first-child. - Nghĩ rằng
p:nth-child(1)là "thẻ p đầu tiên". Nó nghĩa là "phần tử con đầu tiên, nếu đó là thẻ p". Dùng:first-of-typeđể chọn thẻ p đầu tiên. - Đếm từ 0. Vị trí bắt đầu từ 1:
:nth-child(0)không khớp gì cả. - Xóa outline khi focus.
:focus { outline: none }mà không có gì thay thế sẽ làm hỏng việc điều hướng bằng bàn phím. - Nhầm
:với::.:beforelà cách viết cũ của pseudo-element::before; pseudo-class luôn dùng một dấu hai chấm.
Câu hỏi thường gặp
Pseudo-class trong CSS là gì?
Là một từ khóa đứng sau dấu hai chấm, chọn phần tử theo trạng thái hoặc vị trí chứ không theo tên, ví dụ a:hover, li:first-child hoặc input:focus. Nó được gắn vào một selector thông thường, và phần lớn pseudo-class được tính độ ưu tiên như một class (:where() tính bằng 0).
nth-child trong CSS hoạt động thế nào?
:nth-child(an+b) khớp với các phần tử có vị trí trong nhóm anh em là a×n+b với n = 0, 1, 2 và cứ thế, đếm từ 1. :nth-child(3) là phần tử con thứ ba, :nth-child(odd) hay 2n+1 là mọi phần tử ở vị trí lẻ, còn :nth-child(n+4) là từ phần tử thứ tư trở đi.
nth-child và nth-of-type khác nhau thế nào?
:nth-child() đếm mọi phần tử anh em, rồi mới kiểm tra phần còn lại của selector; :nth-of-type() chỉ đếm các phần tử anh em cùng loại thẻ. Trong một danh sách gồm một h2 rồi đến các đoạn văn, p:nth-child(1) không khớp gì cả, còn p:nth-of-type(1) khớp với đoạn văn đầu tiên.
Dùng :not() trong CSS thế nào?
Đặt selector cần loại trừ vào trong ngoặc: li:not(.done) khớp với mọi mục danh sách không có class done. Nó cũng nhận một danh sách, input:not([type="checkbox"], [type="radio"]).
Pseudo-class và pseudo-element khác nhau thế nào?
Pseudo-class (một dấu hai chấm, :hover) chọn cả một phần tử có sẵn ở một trạng thái nào đó. Pseudo-element (hai dấu hai chấm, ::before) nhắm vào một phần của phần tử hoặc tạo ra nội dung được sinh thêm.