Lớp học giả

Podcast CSS – 015: Lớp học giả

Giả sử bạn có biểu mẫu đăng ký email, và bạn muốn trường biểu mẫu email có đường viền màu đỏ nếu trường đó chứa địa chỉ email không hợp lệ. Bạn làm được như thế nào? Bạn có thể sử dụng lớp giả :invalid CSS, là một trong nhiều lớp giả do trình duyệt cung cấp.

Lớp giả cho phép bạn áp dụng kiểu dựa trên các thay đổi về trạng thái và các yếu tố bên ngoài. Tức là thiết kế của bạn có thể phản ứng với hoạt động đầu vào của người dùng, chẳng hạn như địa chỉ email không hợp lệ. Những vấn đề này được đề cập trong mô-đun bộ chọn, và học phần này sẽ hướng dẫn bạn một cách chi tiết hơn.

Không giống như phần tử giả, bạn có thể tìm hiểu thêm trong mô-đun trước, lớp giả kết nối với các trạng thái cụ thể mà phần tử có thể chứa thay vì thường tạo kiểu cho các phần của phần tử đó.

Các trạng thái tương tác

Các lớp giả sau đây được áp dụng do hoạt động tương tác của người dùng với trang của bạn.

:hover

Hỗ trợ trình duyệt

  • Chrome: 1.
  • Cạnh: 12.
  • Firefox: 1.
  • Safari: 2.

Nguồn

Nếu người dùng có một thiết bị trỏ như chuột hoặc bàn di chuột, và đặt lên trên một phần tử bạn có thể chuyển sang trạng thái đó bằng :hover để áp dụng kiểu. Đây là một cách hữu ích để gợi ý rằng có thể tương tác với một phần tử.

:active

Hỗ trợ trình duyệt

  • Chrome: 1.
  • Cạnh: 12.
  • Firefox: 1.
  • Safari: 1.

Nguồn

Trạng thái này được kích hoạt khi bạn đang tương tác với một phần tử – chẳng hạn như lượt nhấp — trước khi lượt nhấp được huỷ bỏ. Nếu một thiết bị trỏ như chuột được sử dụng, trạng thái này là khi lượt nhấp bắt đầu và chưa được phát hành.

:focus, :focus-within:focus-visible

Hỗ trợ trình duyệt

  • Chrome: 1.
  • Cạnh: 12.
  • Firefox: 1.
  • Safari: 1.

Nguồn

Nếu một phần tử có thể nhận tiêu điểm (chẳng hạn như <button>) bạn có thể phản ứng với trạng thái đó bằng Lớp giả :focus.

Bạn cũng có thể phản ứng nếu một phần tử con của phần tử nhận được tiêu điểm bằng :focus-within.

Các thành phần có thể lấy tiêu điểm, như nút, sẽ hiển thị vòng lấy nét khi chúng được lấy nét — ngay cả khi được nhấp vào. Trong loại tình huống này, nhà phát triển sẽ áp dụng CSS sau:

button:focus {
    outline: none;
}

CSS này sẽ xoá vòng tiêu điểm mặc định của trình duyệt khi một phần tử nhận tiêu điểm, dẫn đến vấn đề hỗ trợ tiếp cận đối với những người dùng thao tác trên trang web bằng bàn phím. Nếu không có kiểu tiêu điểm, họ sẽ không thể theo dõi vị trí hiện tại của tiêu điểm khi sử dụng phím tab. Với :focus-visible bạn có thể trình bày kiểu lấy tiêu điểm khi một phần tử nhận được tiêu điểm thông qua bàn phím, đồng thời sử dụng quy tắc outline: none để ngăn chặn khi một thiết bị con trỏ tương tác với quy tắc đó.

button:focus {
    outline: none;
}

button:focus-visible {
    outline: 1px solid black;
}

:target

Hỗ trợ trình duyệt

  • Chrome: 1.
  • Cạnh: 12.
  • Firefox: 1.
  • Safari: 1.3.

Nguồn

:target pseudo-class chọn một phần tử có id khớp với một phân đoạn URL. Giả sử bạn có HTML sau:

<article id="content">
    …
</article>

Bạn có thể đính kèm kiểu cho phần tử đó khi URL chứa #content.

#content:target {
    background: yellow;
}

Điều này rất hữu ích khi làm nổi bật những khu vực có thể đã được liên kết cụ thể, chẳng hạn như nội dung chính trên trang web thông qua đường liên kết bỏ qua.

Các tiểu bang lịch sử

Hỗ trợ trình duyệt

  • Chrome: 1.
  • Cạnh: 12.
  • Firefox: 1.
  • Safari: 1.

