search
HomeWeb Front-endCSS TutorialCreating Animated, Clickable Cards With the :has() Relational Pseudo Class

Creating Animated, Clickable Cards With the :has() Relational Pseudo Class

Chrome and Safari browsers have fully supported the :has() pseudo-class of CSS, which is gradually being launched in many browsers. It is often called a "parent selector" - we can select and set the style of the parent element through child selectors - but :has() is used far more than that. One of the uses is to redesign the clickable card mode that many people often use.

We will explore :has()How to help us with link cards, but first...

:has()What is a pseudo-class?

There are many excellent articles that explain the purpose of :has() well, but it is still relatively new, so we should also briefly introduce it here.

:has() is a relational pseudo-class that is part of the W3C selector level 4 working draft. This is what brackets are for: match elements associated with a specific child element (more precisely, containing a specific child element).

<code>/* 匹配包含图像元素的article元素 */
article:has(img) { }

/* 匹配article元素,其内部直接包含图像 */
article:has(> img) { }</code>

So you can understand why we might refer to it as a "parent" selector. But we can also use it in conjunction with other functional pseudo-classes to get a more specific match. Suppose we want to style the article does not contain any images. We can combine the relationship ability of with the negative ability of :has() to achieve this: :not()

<code>/* 匹配不包含图像的article元素 */
article:not(:has(img)) { }</code>
But this is just the beginning of how we can combine various capabilities to achieve more functions using

. Before we specifically solve the clickable card puzzle, let's take a look at some of the ways to deal with them without using :has(). :has()

How do we currently deal with clickable cards

Nowadays, there are three main ways for people to create fully clickable cards. In order to fully understand the powerful functions of this pseudo-class, it is necessary to summarize it.

"Link as wrapper" method

This method is often used. I never use this method, but I created a quick demo to demonstrate it:

There are many issues here, especially when it comes to accessibility. When users browse your website using the rotator feature, they hear the full text inside the

element - title, text, and link. Some people may not want to listen to all of this. We can do better. Starting with HTML5, we can nest block elements in <a></a> elements. But this always feels wrong to me, especially for this reason. <a></a>

Pros:

    Quickly implement
  • Semantic correct

Disadvantages:

    Accessibility Issues
  • Text not selectable
  • It's very troublesome to override the styles used in the default link
JavaScript Method

With JavaScript, we can attach links to cards instead of writing them into tags. I found this awesome CodePen demo by costdev, which also makes card text optional in the process:

This method has many benefits. Our links are accessible when focused and we can even select text. But there are some disadvantages in terms of style. For example, if we want to animate these cards, we have to add the .card style in the :hover main wrapper instead of the link itself. We also don't benefit from animation when the link is focused through the keyboard tab keys.

Pros:

  • Full accessibility can be achieved
  • Selectable text

Disadvantages:

  • JavaScript is required
  • Cannot right-click (although it can be fixed with some extra scripts)
  • A lot of styles are required to be done on the card itself, which does not work when focusing on the links

::afterSelector method

This method requires us to set the card to relative positioning and then set the absolute positioning on the linked ::after pseudo selector. This does not require any JavaScript and is easy to implement:

There are some drawbacks here, especially when it comes to selecting text. You won't be able to select text unless you provide a higher z-index on the card body, but if you do, be aware that clicking on text won't activate your link. Whether you want selectable text is up to you. I think this might be a UX issue, but it depends on the use case. The text is still accessible via a screen reader, but my main problem with this approach is the lack of animation possibilities.

Pros:

  • Easy to implement
  • Accessible links, no redundant text
  • Effected when hovering and focusing

Disadvantages:

  • Text not selectable
  • You can only animate the link because this is the element you hover.

A new method: use ::after in combination with :has()

Now that we have identified existing methods for clickable cards, I would like to show how to add :has() to the mix to solve most of these shortcomings.

In fact, let's base this approach on the method we last viewed using ::after on the link element. We can actually use :has() there to overcome the animation limitations of the method.

Let's start with the marker:

<code>/* 匹配包含图像元素的article元素 */
article:has(img) { }

/* 匹配article元素,其内部直接包含图像 */
article:has(> img) { }</code>

To keep it simple, I will position elements directly in CSS, instead of using classes.

For this demo, we will add image scaling and shadows to the card for hovering and animate the links so that the arrow pops up and changes the text color of the links. To simplify operations, we will add some scoped custom properties to the card. This is the basic style:

<code>/* 匹配包含图像元素的article元素 */
article:has(img) { }

/* 匹配article元素,其内部直接包含图像 */
article:has(> img) { }</code>

Very good! We have added the initial scaling (--img-scale: 1.001), the initial color of the card title (--title-color: black) and some extra properties we will use to make the arrow pop up from the link. We also set the empty state of the box-shadow declaration to be animate it later. This sets the basis for the clickable cards we need to create now, so let's add some resets and styles by adding these custom properties to the elements we want to animate:

<code>/* 匹配不包含图像的article元素 */
article:not(:has(img)) { }</code>

Let's be user-friendly and add a class hidden in the screen reader behind the link:

