


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>
. 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()
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
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
::after
Selector 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/imghw/default1.png" data-src="https://img.php.cn/" 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.
::after
That'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.
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!

Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

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

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics

The other day, I spotted this particularly lovely bit from Corey Ginnivan’s website where a collection of cards stack on top of one another as you scroll.

I see Google Fonts rolled out a new design (Tweet). Compared to the last big redesign, this feels much more iterative. I can barely tell the difference

Have you ever needed a countdown timer on a project? For something like that, it might be natural to reach for a plugin, but it’s actually a lot more

Questions about purple slash areas in Flex layouts When using Flex layouts, you may encounter some confusing phenomena, such as in the developer tools (d...

When the number of elements is not fixed, how to select the first child element of the specified class name through CSS. When processing HTML structure, you often encounter different elements...

Everything you ever wanted to know about data attributes in HTML, CSS, and JavaScript.

At the start of a new project, Sass compilation happens in the blink of an eye. This feels great, especially when it’s paired with Browsersync, which reloads

How to implement Windows-like in front-end development...