Nguồn

:link có thể áp dụng lớp giả cho bất kỳ phần tử <a> nào có giá trị href chưa được truy cập.

:visited

Bạn có thể tạo kiểu cho một đường liên kết mà người dùng đã truy cập bằng cách sử dụng Lớp giả :visited. Đây là trạng thái đối lập với :link nhưng bạn có ít thuộc tính CSS hơn để sử dụng lý do bảo mật. Bạn chỉ có thể tạo kiểu cho color, background-color, border-color, outline-color và màu của SVG fillstroke.

Vấn đề về đơn đặt hàng

Nếu bạn xác định kiểu :visited, nó có thể bị ghi đè bằng một lớp giả của đường liên kết với độ cụ thể ít nhất là bằng nhau. Do đó, Bạn nên sử dụng quy tắc LVHA cho việc định kiểu các đường liên kết có lớp giả theo thứ tự cụ thể: :link, :visited, :hover, :active.

a:link {}
a:visited {}
a:hover {}
a:active {}

Các trạng thái trên biểu mẫu

Các lớp giả sau đây có thể chọn các phần tử biểu mẫu, ở các trạng thái khác nhau mà các phần tử này có thể ở trong quá trình tương tác với chúng.

:disabled:enabled

Hỗ trợ trình duyệt

  • Chrome: 1.
  • Cạnh: 12.
  • Firefox: 1.
  • Safari: 3.1.

Nguồn

Nếu là một phần tử biểu mẫu, chẳng hạn như <button> sẽ bị trình duyệt tắt, bạn có thể chuyển sang trạng thái đó bằng Lớp giả :disabled. :enabled có sẵn lớp pseudo cho trạng thái ngược lại mặc dù các thành phần biểu mẫu cũng là :enabled theo mặc định, do đó, bạn có thể không tiếp cận được với lớp giả này.

:checked:indeterminate

Hỗ trợ trình duyệt

  • Chrome: 1.
  • Cạnh: 12.
  • Firefox: 1.
  • Safari: 3.1.

Nguồn

:checked lớp giả khả dụng khi có phần tử biểu mẫu hỗ trợ, chẳng hạn như hộp đánh dấu hoặc nút chọn đang ở trạng thái đã đánh dấu.

Trạng thái :checked là trạng thái nhị phân(true hoặc false), nhưng các hộp đánh dấu vẫn có trạng thái ở giữa khi không được đánh dấu hoặc bỏ đánh dấu. Đây được gọi là Trạng thái :indeterminate.

Một ví dụ về trạng thái này là khi bạn có tuỳ chọn "chọn tất cả" để chọn tất cả các hộp đánh dấu trong một nhóm. Sau đó, nếu người dùng chọn bỏ chọn một trong các hộp kiểm này, hộp đánh dấu gốc sẽ không thể hiện "tất cả" nữa đang được kiểm tra, do đó nên được đưa vào trạng thái không xác định.

Phần tử <progress> cũng có trạng thái không xác định và có thể được tạo kiểu. Một trường hợp sử dụng phổ biến là tạo đường kẻ sọc để thể hiện việc không biết cần thêm bao nhiêu nữa.

:placeholder-shown

Hỗ trợ trình duyệt

  • Chrome: 47.
  • Cạnh: 79.
  • Firefox: 51.
  • Safari: 9.

Nguồn

Nếu một trường biểu mẫu có thuộc tính placeholderkhông có giá trị, :placeholder-shown bạn có thể dùng lớp giả để đính kèm kiểu cho trạng thái đó. Ngay khi có nội dung trên trường, cho dù ứng dụng có placeholder hay không, trạng thái này sẽ không còn được áp dụng.

Trạng thái xác thực

Hỗ trợ trình duyệt

  • Chrome: 10.
  • Cạnh: 12.
  • Firefox: 4.
  • Safari: 5.

Nguồn

Bạn có thể phản hồi xác thực biểu mẫu HTML bằng các lớp giả như :valid! :invalid:in-range. Các lớp giả :valid:invalid rất hữu ích cho các ngữ cảnh chẳng hạn như trường email có pattern cần được so khớp, trở thành trường hợp lệ. Người dùng có thể thấy trạng thái giá trị hợp lệ này, giúp họ hiểu rằng họ có thể chuyển sang lĩnh vực tiếp theo một cách an toàn.

Lớp giả :in-range có sẵn nếu một đầu vào có minmax, chẳng hạn như nhập vào số giá trị nằm trong các giới hạn đó.

