Tiếng Việt

Khám phá bộ chọn CSS :has(), một yếu tố thay đổi cuộc chơi trong việc chọn phần tử cha. Tìm hiểu các ứng dụng thực tế, khả năng tương thích và các kỹ thuật nâng cao để cách mạng hóa cách viết CSS của bạn.

Làm chủ bộ chọn CSS :has(): Khai phá sức mạnh chọn phần tử cha

Trong nhiều năm, các nhà phát triển CSS đã mong mỏi có một cách đơn giản và hiệu quả để chọn các phần tử cha dựa trên các phần tử con của chúng. Sự chờ đợi đã kết thúc! Lớp giả :has() cuối cùng đã xuất hiện, và nó đang cách mạng hóa cách chúng ta viết CSS. Bộ chọn mạnh mẽ này cho phép bạn nhắm mục tiêu một phần tử cha nếu nó chứa một phần tử con cụ thể, mở ra một thế giới các khả năng tạo kiểu động và đáp ứng.

Bộ chọn :has() là gì?

Lớp giả :has() là một lớp giả quan hệ trong CSS, chấp nhận một danh sách bộ chọn làm đối số. Nó chọn một phần tử nếu bất kỳ bộ chọn nào trong danh sách đối số khớp với ít nhất một phần tử trong số các hậu duệ của phần tử đó. Nói một cách đơn giản hơn, nó kiểm tra xem một phần tử cha có sở hữu một phần tử con cụ thể hay không, và nếu có, phần tử cha sẽ được chọn.

Cú pháp cơ bản là:

parent:has(child) { /* Các quy tắc CSS */ }

Lệnh này chọn phần tử parent chỉ khi nó chứa ít nhất một phần tử child.

Tại sao :has() lại quan trọng đến vậy?

Theo truyền thống, CSS bị hạn chế trong khả năng chọn các phần tử cha dựa trên các phần tử con. Hạn chế này thường đòi hỏi các giải pháp JavaScript phức tạp hoặc các cách giải quyết tạm thời để đạt được kiểu dáng động. Bộ chọn :has() loại bỏ sự cần thiết của các phương pháp rườm rà này, cho phép mã CSS sạch hơn, dễ bảo trì hơn và hiệu suất cao hơn.

Đây là lý do tại sao :has() là một yếu tố thay đổi cuộc chơi:

Các ví dụ cơ bản về bộ chọn :has()

Hãy bắt đầu với một số ví dụ đơn giản để minh họa sức mạnh của bộ chọn :has().

Ví dụ 1: Tạo kiểu cho một Div cha dựa trên sự hiện diện của hình ảnh

Giả sử bạn muốn thêm một đường viền vào phần tử <div> chỉ khi nó chứa một phần tử <img>:

div:has(img) { border: 2px solid blue; }

Quy tắc CSS này sẽ áp dụng một đường viền màu xanh cho bất kỳ <div> nào chứa ít nhất một phần tử <img>.

Ví dụ 2: Tạo kiểu cho một mục danh sách dựa trên sự hiện diện của một Span

Giả sử bạn có một danh sách các mục, và bạn muốn làm nổi bật mục danh sách nếu nó chứa một phần tử <span> với một lớp cụ thể:

li:has(span.highlight) { background-color: yellow; }

Quy tắc CSS này sẽ thay đổi màu nền của bất kỳ <li> nào chứa một <span> với lớp "highlight" thành màu vàng.

Ví dụ 3: Tạo kiểu cho nhãn biểu mẫu dựa trên tính hợp lệ của trường nhập liệu

Bạn có thể sử dụng :has() để tạo kiểu cho nhãn biểu mẫu dựa trên việc trường nhập liệu liên quan của nó có hợp lệ hay không (kết hợp với lớp giả :invalid):

label:has(+ input:invalid) { color: red; font-weight: bold; }

Lệnh này sẽ làm cho nhãn có màu đỏ và in đậm nếu trường nhập liệu ngay sau nó không hợp lệ.

Các cách sử dụng nâng cao của bộ chọn :has()

Bộ chọn :has() trở nên mạnh mẽ hơn nữa khi kết hợp với các bộ chọn và lớp giả CSS khác. Dưới đây là một số trường hợp sử dụng nâng cao:

Ví dụ 4: Nhắm mục tiêu các phần tử trống