<img src="/static/imghwm/default1.png" data-src="https://img.php.cn/?x-oss-process=image/resize,p_40" class="lazy" alt="Creating Animated, Clickable Cards With the :has() Relational Pseudo Class "><div clas="article-body">
    <h2 id="Some-Heading">Some Heading</h2>
    <p>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.</p>
    <a href="https://www.php.cn/link/93ac0c50dd620dc7b88e5fe05c70e15b">
      Read more
       <svg fill="currentColor" viewbox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path clip-rule="evenodd" d="M12.293 5.293a1 1 0 011.414 0l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414-1.414L14.586 11H3a1 1 0 110-2h11.586l-2.293-2.293a1 1 0 010-1.414z" fill-rule="evenodd"></path></svg></a>
  </div>

Our cards are starting to look beautiful. It's time to add some magic to it. Using the :has() pseudo-class, we can now check if our link is hovered or focused, then update our custom properties and add box-shadow. With this small amount of CSS code, our cards are truly come to life:

/* 卡片元素 */
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: https://www.php.cn/link/93ac0c50dd620dc7b88e5fe05c70e15bfff;
  transform-origin: center;
  transition: all 0.4s ease-in-out;
  overflow: hidden;
}
/* 链接的::after伪元素 */
article a::after {
  content: "";
  position: absolute;
  inset-block: 0;
  inset-inline: 0;
  cursor: pointer;
}

Did you see the above content? Now, if any child elements in the card are hovered or focused, we will get updated styles. Even if the link element is the only element that can contain a hover or focus state in the clickable card method, we can use it to match the parent element and apply the transformation. ::afterThat's it. Another powerful use case for selectors. We can not only match the parent element by declaring other elements as parameters, but also use pseudo-classes to match and set the style of the parent element.

:has()Pros:

Accessible

    Anime can be set
  • No JavaScript required
  • Use on the correct element
  • :hover
  • Disadvantages:

Text is not easy to choose.

    Browser support is limited to Chrome and Safari (in Firefox, it is supported behind the logo).
  • This is a demonstration using this technique. You may notice an extra wrapper around the card, but this is just a few of the attempts I made when using container queries, which is just one of some other great features that are being launched in all major browsers.
Do you have some other examples you want to share? The comments section is very welcome to other solutions or ideas.

The above is the detailed content of Creating Animated, Clickable Cards With the :has() Relational Pseudo Class. For more information, please follow other related articles on the PHP Chinese website!

Statement
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Simulating Mouse MovementSimulating Mouse MovementApr 22, 2025 am 11:45 AM

If you've ever had to display an interactive animation during a live talk or a class, then you may know that it's not always easy to interact with your slides

Powering Search With Astro Actions and Fuse.jsPowering Search With Astro Actions and Fuse.jsApr 22, 2025 am 11:41 AM

With Astro, we can generate most of our site during our build, but have a small bit of server-side code that can handle search functionality using something like Fuse.js. In this demo, we’ll use Fuse to search through a set of personal “bookmarks” th

Undefined: The Third Boolean ValueUndefined: The Third Boolean ValueApr 22, 2025 am 11:38 AM

I wanted to implement a notification message in one of my projects, similar to what you’d see in Google Docs while a document is saving. In other words, a

In Defense of the Ternary StatementIn Defense of the Ternary StatementApr 22, 2025 am 11:25 AM

Some months ago I was on Hacker News (as one does) and I ran across a (now deleted) article about not using if statements. If you’re new to this idea (like I

Using the Web Speech API for Multilingual TranslationsUsing the Web Speech API for Multilingual TranslationsApr 22, 2025 am 11:23 AM

Since the early days of science fiction, we have fantasized about machines that talk to us. Today it is commonplace. Even so, the technology for making

Jetpack Gutenberg BlocksJetpack Gutenberg BlocksApr 22, 2025 am 11:20 AM

I remember when Gutenberg was released into core, because I was at WordCamp US that day. A number of months have gone by now, so I imagine more and more of us

Creating a Reusable Pagination Component in VueCreating a Reusable Pagination Component in VueApr 22, 2025 am 11:17 AM

The idea behind most of web applications is to fetch data from the database and present it to the user in the best possible way. When we deal with data there

Using 'box shadows' and clip-path togetherUsing 'box shadows' and clip-path togetherApr 22, 2025 am 11:13 AM

Let's do a little step-by-step of a situation where you can't quite do what seems to make sense, but you can still get it done with CSS trickery. In this

See all articles

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Tools

Atom editor mac version download

Atom editor mac version download

The most popular open source editor

SublimeText3 Linux new version

SublimeText3 Linux new version

SublimeText3 Linux latest version

mPDF

mPDF

mPDF is a PHP library that can generate PDF files from UTF-8 encoded HTML. The original author, Ian Back, wrote mPDF to output PDF files "on the fly" from his website and handle different languages. It is slower than original scripts like HTML2FPDF and produces larger files when using Unicode fonts, but supports CSS styles etc. and has a lot of enhancements. Supports almost all languages, including RTL (Arabic and Hebrew) and CJK (Chinese, Japanese and Korean). Supports nested block-level elements (such as P, DIV),

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

SecLists

SecLists

SecLists is the ultimate security tester's companion. It is a collection of various types of lists that are frequently used during security assessments, all in one place. SecLists helps make security testing more efficient and productive by conveniently providing all the lists a security tester might need. List types include usernames, passwords, URLs, fuzzing payloads, sensitive data patterns, web shells, and more. The tester can simply pull this repository onto a new test machine and he will have access to every type of list he needs.