:has() 案例研究

Swetha Gopalakrishnan
Swetha Gopalakrishnan
Saurabh Rajpal
Saurabh Rajpal

CSS 一直缺少一种根据其子元素直接选择父元素的方法。这多年来一直是开发者最热切期盼的功能。现在,所有主流浏览器都支持 :has() 选择器,它可以解决此问题。在 :has() 之前,您通常会链接长选择器或添加类来设置样式钩子。现在,您可以根据元素与其后代的关系来设置样式。如需详细了解 :has() 选择器,请参阅 CSS Wrapped 20235 个所有前端开发者都应掌握的 CSS 代码段

虽然此选择器看起来很小,但它可以支持大量用例。本文介绍了一些电子商务公司使用 :has() 选择器实现的用例。

:has() 属于新推出的基准组合

浏览器支持

  • Chrome:105。
  • 边缘:105。
  • Firefox:121。
  • Safari:15.4。

来源

请参阅本文所在的完整系列文章,其中介绍了电子商务公司如何使用新的 CSS 和界面功能增强其网站。

Policybazaar

借助 :has() 选择器,我们能够消除对用户选择基于 JavaScript 的验证,并将其替换为 CSS 解决方案,该解决方案能够顺畅运行,并提供与之前相同的体验。- Aman Soni,Policybazaar 技术主管

Policybazaar 的投资团队巧妙地应用了 :has() 选择器,为正在比较方案的用户提供清晰直观的指示。下图显示了比较界面中的两种方案(黄色和蓝色)。每种方案只能与其自身类型的方案进行比较。使用 :has() 后,当用户选择一种类型的方案时,就无法选择另一种方案类型。

实现 :has() 以设置父元素及其子元素的样式,从而创建类别绑定的选择功能。

代码

借助 :has(),您可以设置父元素及其子元素的样式。以下代码会检查父级容器是否设置了 .disabled-group 类。如果存在,系统会将 pointer-events 设置为 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);
}

Policybazaar 的健康团队实现了一个略有不同的用例。他们为用户提供了内嵌知识问答,并使用 :has() 检查题目复选框状态,以了解用户是否已回答相应题目。如果用户选择了“是”,系统会应用动画效果以转换到下一个问题。

health.policybazaar.com/

代码

在方案比较示例中,:has() 用于检查类是否存在。您还可以使用 :has(input:checked) 检查输入元素(例如复选框)的状态。在显示测验的视觉内容中,紫色横幅中的每个题目都是一个复选框。Policybazaar 会检查问题是否已使用 :has(input:checked) 回答,如果已回答,则使用 animation: quesSlideOut 0.3s 0.3s linear forwards 触发动画以滑动到下一个问题。请参阅以下代码,了解其运作方式。

.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 会使用 :has() 创建叠加图片。如果商品缩略图包含 .playIcon 类,系统会添加 CSS 叠加层。在这里,:has() 选择器与 & 嵌套选择器一起用于适用于所有缩略图的总体 .thumbnailWrapper 类中。这样可以创建更模块化且更易读的 CSS。

使用 has 选择器前后的 Tokopedia 页面屏幕截图。
使用 :has() 前后。

代码

以下代码使用 CSS 选择器和组合器&>)并通过嵌套 :has() 来设置缩略图的样式。对于不支持的浏览器,系统会使用常规的额外 CSS 类规则作为后备选项。@supports selector(:has(*)) 规则还用于检查浏览器支持情况。因此,不同浏览器版本的整体体验是相同的。

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;
    }
  }
`;

使用 :has() 时的注意事项

:has() 与其他选择器组合使用,以创建更复杂的条件。请查看 has() 系列选择器中的一些示例。

资源:

请浏览本系列中的其他文章,这些文章介绍了电子商务公司如何通过使用新的 CSS 和界面功能(例如滚动条驱动的动画、视图转换、弹出式窗口和容器查询)获益。