Menu

::before và ::after trong CSS: pseudo-element kèm ví dụ

::before và ::after chèn nội dung sinh ra làm con đầu tiên và con cuối cùng của một phần tử, ngay từ CSS. Tìm hiểu thuộc tính content, vì sao bắt buộc phải có content rỗng, cách định vị chúng, tooltip bằng attr(), bộ đếm và những chỗ chúng không hoạt động.

Trang này có trình soạn thảo chạy trực tiếp. Sửa, chạy và xem đầu ra ngay lập tức.

::before và ::after làm gì

::before chèn một hộp làm con đầu tiên của phần tử và ::after chèn làm con cuối cùng. Nội dung trong hộp do thuộc tính content quyết định. HTML không thêm gì cả: trình duyệt tạo ra hộp này từ CSS.

HTML chỉ chứa 9 và Tests pass. Ký hiệu đô la, nhãn "/ month" và dấu tích đều đến từ CSS. Chúng kế thừa style của phần tử (font, màu) trừ khi bạn ghi đè, như các ví dụ trên.

Cú pháp

selector::before {
  content: "text";   /* required */
  /* any other styles */
}

selector::after {
  content: "";       /* empty string: a box with no text */
}
Giá trị contentKết quả
"text"Một chuỗi. Dùng "\A" để xuống dòng (kèm white-space: pre), "\2192" cho một ký tự Unicode (→)
""Một hộp rỗng, dùng cho hình khối và trang trí
attr(data-label)Giá trị của một thuộc tính của phần tử
counter(step)Giá trị của một bộ đếm CSS
open-quote / close-quoteDấu ngoặc kép theo ngôn ngữ của phần tử
none hoặc normalKhông có pseudo-element (normal là mặc định)

content là bắt buộc. Không có nó, ::before và ::after không bao giờ được tạo ra, dù bạn đặt bao nhiêu thuộc tính khác.

Hình trang trí với content: ""

Với content: "", pseudo-element là một hộp rỗng mà bạn có thể đặt kích thước và tô màu. Mặc định nó là inline, mà hộp inline bỏ qua width và height, nên hãy đặt display: block, inline-block hoặc position: absolute:

Định vị pseudo-element

Với phần trang trí nằm đè lên hoặc bao quanh phần tử, hãy dùng position: absolute cho pseudo-element và position: relative cho chính phần tử, để các khoảng lệch được tính từ phần tử đó:

Chú ý thứ tự khi kết hợp với pseudo-class: trạng thái đứng trước, rồi mới đến pseudo-element, .link:hover::after, không bao giờ là .link::after:hover.

Đọc thuộc tính bằng attr(): tooltip

attr() lấy giá trị của một thuộc tính đưa vào content, nên chỉ một quy tắc có thể hiện chữ khác nhau trên từng phần tử:

Tooltip chỉ hiện khi hover sẽ vô hình với người dùng bàn phím và màn hình cảm ứng. Với nội dung quan trọng, hãy đặt chữ ngay trên trang, hoặc hiện thêm khi :focus với tabindex="0" trên phần tử.

Đánh số bằng bộ đếm

Bộ đếm CSS (counter) và ::before đánh số mà không cần gõ tay các con số:

Thêm hoặc bớt một bước, các con số tự cập nhật.

Chỗ ::before và ::after không hoạt động

Pseudo-element được chèn vào bên trong phần tử, giữa thẻ mở và thẻ đóng. Phần tử nào không có phần bên trong thì không hiển thị được chúng:

  • <img>, <video>, <iframe> (phần tử thay thế)
  • <input>, <select>, <textarea> (điều khiển form) và <br>

Một số trình duyệt vẽ chúng trên checkbox hoặc ảnh lỗi, nhưng không nhất quán. Hãy đặt pseudo-element lên phần tử bọc: <span class="field"><input></span> rồi định dạng .field::after.

Lỗi thường gặp

  • Không có content. Lý do phổ biến nhất khiến không có gì hiện ra. Hãy thêm content: "".
  • Đặt kích thước cho pseudo-element inline. width và height không có tác dụng cho đến khi bạn đặt display: block, inline-block hoặc position: absolute.
  • Sai thứ tự với trạng thái. a:hover::after hoạt động; a::after:hover thì không.
  • Định vị tuyệt đối mà cha không được định vị. Khi đó pseudo-element căn theo một phần tử tổ tiên ở xa nào đó. Hãy thêm position: relative cho phần tử.
  • Đặt nội dung thật trong CSS. Chữ trong content không thể chọn hay sao chép. Hãy giữ thông tin trong HTML.

Câu hỏi thường gặp

::before trong CSS dùng để làm gì?

Nó tạo một pseudo-element là con đầu tiên của phần tử được chọn, chứa nội dung mà thuộc tính content chỉ định. ::after làm điều tương tự ở vị trí con cuối cùng. Cả hai đều không có trong HTML, nên rất tiện để làm icon, nhãn và trang trí.

Vì sao ::before hoặc ::after của tôi không hiện?

Lý do phổ biến nhất là thiếu thuộc tính content: không có nó thì pseudo-element không được tạo ra. Dùng content: "" cho một hộp trang trí rỗng. Các nguyên nhân khác: pseudo-element inline có width và height (hãy đặt display: block hoặc inline-block), hoặc phần tử như <img> hay <input> không thể chứa chúng.

:before và ::before khác nhau thế nào?

Về hoạt động thì không khác gì. ::before với hai dấu hai chấm là cú pháp hiện hành dùng để đánh dấu pseudo-element; :before với một dấu hai chấm là cách viết cũ từ CSS2 mà trình duyệt vẫn chấp nhận cho before, after, first-line và first-letter.

Có dùng ::before cho img hoặc input được không?

Không ổn định. Pseudo-element được chèn vào bên trong nội dung của phần tử, mà các phần tử thay thế như <img> và điều khiển form như <input> không có vùng nội dung để chứa chúng. Hãy bọc phần tử trong <span> hoặc <div> và đặt pseudo-element lên phần tử bọc.

Trình đọc màn hình có đọc được nội dung ::before trong CSS không?

Nhìn chung là có: chữ trong content thường được tính vào tên truy cập (accessible name), nhưng không thể chọn hay sao chép. Hãy giữ thông tin thật trong HTML và dùng pseudo-element cho trang trí và các gợi ý thị giác nhỏ.

Hình minh họa các ngôn ngữ lập trình của Coddy

Học lập trình cùng Coddy

Bắt đầu