使用 :has() 关系伪类 PlatoBlockchain 数据智能创建动画、可点击的卡片。 垂直搜索。 人工智能。

使用 :has() 关系伪类创建动画的、可点击的卡片

CSS :has() 伪类正在许多浏览器中推出 Safari 已经完全支持了。它通常被称为“父选择器”——例如,我们可以从子选择器中选择父元素的样式——但还有更多 :has() 可以帮我们解决。其中之一就是重新发明我们许多人不时喜欢使用的可点击卡片图案。

我们来看看如何 :has() 可以帮助我们处理链接卡,但首先……

这是什么 :has() 伪类?

已经有一个 of 职位 飘来飘去 很好地解释了什么 :has() 它是什么以及它的用途,但它仍然足够新,我们也应该在这里说几句话。

:has() 是一个关系伪类,它是 W3C 选择器 4 级工作草案。这就是括号的全部含义:匹配与某些子元素相关(或者更准确地说,包含某些子元素)的元素。

/* Matches an article element that contains an image element */
article:has(img) { }

/* Matches an article element with an image contained immediately within it */
article:has(> img) { }

因此,您可以明白为什么我们可能想将其称为“父”选择器。但我们也可以将它与其他函数伪类结合起来以获得更具体的结果。假设我们想要为文章设计样式 不能 包含任何图像。我们可以结合以下关系的力量 :has() 具有否定权 :not() 要做到这一点:

/* Matches an article without images  */
article:not(:has(img)) { }

但这只是我们如何结合力量做更多事情的开始 :has()。在我们专门解决可点击卡片难题之前,让我们先看看我们目前在不使用 :has().

我们目前如何处理可点击卡片

如今,人们如何创建完全可点击的卡片有三种主要方法,为了充分理解这个伪类的强大功能,最好进行一些总结。

这种方法是经常使用的方法。我从未使用过这种方法,但我创建了一个快速演示来演示它:

这里有很多问题,特别是在可访问性方面。当用户使用以下方式浏览您的网站时 转子函数,他们会听到其中的全文 元素 — 标题、文本和链接。有人可能不想经历这一切。我们可以做得更好。从 HTML5 开始,我们可以将块元素嵌套在 元素。但我总觉得这不对劲,尤其是因为这个原因。

优点:

  • 快速实施
  • 语义正确

缺点:

  • 无障碍问题
  • 文本不可选择
  • 覆盖默认链接上使用的样式很麻烦

JavaScript 方法

使用 JavaScript,我们可以将链接附加到卡片上,而不是将其写入标记中。我发现了这个很棒的 CodePen 演示 成本开发 在此过程中,他还使卡片文本可供选择:

这种方法有很多好处。我们的链接可以在焦点上访问,我们甚至可以选择文本。但在造型方面存在一些缺点。例如,如果我们想要为这些卡片添加动画,我们必须添加 :hover 我们主要的款式 .card 包装器而不是链接本身。当链接通过键盘选项卡聚焦时,我们也不会从动画中受益。

优点:

  • 可以完全无障碍
  • 选择文本的能力

缺点:

  • 需要 JavaScript
  • 无法右键单击(尽管可以通过一些额外的脚本来修复)
  • 卡片本身需要大量的样式,这在聚焦链接时不起作用

::after 选择器方法

该方法需要我们将卡片设置为相对定位,然后在链接上设置绝对定位 ::after 链接的伪选择器。这不需要任何 JavaScript 并且非常容易实现:

这里有一些缺点,特别是在选择文本时。除非您在卡体上提供更高的 z-index,否则您将无法选择文本,但如果您这样做,请注意单击文本将不会激活您的链接。是否需要可选文本取决于您。我认为这可能是用户体验问题,但这取决于用例。屏幕阅读器仍然可以访问文本,但该方法的主要问题是缺乏动画的可能性。

优点:

  • 易于实施
  • 没有臃肿文本的可访问链接
  • 适用于悬停和焦点

缺点:

  • 文本不可选择
  • 您只能为链接设置动画,因为这是您悬停的元素。

一种新方法:使用 ::after :has()

现在我们已经建立了可点击卡片的现有方法,我想展示如何引入 :has() 混合解决了大部分缺点。

事实上,让我们将这种方法建立在我们最后使用的方法的基础上 ::after 在链接元素上。我们实际上可以使用 :has() 克服该方法的动画限制。

让我们从标记开始:

Fluffy gray and white tabby kitten snuggled up in a ball.

Some Heading

