nghiên cứu điển hình về :has()

Swetha Gopalakrishnan
Swetha Gopalakrishnan
Saurabh Rajpal
Saurabh Rajpal

CSS nổi tiếng là thiếu cách chọn trực tiếp phần tử mẹ dựa trên các phần tử con. Đây là yêu cầu hàng đầu của các nhà phát triển trong nhiều năm. Bộ chọn :has() (hiện được tất cả các trình duyệt chính hỗ trợ) sẽ giải quyết vấn đề này. Trước :has(), bạn thường tạo chuỗi các bộ chọn dài hoặc thêm các lớp để tạo kiểu cho các móc. Giờ đây, bạn có thể tạo kiểu dựa trên mối quan hệ của một phần tử với các phần tử con cháu. Đọc thêm về bộ chọn :has() trong CSS Wrapped 20235 đoạn mã CSS mà mọi nhà phát triển giao diện người dùng đều nên biết.

Mặc dù bộ chọn này có vẻ nhỏ, nhưng có thể hỗ trợ rất nhiều trường hợp sử dụng. Bài viết này trình bày một số trường hợp sử dụng mà các công ty thương mại điện tử đã khai thác bằng bộ chọn :has().

:has() là một phần của Baseline Newly Available (Tính năng mới của Baseline).

Hỗ trợ trình duyệt

  • Chrome: 105.
  • Edge: 105.
  • Firefox: 121.
  • Safari: 15.4.

Nguồn

Hãy xem loạt bài viết đầy đủ mà bài viết này thuộc về. Loạt bài viết này thảo luận về cách các công ty thương mại điện tử nâng cao trang web của họ bằng cách sử dụng các tính năng mới về CSS và giao diện người dùng.

Policybazaar

Với bộ chọn :has(), chúng tôi có thể loại bỏ quy trình xác thực dựa trên JavaScript của lựa chọn của người dùng và thay thế bằng giải pháp CSS hoạt động mượt mà cho chúng tôi với cùng trải nghiệm như trước.—Aman Soni, Trưởng nhóm kỹ thuật, Policybazaar

Nhóm đầu tư của Policybazaar đã áp dụng bộ chọn :has() một cách khéo léo để cung cấp thông tin trực quan rõ ràng cho người dùng đang so sánh các gói. Hình ảnh sau đây cho thấy hai loại gói trong giao diện người dùng so sánh (vàng và xanh dương). Bạn chỉ có thể so sánh từng kế hoạch với loại kế hoạch tương ứng. Khi sử dụng :has(), khi người dùng chọn một loại gói, họ sẽ không thể chọn loại gói còn lại.

Triển khai :has() để tạo kiểu cho phần tử mẹ và các phần tử con của phần tử mẹ để tạo chức năng lựa chọn liên kết với danh mục.

:has() cho phép bạn định kiểu cho phần tử mẹ và phần tử con của phần tử mẹ đó. Đoạn mã sau đây sẽ kiểm tra xem vùng chứa mẹ có đặt lớp .disabled-group hay không. Nếu có, thẻ sẽ chuyển sang màu xám và nút "Thêm" sẽ không phản hồi các lượt nhấp bằng cách đặt pointer-events thành none.

.plan-group-container:has(.disabled-group) {
  opacity: 0.5;
  filter: grayscale(100%);
}

.plan-group-container:has(.disabled-section) .button {
  pointer-events: none;
  border-color: #B5B5B5;
  color: var(--text-primary-38-color);
  background: var(--input-border-color);
}

Nhóm sức khoẻ tại Policybazaar đã triển khai một trường hợp sử dụng khác một chút. Ứng dụng này có một bài kiểm tra nội tuyến cho người dùng và sử dụng :has() để kiểm tra trạng thái hộp đánh dấu câu hỏi để xem người dùng có trả lời câu hỏi hay không. Nếu có, một ảnh động sẽ được áp dụng để chuyển sang câu hỏi tiếp theo.

health.policybazaar.com/