Bạn có thể sử dụng lớp giả :not() kết hợp với :has() để nhắm mục tiêu các phần tử *không* có một phần tử con cụ thể. Ví dụ, để tạo kiểu cho các div *không* chứa hình ảnh:

div:not(:has(img)) { background-color: #f0f0f0; }

Lệnh này sẽ áp dụng một nền màu xám nhạt cho bất kỳ <div> nào không chứa phần tử <img>.

Ví dụ 5: Tạo các bố cục phức tạp

Bộ chọn :has() có thể được sử dụng để tạo các bố cục động dựa trên nội dung của một vùng chứa. Ví dụ, bạn có thể thay đổi bố cục của một lưới dựa trên sự hiện diện của một loại phần tử cụ thể trong một ô lưới.

.grid-container { display: grid; grid-template-columns: repeat(3, 1fr); } .grid-item:has(img) { grid-column: span 2; }

Lệnh này sẽ làm cho một mục lưới kéo dài hai cột nếu nó chứa một hình ảnh.

Ví dụ 6: Tạo kiểu biểu mẫu động

Bạn có thể sử dụng :has() để tạo kiểu động cho các phần tử biểu mẫu dựa trên trạng thái của chúng (ví dụ: đang được focus, đã được điền, hoặc hợp lệ).

.form-group:has(input:focus) { box-shadow: 0 0 5px rgba(0, 0, 255, 0.5); } .form-group:has(input:valid) { border-color: green; } .form-group:has(input:invalid) { border-color: red; }

Lệnh này sẽ thêm một bóng hộp màu xanh khi trường nhập liệu được focus, một đường viền màu xanh lá nếu hợp lệ, và một đường viền màu đỏ nếu không hợp lệ.

Ví dụ 7: Tạo kiểu dựa trên số lượng phần tử con

Mặc dù :has() không trực tiếp đếm số lượng phần tử con, bạn có thể kết hợp nó với các bộ chọn và thuộc tính CSS khác để đạt được hiệu ứng tương tự. Ví dụ, bạn có thể sử dụng :only-child để tạo kiểu cho một phần tử cha nếu nó chỉ có một phần tử con thuộc loại cụ thể.

div:has(> p:only-child) { background-color: lightgreen; }

Lệnh này sẽ tạo kiểu cho một <div> với nền màu xanh lá nhạt chỉ khi nó chứa một phần tử <p> duy nhất làm con trực tiếp.

Khả năng tương thích trên các trình duyệt và phương án dự phòng

Tính đến cuối năm 2023, bộ chọn :has() được hỗ trợ rất tốt trên các trình duyệt hiện đại, bao gồm Chrome, Firefox, Safari và Edge. Tuy nhiên, việc kiểm tra khả năng tương thích trên Can I use trước khi triển khai trong môi trường sản xuất là rất quan trọng, đặc biệt nếu bạn cần hỗ trợ các trình duyệt cũ hơn.

Dưới đây là phân tích về các vấn đề tương thích:

Cung cấp phương án dự phòng (Fallbacks)

Nếu bạn cần hỗ trợ các trình duyệt cũ, bạn sẽ cần cung cấp các phương án dự phòng. Dưới đây là một vài chiến lược:

Đây là một ví dụ về việc sử dụng truy vấn tính năng:

.parent { /* Kiểu cơ bản cho tất cả trình duyệt */ border: 1px solid black; } @supports selector(:has(img)) { .parent:has(img) { /* Kiểu nâng cao cho các trình duyệt hỗ trợ :has() */ border: 3px solid blue; } }

Đoạn mã này sẽ áp dụng một đường viền màu đen cho phần tử .parent trên tất cả các trình duyệt. Trên các trình duyệt hỗ trợ :has(), nó sẽ áp dụng một đường viền màu xanh nếu phần tử .parent chứa một hình ảnh.

Những cân nhắc về hiệu suất

Mặc dù :has() mang lại những lợi thế đáng kể, điều cần thiết là phải xem xét tác động tiềm tàng của nó đối với hiệu suất, đặc biệt khi được sử dụng rộng rãi hoặc với các bộ chọn phức tạp. Trình duyệt cần phải đánh giá bộ chọn cho mọi phần tử trên trang, điều này có thể trở nên tốn kém về mặt tính toán.

Dưới đây là một số mẹo để tối ưu hóa hiệu suất của :has():

Những lỗi thường gặp cần tránh

Khi làm việc với bộ chọn :has(), rất dễ mắc phải những sai lầm có thể dẫn đến kết quả không mong muốn. Dưới đây là một số cạm bẫy phổ biến cần tránh:

Các phương pháp hay nhất khi sử dụng :has()

Để tối đa hóa lợi ích của bộ chọn :has() và tránh các vấn đề tiềm ẩn, hãy làm theo các phương pháp hay nhất sau:

Ví dụ thực tế và các trường hợp sử dụng

Hãy khám phá một số ví dụ thực tế về cách bộ chọn :has() có thể được sử dụng để giải quyết các thách thức thiết kế phổ biến.

Ví dụ 8: Tạo menu điều hướng đáp ứng

Bạn có thể sử dụng :has() để tạo các menu điều hướng đáp ứng, thích ứng với các kích thước màn hình khác nhau dựa trên sự hiện diện của các mục menu cụ thể.

Hãy tưởng tượng một kịch bản nơi bạn muốn hiển thị một menu điều hướng khác nhau tùy thuộc vào việc người dùng đã đăng nhập hay chưa. Nếu họ đã đăng nhập, bạn có thể hiển thị các hành động hồ sơ và đăng xuất, nếu không bạn có thể hiển thị đăng nhập/đăng ký.

nav:has(.user-profile) { /* Kiểu cho người dùng đã đăng nhập */ } nav:not(:has(.user-profile)) { /* Kiểu cho người dùng đã đăng xuất */ }

Ví dụ 9: Tạo kiểu cho các thành phần thẻ (Card)

Bộ chọn :has() có thể được sử dụng để tạo kiểu cho các thành phần thẻ dựa trên nội dung của chúng. Ví dụ, bạn có thể thêm bóng đổ vào một thẻ chỉ khi nó chứa một hình ảnh.

.card:has(img) { box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); }

