Css select parent based on child

I wonder why I have to follow "Tech Twitter" to find out the good news, so I'm the one to write a short post here on dev.to to celebrate a new CSS feature:

"Parent selectors", the second most awaited CSS feature according to State of CSS survey 2021, also known as the has-selector, have got browser support!

To quote Sara Soueidan quoting Jen Simmons on Twitter:

:has() is essentially the long-awaited parent selector in CSS 🎊

Don’t say Safari is always last. Sometimes we are first.

Css select parent based on child

But before celebrating this time's "Safari first", be aware that you might not have a browser to test parent selectors early in 2022 yet. Safari updates currently don't ship or install on older Apple operating systems.

No longer "Missing from CSS"

Now parent selectors are no longer missing from CSS, let's hope that Firefox and Chromium follow quickly.

Css select parent based on child

What does a "Parent Selector" select?

Parent selectors select parent elements, right? They actually select grandparents and any matching ancestors as well.

I haven't been the only one thinking of :has() as a "child selector", so should I call them "has-selectors" to avoid misunderstanding?

Timothy Huang called :has() "a CSS-selector that (selects) a parent with child which sounds like an appropriate description to me.

From caniuse.com/css-has:

For example, a:has(>img) selects all elements that contain an

Css select parent based on child

After watching Byungwoo Lee on YouTube, I would say that the Blink engine's strategy is somehow similar to the efficiency of a chess engine that must figure out how to ignore irrelevant moves quickly instead of predicting every possible outcome of every possible combination of moves.

In the case of CSS, the Blink engine will prevent walk up and invalidation on irrelevant elements. To reduce the irrelevant recalculations after applying the style, the engine can mark if a style is affected by a :has() state change during the recalculation.

But let Byungwoo Lee explain the details of the problems and solutions implementing parent selectors.

His explanation includes complex use cases like

.a:has(.b ~ .c)

or

.a:is(:has(b), :has(c))

Wow! I didn't even know that could be valid CSS.

Never stop learning! But still don't show code like that to me in a code review. I will probably request you to refactor that to something which is more easy to understand and maintain for the human brain!

Actual Use Case

As I see many people struggle to contrive examples how to make use of has selectors: lucky you!

Here is a real world example: I had to hotfix a Shopware theme that had already been hotfixed before, and it was urgent and !important, so no clean code at that part of the roadmap at least.

I wish I had been able to use :has() here, to lower the risk of accidentally targeting the wrong elements in the CMS-generated markup. The selector is so long that you have to scroll to see all of it!

/* override template heading style */
body.is-act-index .cms-sections .col-12 .cms-element-alignment.align-self-start {

Enter fullscreen mode Exit fullscreen mode

Using has makes the fix at least a little bit clearer:

/* override template heading style */
body.is-act-index .cms-element-alignment:has(> h2) {

Enter fullscreen mode Exit fullscreen mode

We might want to write that code just for the sake of readability. But we have to ensure browser support.

How to Polyfill :has() Selectors?

As there is no way to workaround parent selectors in recent CSS syntax, they can't be transpiled. Don't hope for PostCSS or SASS! This time you will need JavaScript to polyfill older browsers.

"jQuery has had the :has selector in its arsenal since basically forever", Eric Ponto wrote in 2015 already showing a polyfill based on jQuery:

Polyfill({
    selectors: [":has"]
}).doMatched(rules => {
    rules.each(rule => {
        // just pass it into jQuery since it supports `:has`
        $(rule.getSelectors()).css(rule.getDeclaration())
    });
});

Enter fullscreen mode Exit fullscreen mode

Quiz: How to polyfill without using jQuery?

Take the quiz and submit your Vanilla JS solution!

// TODO: add a parent selector polyfill without using jQuery

Enter fullscreen mode Exit fullscreen mode

If you know the solution, you can also post it as an answer to the StackOverflow question if there is a vanilla JS equivalent of jQuery .has().

querySelectorAllWithHas

Josh Larson's polyfill-css-has provides a querySelectorAllWithHas (thanks to @lukeshiru for the link!)

But we have managed to live without parent selectors for so long, maybe we don't want to worry anymore, and rather move on to there next upcoming upgrades to the CSS language:

What's next in CSS?

What to expect from CSS in 2022?

There are more useful features in the pipeline, like CSS Container Queries which we can already use in Chrome and Edge by enabling them using feature flags.

This article is part of a small series about new (and underrated) CSS features that you can start to learn and use in 2022.

How do I select parent child in CSS?

The element>element selector is used to select elements with a specific parent. Note: Elements that are not directly a child of the specified parent, are not selected.

Is there a parent selector in CSS?

Parent selector has been on developers' wishlist for more than 10 years and it has become one of the most requested CSS features alongside container queries ever since. The main reason this feature wasn't implemented all this time seems to be due to performance concerns.

What is a parent child selector?

The ("parent > child") selector selects all elements that are a direct child of the specified element.

Is there a SCSS parent selector?

The parent selector, & , is a special selector invented by Sass that's used in nested selectors to refer to the outer selector. It makes it possible to re-use the outer selector in more complex ways, like adding a pseudo-class or adding a selector before the parent.