Trong ví dụ so sánh kế hoạch, :has() được dùng để kiểm tra sự hiện diện của một lớp. Bạn cũng có thể kiểm tra trạng thái của một phần tử đầu vào như hộp đánh dấu bằng cách sử dụng :has(input:checked). Trong hình ảnh hiển thị bài kiểm tra, mỗi câu hỏi trong biểu ngữ màu tím là một hộp đánh dấu. Policybazaar kiểm tra xem câu hỏi đã được trả lời hay chưa bằng :has(input:checked). Nếu câu hỏi đã được trả lời, hãy kích hoạt ảnh động bằng animation: quesSlideOut 0.3s 0.3s linear forwards để chuyển sang câu hỏi tiếp theo. Hãy xem cách hoạt động của mã sau.

.segment_banner__wrap__questions {
 position: relative;
 animation: quesSlideIn 0.3s linear forwards;
}

.segment_banner__wrap__questions:has(input:checked) {
 animation: quesSlideOut 0.3s 0.3s linear forwards;
}


@keyframes quesSlideIn {
 from {
   transform: translateX(50px);
   opacity: 0;
 }
 to {
   transform: translateX(0px);
   opacity: 1;
 }
}

@keyframes quesSlideOut {
 from {
   transform: translateX(0px);
   opacity: 1;
 }
 to {
   transform: translateX(-50px);
   opacity: 0;
 }
}

Tokopedia

Tokopedia đã sử dụng :has() để tạo hình ảnh lớp phủ nếu hình thu nhỏ sản phẩm chứa video. Nếu hình thu nhỏ sản phẩm chứa lớp .playIcon, thì một lớp phủ CSS sẽ được thêm vào. Ở đây, bộ chọn :has() được sử dụng cùng với bộ chọn lồng ghép & trong lớp .thumbnailWrapper tổng quát áp dụng cho tất cả hình thu nhỏ. Điều này tạo ra CSS linh hoạt và dễ đọc hơn.

Ảnh chụp màn hình trang Tokopedia trước và sau khi sử dụng bộ chọn has.
Trước và sau khi sử dụng :has().

Mã sau đây sử dụng bộ chọn và bộ kết hợp CSS (&>) và lồng với :has() để tạo kiểu cho hình thu nhỏ. Đối với các trình duyệt không hỗ trợ, quy tắc lớp CSS bổ sung thông thường sẽ được dùng làm phương án dự phòng. Quy tắc @supports selector(:has(*)) cũng được dùng để kiểm tra khả năng hỗ trợ trình duyệt. Do đó, trải nghiệm tổng thể trên các phiên bản trình duyệt là giống nhau.

export const thumbnailWrapper = css`
  padding: 0;
  margin-right: 7px;
  border: none;
  outline: none;
  background: transparent;

  > div {
    width: 64px;
    height: 64px;
    overflow: hidden;
    cursor: pointer;
    border-color: ;
    position: relative;
    border: 2px solid ${NN0};
    border-radius: 8px;
    transition: border-color 0.25s;

    &.active {
      border-color: ${GN500};
    }

    @supports selector(:has(*)) {
      &:has(.playIcon) {
        &::after {
          content: '';
          display: block;
          background: rgba(0, 0, 0, 0.2);
          position: absolute;
          top: 0;
          left: 0;
          right: 0;
          bottom: 0;
        }
      }
    }

    & > .playIcon {
      position: absolute;
      top: 25%;
      left: 25%;
      width: 50%;
      height: 50%;
      text-align: center;
      z-index: 1;
    }
  }
`;

Những điều cần cân nhắc khi sử dụng :has()

Kết hợp :has() với các bộ chọn khác để tạo một điều kiện phức tạp hơn. Hãy xem một số ví dụ trong has() bộ chọn gia đình.

Tài nguyên:

Khám phá các bài viết khác trong loạt bài này, trong đó đề cập đến lợi ích của các công ty thương mại điện tử khi sử dụng các tính năng mới của CSS và giao diện người dùng, chẳng hạn như ảnh động do cuộn, chuyển đổi chế độ xem, cửa sổ bật lên và truy vấn vùng chứa.