Latest on CSS Parent Selector

Is there a CSS parent selector?

There is currently no way to select the parent of an element in CSS in a way that works across all browsers.

That said, the Selectors Level 4 Working Draft includes a :has() pseudo-class that will provide this capability. It will be similar to the jQuery implementation.

li:has(> a.active) { /* styles to apply to the li tag */ }

As of 2022, it is only supported by Safari, and by Chromium browsers behind a flag.

In the meantime, you'll have to resort to JavaScript if you need to select a parent element with full cross-browser support.

Latest on CSS parent selector

The survey culminated in the subject selector (the proper name for the so-fabled "parent selector") being replaced with the far more versatile :has() pseudo-class, which is documented here (with an interesting anchor name, #relational, I wonder if that will stick).

Implementations will probably only arrive when the specification for this feature is more stable. Currently, with such disruptive changes as completely replacing the subject selector with a pseudo-class, I'm not banking on it happening anytime soon. That said, it is likely that the :has() pseudo-class will stick, but whether it can be implemented in CSS remains to be seen due to its very nature. See this section of the same draft to learn about implementation profiles.


The reason :has() is more versatile is because, with the subject selector, it was never made clear in any draft if a single complex selector could have more than one subject selector (since a single complex selector can only ever have one subject) and/or if functional pseudo-classes such as :matches() accepted the subject selector. But because a pseudo-class is a simple selector, it fits right into the existing selector syntax, and you can reliably assume that :has() will be accepted anywhere a pseudo-class is accepted.

As an example, this makes such selectors as the following quite theoretically possible:

/* 
* Select any p
* that is a sibling of a ul
* that has more than one li child.
*/
ul:has(> li:nth-of-type(2)) ~ p, /* p follows ul */
p:has(~ ul:has(> li:nth-of-type(2))) /* p precedes ul */

Whereas, using the subject selector, this would only be possible if :matches() accepted the subject selector, which was never stated directly in the spec:

ul:matches(! > li:nth-of-type(2)) ~ p, /* p follows ul */
!p ~ ul:matches(! > li:nth-of-type(2)) /* p precedes ul */

You can also see here why I dislike the name "parent selector" for either form of the selector — it can be used for so much more.

Select CSS Parent `selector` in iOS Content Blocking

Update:: has is now supported in Safari and Safari iOS. source: caniuse

There is currently no parent selector in css even though it is one of the most requested CSS feature.

The simple reason for the lack of implementation yet is performance issues.
https://snook.ca/archives/html_and_css/css-parent-selectors

The closest thing we have to a parent selector in CSS for now is :focus-within which will match an element if the element or any of its descendants is focused. However it is of no use in your case.

The proposed implementation of a parent selector as you mentioned is :has and is part of the level 4 of CSS selectors.

https://www.w3.org/TR/selectors-4/

Although it isn't implemented yet in any browser, it is now part of the technical preview for Safari so we might get it some day.
However it is not yet part of the technical preview for iOS and that might still take a lot of time.

https://caniuse.com/css-has

Even though there is no CSS parent selector, what you are describing can be easily achieved through Javascript in your Safari extension.

However you will need to give permissions to your Safari extension to inject scripts in the web page.

The users will have to accept the permissions. If they refuse you won't be able to access the page DOM through javascript.

You can do that by going in the manifest.json of your Xcode project : AppName => Shared (Extension) => Ressources => manifest

In content_scripts you will need to add

"content_scripts": [{
"js": [ "content.js" ],
"matches": [ "<all_urls>" ]
}]

You can also select the sites you want your extension to have access to with regular expressions like you did previously.

https://developer.apple.com/documentation/safariservices/safari_web_extensions/managing_safari_web_extension_permissions

Then in the content.js file you can add your javascript code to edit the web pages as you please.

Here is a function you could use to remove the parent of the bad elements:

const removeBadElementParent = () =>{
const badElements = document.querySelectorAll('.bad-class-name')
if(badElements.length === 0) return;

badElements.forEach(element =>{
if(!element instanceof HTMLElement) return;
const parent = element.parentElement;

if(!parent instanceof HTMLElement) return;
parent.style.display = 'none'
})
}

You don't want to use it immediately but only when the DOM has loaded so you will need to call it like this:

if( document.readyState !== 'loading' ) {
removeBadElementParent();
} else {
document.addEventListener("DOMContentLoaded", function(event) {
removeBadElementParent();
});
}

However most website make changes to the DOM and might add the bad elements after the DOMContentLoaded event has fired. So you will need to add a mutation observer to check when the DOM is changed:

const onDOMMutation = (callback) =>{
MutationObserver = window.MutationObserver || window.WebKitMutationObserver;
const observer = new MutationObserver(function(mutations, observer) {
callback();
});

observer.observe(document, {
subtree: true,
attributes: true
});
}

And you can call it like this instead of calling directly the removeBadElementParent function:

if( document.readyState !== 'loading' ) {
onDOMMutation(removeBadElementParent);
} else {
document.addEventListener("DOMContentLoaded", function(event) {
onDOMMutation(removeBadElementParent);
});
}

https://developer.apple.com/documentation/safariservices/safari_app_extensions/injecting_a_script_into_a_webpage

Complex CSS selector for parent of active child

Unfortunately, there's no way to do that with CSS.

It's not very difficult with JavaScript though:

// JavaScript code:
document.getElementsByClassName("active")[0].parentNode;

// jQuery code:
$('.active').parent().get(0); // This would be the <a>'s parent <li>.

Select parent selector when child is checked in SCSS/SASS

In this case, javascript would be more apropriated, since as of now we dont have a way to affect a parent element like this that works across all browsers.

SCSS modify parent selector

To make your last solution work, you can use @at-root.

body p {
& {
color: black;
}
@at-root #{selector-replace(&, "body", "body.other-mode")} {
color: red;
}
}

compiles to

body p {
color: black;
}
body.other-mode p {
color: red;
}

But personally, I find your original solution the most readable.

body { &.other-mode p {color: red;} }

I find the split body and p more convenient in SCSS.

CSS styling a child element from a parent element using selectors

You can use :nth-child() property of CSS! Try below-given code. I'm also attaching the link for working CodePen. To understand how it works you can play with it!

Visit the pen for more understanding and live demo: https://codepen.io/CUManiar/pen/vqGdze

.grand-parent {  color: blue;}
.grand-parent h2:nth-child(4) { color: red;}
.grand-parent .parent p:nth-child(2) { color: pink}
<div class="grand-parent">   Hi I am grandparent.     <h2 class="parent">        Hi I am parent.          <p class="child"> Hi I am grand child. </p>          <p class="child"> Hi I am 2nd grand child. </p>     </h2>     <h2 class="parent">        Hi I am parent.          <p class="child"> Hi I am 2nd child. </p>     </h2>     <h2 class="parent">        Hi I am parent.          <p class="child"> Hi I am 3rd child. </p>     </h2>     <h2 class="parent">        Hi I am parent.          <p class="child"> Hi I am 4th child. </p>     </h2>     <h2 class="parent">        Hi I am parent.          <p class="child"> Hi I am 5th child. </p>     </h2></div>


Related Topics



Leave a reply



Submit