Với biểu mẫu HTML, bạn có thể xác định rằng một trường là bắt buộc bằng thuộc tính required. :required lớp giả sẽ có sẵn cho các trường bắt buộc. Bạn có thể chọn các trường không bắt buộc bằng Lớp giả :optional.

Chọn các phần tử theo chỉ mục, thứ tự và số lần xuất hiện của chúng

Có một nhóm lớp giả chọn các mục dựa trên vị trí của các mục đó trong tài liệu.

:first-child:last-child

Hỗ trợ trình duyệt

  • Chrome: 4.
  • Cạnh: 12.
  • Firefox: 3.
  • Safari: 3.1.

Nguồn

Nếu bạn muốn tìm mục đầu tiên hoặc mục cuối cùng, bạn có thể sử dụng :first-child:last-child. Các lớp giả này sẽ trả về phần tử đầu tiên hoặc phần tử cuối cùng trong một nhóm các phần tử đồng cấp.

:only-child

Hỗ trợ trình duyệt

  • Chrome: 2.
  • Cạnh: 12.
  • Firefox: 1.5.
  • Safari: 3.1.

Nguồn

Bạn cũng có thể chọn các phần tử không có đồng cấp, với Lớp giả :only-child.

:first-of-type:last-of-type

Hỗ trợ trình duyệt

  • Chrome: 1.
  • Cạnh: 12.
  • Firefox: 3.5.
  • Safari: 3.1.

Nguồn

Bạn có thể chọn :first-of-type:last-of-type lúc đầu, trông giống như chúng làm điều tương tự như :first-child:last-child, nhưng hãy xem xét HTML sau:

<div class="my-parent">
    <p>A paragraph</p>
    <div>A div</div>
    <div>Another div</div>
</div>

Và CSS này:

.my-parent div:first-child {
    color: red;
}

Không phần tử nào được tô màu đỏ vì phần tử con đầu tiên là một đoạn chứ không phải một div. Lớp giả :first-of-type rất hữu ích trong ngữ cảnh này.

.my-parent div:first-of-type {
    color: red;
}

Mặc dù <div> đầu tiên là con thứ hai, đây vẫn là phần tử đầu tiên thuộc loại này trong phần tử .my-parent. khi áp dụng quy tắc này, mã sẽ có màu đỏ.

:nth-child:nth-of-type

Hỗ trợ trình duyệt

  • Chrome: 1.
  • Cạnh: 12.
  • Firefox: 3.5.
  • Safari: 3.1.

Nguồn

Bạn không bị giới hạn ở con đầu tiên và con cuối cùng cũng như loại dữ liệu. :nth-child:nth-of-type lớp giả cho phép bạn chỉ định một phần tử nằm trong chỉ mục nhất định. Quá trình lập chỉ mục trong bộ chọn CSS bắt đầu từ 1.

Bạn cũng có thể truyền nhiều chỉ mục vào các lớp giả này. Nếu muốn chọn tất cả các phần tử chẵn, bạn có thể sử dụng :nth-child(even).

Bạn cũng có thể tạo các bộ chọn phức tạp hơn để tìm các mục theo khoảng thời gian thường xuyên, bằng cách dùng cú pháp vi mô An+B.

li:nth-child(3n+3) {
    background: yellow;
}

Bộ chọn này chọn mọi mục thứ ba, bắt đầu từ mục 3. n trong biểu thức này là chỉ mục, giá trị này bắt đầu từ 0 và 3 (3n) là số tiền bạn nhân với chỉ số đó.

Giả sử bạn có 7 mục <li>. Mục đầu tiên được chọn là 3 vì 3n+3 dịch sang (3 * 0) + 3. Lần lặp tiếp theo sẽ chọn mục 6 vì n hiện đã tăng lên 1, nên (3 * 1) + 3). Biểu thức này dùng được cho cả :nth-child:nth-of-type.

Bạn có thể thử dùng loại bộ chọn này trên người kiểm thử con thứ n hoặc điều này công cụ chọn số lượng.

:only-of-type

Hỗ trợ trình duyệt

  • Chrome: 1.
  • Cạnh: 12.
  • Firefox: 3.5.
  • Safari: 3.1.

Nguồn

Cuối cùng, bạn có thể tìm thấy phần tử duy nhất thuộc một loại nhất định trong một nhóm anh chị em cùng với :only-of-type. Điều này rất hữu ích nếu bạn muốn chọn danh sách chỉ có một mục, hoặc nếu bạn muốn tìm phần tử in đậm duy nhất trong một đoạn.

Tìm phần tử trống

Đôi khi có thể hữu ích khi xác định các phần tử hoàn toàn trống, và cũng có một lớp giả cho việc đó.