Ví dụ 10: Triển khai các chủ đề động

Bạn có thể sử dụng :has() để triển khai các chủ đề động dựa trên sở thích của người dùng hoặc cài đặt hệ thống. Ví dụ, bạn có thể thay đổi màu nền của trang dựa trên việc người dùng có bật chế độ tối hay không.

body:has(.dark-mode) { background-color: #333; color: #fff; }

Những ví dụ này minh họa tính linh hoạt của bộ chọn :has() và khả năng giải quyết một loạt các thách thức thiết kế.

Tương lai của CSS: Điều gì tiếp theo?

Sự ra đời của bộ chọn :has() đánh dấu một bước tiến quan trọng trong sự phát triển của CSS. Nó cho phép các nhà phát triển tạo ra các bảng kiểu động, đáp ứng và dễ bảo trì hơn mà ít phụ thuộc vào JavaScript. Khi sự hỗ trợ của trình duyệt cho :has() tiếp tục tăng lên, chúng ta có thể mong đợi sẽ thấy nhiều cách sử dụng sáng tạo và đổi mới hơn nữa của bộ chọn mạnh mẽ này.

Nhìn về phía trước, CSS Working Group đang khám phá các tính năng và cải tiến thú vị khác sẽ tiếp tục mở rộng khả năng của CSS. Chúng bao gồm:

Bằng cách cập nhật những phát triển CSS mới nhất và đón nhận các tính năng mới như :has(), các nhà phát triển có thể khai phá toàn bộ tiềm năng của CSS và tạo ra những trải nghiệm web thực sự đặc biệt.

Kết luận

Bộ chọn :has() là một sự bổ sung mạnh mẽ cho bộ công cụ CSS, cho phép lựa chọn phần tử cha và mở ra những khả năng mới cho việc tạo kiểu động và đáp ứng. Mặc dù việc xem xét khả năng tương thích của trình duyệt và các tác động về hiệu suất là rất quan trọng, nhưng lợi ích của việc sử dụng :has() để có mã CSS sạch hơn, dễ bảo trì hơn và hiệu suất cao hơn là không thể phủ nhận. Hãy nắm bắt bộ chọn thay đổi cuộc chơi này và cách mạng hóa cách tạo kiểu CSS của bạn ngay hôm nay!

Hãy nhớ xem xét khả năng truy cập và cung cấp các cơ chế dự phòng cho các trình duyệt cũ hơn. Bằng cách tuân theo các phương pháp hay nhất được nêu trong hướng dẫn này, bạn có thể tận dụng toàn bộ tiềm năng của bộ chọn :has() và tạo ra những trải nghiệm web thực sự đặc biệt cho người dùng trên toàn cầu.