:has() là selector cha — chọn element dựa trên thứ nằm bên trong nó.
Trước đây CSS không làm được việc này, phải nhờ JS gắn class.
css
/* card nào có ảnh thì đổi layout */
.card:has(img) { grid-template-columns: 120px 1fr; }
/* label đổi màu khi input bên trong invalid và đã nhập */
.field:has(input:user-invalid) { color: var(--rose-ink); }
/* form có checkbox đang tick thì hiện nút hành động hàng loạt */
.list:has(input[type="checkbox"]:checked) .bulk-actions { display: flex; }
/* chỉ thêm khoảng cách khi có heading đứng ngay trước đoạn văn */
h2:has(+ p) { margin-bottom: 8px; }Specificity lấy theo selector mạnh nhất bên trong (giống :is()), không phải 0 như :where().
Hỗ trợ: Baseline từ 2023 — Chrome 105+, Safari 15.4+, Firefox 121+.
Lưu ý 1: :has() không lồng được vào nhau và không dùng được với pseudo-element.
Lưu ý 2: với selector rộng như body:has(.modal-open) browser phải đánh giá lại mỗi khi DOM đổi. Neo vào phạm vi hẹp (.card:has(...)) thay vì *:has(...).
Chốt: dùng đúng chỗ thì :has() xoá được cả một lớp class trạng thái do JS gắn — đây là lý do nó hay được hỏi trong phỏng vấn CSS hiện đại.