:empty

Hỗ trợ trình duyệt

  • Chrome: 1.
  • Cạnh: 12.
  • Firefox: 1.
  • Safari: 3.1.

Nguồn

Nếu một phần tử không có phần tử con thì phần tử Lớp giả :empty sẽ áp dụng cho các lớp này. Tuy nhiên, phần tử con không chỉ là các phần tử HTML hoặc nút văn bản: chúng còn có thể là khoảng trắng, điều này có thể gây nhầm lẫn khi bạn gỡ lỗi HTML sau đây và thắc mắc tại sao HTML này không hoạt động với :empty:

<div>
</div>

Lý do là có một số khoảng trắng giữa phần mở và đóng <div>, vì vậy trống sẽ không hoạt động.

Lớp giả :empty có thể hữu ích nếu bạn có ít quyền kiểm soát đối với HTML và muốn ẩn các phần tử trống, chẳng hạn như trình soạn thảo nội dung WYSIWYG. Ở đây, người chỉnh sửa đã thêm một đoạn trống, không liên quan.

<article class="post">
 <p>Donec ullamcorper nulla non metus auctor fringilla.</p>
 <p></p>
 <p>Curabitur blandit tempus porttitor.</p>
</article>

Với :empty, bạn có thể tìm và ẩn thông tin đó.

.post :empty {
    display: none;
}

Tìm và loại trừ nhiều phần tử

Một số lớp giả giúp bạn viết CSS nhỏ gọn hơn.

:is()

Hỗ trợ trình duyệt

  • Chrome: 88.
  • Cạnh: 88.
  • Firefox: 78.
  • Safari: 14.

Nguồn

Nếu bạn muốn tìm tất cả phần tử con h2, liimg trong phần tử .post, bạn có thể nghĩ đến việc viết một danh sách bộ chọn như sau:

.post h2,
.post li,
.post img {
    
}

Với :is() giả, bạn có thể viết một phiên bản nhỏ gọn hơn:

.post :is(h2, li, img) {
    
}

Lớp giả :is không chỉ nhỏ gọn hơn danh sách bộ chọn mà còn dễ truy cập hơn. Trong hầu hết các trường hợp, nếu có lỗi hoặc bộ chọn không được hỗ trợ trong danh sách bộ chọn, toàn bộ danh sách bộ chọn sẽ không hoạt động nữa. Nếu có lỗi trong các bộ chọn đã truyền trong lớp giả :is, thì hệ thống sẽ bỏ qua bộ chọn không hợp lệ nhưng hãy sử dụng các bộ chọn hợp lệ.

:not()

Hỗ trợ trình duyệt

  • Chrome: 1.
  • Cạnh: 12.
  • Firefox: 1.
  • Safari: 3.1.

Nguồn

Bạn cũng có thể loại trừ các mục có Lớp giả :not(). Ví dụ: bạn có thể dùng đối tượng này để tạo kiểu cho mọi đường liên kết không có thuộc tính class.

a:not([class]) {
    color: blue;
}

Lớp giả :not cũng có thể giúp bạn cải thiện khả năng hỗ trợ tiếp cận. Ví dụ: <img> phải có alt, ngay cả khi đó là giá trị trống, để bạn có thể viết quy tắc CSS thêm đường viền màu đỏ đậm vào hình ảnh không hợp lệ:

img:not([alt]) {
    outline: 10px red;
}

Kiểm tra kiến thức

Kiểm tra kiến thức về lớp giả

Lớp giả hoạt động như thể một lớp được áp dụng động cho một phần tử, trong khi các phần tử giả tự hoạt động trên chính phần tử đó.

Đúng
Chú ý đến việc sử dụng một : đơn hoặc kép làm ký tự phân biệt khoá trong bộ chọn
Sai
Phần tử giả là dành cho các bộ phận, Lớp giả là dành cho trạng thái.

Lớp nào sau đây là lớp giả chức năng?

:is()
🎉
:target
Các lớp giả chức năng có () theo sau để cho biết các lớp này chấp nhận các tham số.
:empty
Các lớp giả chức năng có () theo sau để cho biết các lớp này chấp nhận các tham số.
:not()
🎉

Lớp giả nào sau đây là do tương tác của người dùng?

:hover
🎉
:press
Hãy thử lại!
:squeeze
Hãy thử lại!
:target
🎉
:focus-within
🎉

Phần nào sau đây là lớp giả trạng thái <form>?

:enabled
🎉
:fresh
Hãy thử lại!
:indeterminate
🎉
:checked
🎉
:in-range
🎉
:loading
Hãy thử lại!
:valid
🎉