Curabitur convallis ac quam vitae laoreet. Nulla mauris ante, euismod sed lacus sit amet, congue bibendum eros. Etiam mattis lobortis porta. Vestibulum ultrices iaculis enim imperdiet egestas.

我将通过定位 CSS 中的元素而不是类来使事情尽可能简单。

对于此演示,我们将在悬停时向卡片添加图像缩放和阴影,并通过弹出的箭头对链接进行动画处理,同时更改链接的文本颜色。为了使这一切变得简单,我们将在我们的卡上添加一些自定义属性。这是基本样式:

/* The card element */
article {
  --img-scale: 1.001;
  --title-color: black;
  --link-icon-translate: -20px;
  --link-icon-opacity: 0;

  position: relative;
  border-radius: 16px;
  box-shadow: none;
  background: #fff;
  transform-origin: center;
  transition: all 0.4s ease-in-out;
  overflow: hidden;
}
/* The link's ::after pseudo */
article a::after {
  content: "";
  position: absolute;
  inset-block: 0;
  inset-inline: 0;
  cursor: pointer;
}

伟大的!我们为图像添加了初始比例(--img-scale: 1.001)、卡片标题的初始颜色(--title-color: black)以及一些额外的属性,我们将使用这些属性使箭头从链接中弹出。我们还设置了一个空状态 box-shadow 声明以便稍后对其进行动画处理。这设置了我们现在所需的可点击卡片,因此让我们通过将这些自定义属性添加到我们想要设置动画的元素来添加一些重置和样式:

article h2 {
  margin: 0 0 18px 0;
  font-family: "Bebas Neue", cursive;
  font-size: 1.9rem;
  letter-spacing: 0.06em;
  color: var(--title-color);
  transition: color 0.3s ease-out;
}
article figure {
  margin: 0;
  padding: 0;
  aspect-ratio: 16 / 9;
  overflow: hidden;
}
article img {
  max-width: 100%;
  transform-origin: center;
  transform: scale(var(--img-scale));
  transition: transform 0.4s ease-in-out;
}
article a {
  display: inline-flex;
  align-items: center;
  text-decoration: none;
  color: #28666e;
}
article a:focus {
  outline: 1px dotted #28666e;
}
article a .icon {
  min-width: 24px;
  width: 24px;
  height: 24px;
  margin-left: 5px;
  transform: translateX(var(--link-icon-translate));
  opacity: var(--link-icon-opacity);
  transition: all 0.3s;
}

.article-body {
  padding: 24px;
}

让我们与人为善,并添加一个 屏幕阅读器类 隐藏在链接后面:

.sr-only:not(:focus):not(:active) {
  clip: rect(0 0 0 0); 
  clip-path: inset(50%);
  height: 1px;
  overflow: hidden;
  position: absolute;
  white-space: nowrap; 
  width: 1px;
}

我们的卡片开始看起来很可爱。是时候给它添加一点魔力了。随着 :has() 伪类,我们现在可以检查链接是否悬停或聚焦,然后更新我们的自定义属性并添加 box-shadow。有了这一小块 CSS,我们的卡片才真正变得栩栩如生:

/* Matches an article element that contains a hover or focus state */
article:has(:hover, :focus) {
  --img-scale: 1.1;
  --title-color: #28666e;
  --link-icon-translate: 0;
  --link-icon-opacity: 1;

  box-shadow: rgba(0, 0, 0, 0.16) 0px 10px 36px 0px, rgba(0, 0, 0, 0.06) 0px 0px 0px 1px;
}

看看上面有什么?现在我们得到更新的样式,如果 任何 卡片中的子元素悬停或聚焦。即使链接元素是唯一可以包含悬停或焦点状态的元素 ::after 可点击的卡片方法,我们可以使用它来匹配父元素并应用过渡。

现在你就得到了它。这只是另一个强大的用例 :has() 选择器。我们不仅可以通过将其他元素声明为参数来匹配父元素,而且还可以使用伪类来匹配父元素并为其设置样式。

优点:

  • 残疾人
  • 可动画化
  • 无需 JavaScript
  • 使用 :hover 在正确的元素上

缺点:

  • 文本不容易选择。
  • 浏览器支持仅限于 Chrome 和 Safari(Firefox 中支持该功能)。

这是使用此技术的演示。你可能会注意到卡片周围有一个额外的包装纸,但这只是我在玩弄 容器查询,这只是所有主要浏览器中推出的其他奇妙功能之一。

有一些 其他例子 你想分享吗?其他解决方案或想法非常欢迎在评论部分中提出。

时间戳记:

更多来自 CSS技巧