Bài 3. Pseudo-class và pseudo-element

Pseudo-class chọn phần tử theo trạng thái (đang rê chuột, đang focus, là con đầu tiên...), pseudo-element tạo “phần ảo” của phần tử (dòng đầu, chữ đầu, nội dung chèn trước/sau). Đây là công cụ mạnh để làm giao diện tương tác mà không cần JavaScript.

45 phútCơ bản
Bạn sẽ học được
  • Dùng :hover, :focus, :focus-visible, :active, :visited
  • Chọn theo vị trí: :first-child, :nth-child(), :not()
  • Dùng ::before, ::after, ::first-letter, ::selection, ::placeholder
  • Dùng :has() làm “bộ chọn cha”
Thuật ngữ cần biết
Pseudo-class
Một dấu hai chấm, chọn theo trạng thái hoặc vị trí.
Pseudo-element
Hai dấu hai chấm, tạo phần ảo để định dạng.
content
Thuộc tính bắt buộc của ::before/::after.

Một số khái niệm

NhómVí dụÝ nghĩa
Tương tác:hover :focus :focus-visible :activeRê chuột, đang nhập, dùng bàn phím, đang bấm
Liên kết:link :visitedChưa xem / đã xem
Vị trí:first-child :last-child :nth-child(2n+1) :only-childTheo thứ tự trong cha
Theo loại:first-of-type :nth-of-type(3)Theo thứ tự cùng thẻ
Form:checked :disabled :required :invalid :placeholder-shownTrạng thái ô nhập
Logic:not() :is() :where() :has()Phủ định, nhóm, chọn cha

Công thức :nth-child(an+b): 2n hoặc even là chẵn, 2n+1 hoặc odd là lẻ, -n+3 là 3 phần tử đầu, 3n là mỗi phần tử thứ 3.

Trạng thái tương tác

<style>
  .nut { padding: 10px 18px; border: 0; border-radius: 8px; background: #2e7d32; color: #fff; cursor: pointer; transition: .2s; }
  .nut:hover { background: #1b5e20; transform: translateY(-2px); }
  .nut:active { transform: translateY(1px); }
  .nut:focus-visible { outline: 3px solid #ffb300; outline-offset: 2px; }
  input:focus { border-color: #1565c0; box-shadow: 0 0 0 3px #bbdefb; outline: none; }
  input { padding: 8px; border: 2px solid #ccc; border-radius: 6px; }
</style>
<button class="nut">Rê chuột, bấm, nhấn Tab</button>
<input placeholder="Bấm vào ô này">
Kết quả hiển thị

Chọn theo vị trí và :not()

<style>
  li:nth-child(odd) { background: #f1f8e9; }
  li:first-child { font-weight: 700; }
  li:last-child { color: #c62828; }
  li:not(:last-child) { border-bottom: 1px solid #ddd; }
  li { list-style: none; padding: 6px 10px; }
  ul { padding: 0; max-width: 300px; }
</style>
<ul><li>Sơn La</li><li>Điện Biên</li><li>Lai Châu</li><li>Hòa Bình</li><li>Lào Cai</li></ul>
Kết quả hiển thị

::before, ::after và các pseudo-element

<style>
  .moi::after { content: "MỚI"; margin-left: 6px; font-size: 11px; background: #e53935; color: #fff; padding: 1px 6px; border-radius: 10px; }
  .trich::before { content: "“"; font-size: 40px; color: #2e7d32; line-height: 0; vertical-align: -14px; margin-right: 4px; }
  .dau::first-letter { font-size: 2.4em; float: left; line-height: 1; margin-right: 6px; color: #1565c0; font-weight: 700; }
  ::selection { background: #ffeb3b; }
</style>
<p class="moi">Loạt bài Tailwind CSS</p>
<p class="trich">Học đi đôi với hành.</p>
<p class="dau">Tây Bắc là vùng núi phía tây bắc Bắc Bộ, nổi tiếng với ruộng bậc thang và mùa hoa ban. Hãy bôi đen đoạn này.</p>
Kết quả hiển thị

:has(): chọn phần tử cha

<style>
  .the { border: 2px solid #ddd; border-radius: 10px; padding: 10px; margin: 6px 0; }
  .the:has(input:checked) { border-color: #2e7d32; background: #e8f5e9; }
  label:has(+ input:required)::after { content: " *"; color: red; }
</style>
<label class="the" style="display:block"><input type="checkbox"> Chọn gói Cơ bản</label>
<label class="the" style="display:block"><input type="checkbox"> Chọn gói Nâng cao</label>
<label for="e">Email</label> <input id="e" required>
Kết quả hiển thị
Mẹo hay

Luôn giữ trạng thái focus nhìn thấy được cho người dùng bàn phím; nếu muốn bỏ viền khi bấm chuột, dùng :focus-visible thay vì xóa outline.

Lưu ý

::before/::after không hoạt động với phần tử rỗng như img, input, và bắt buộc có content (có thể là chuỗi rỗng "").

Thực hành
  1. Làm bảng kẻ sọc xen kẽ bằng tr:nth-child(even).
  2. Thêm biểu tượng ↗ sau liên kết ngoài bằng ::after.
  3. Tô viền xanh cho thẻ khi checkbox bên trong được chọn bằng :has().
  4. Làm chữ cái đầu đoạn văn to và nổi bật bằng ::first-letter.
Tóm tắt bài học
  • :hover, :focus-visible, :active cho tương tác.
  • :nth-child(), :first/last-child, :not() theo vị trí.
  • ::before/::after cần content; ::first-letter, ::selection, ::placeholder.
  • :has() chọn cha theo con.