Is There a CSS Parent Selector

Is there a CSS parent selector?

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

If there was a way to do it, it would be in either of the current CSS selectors specs:

  • Selectors Level 3 Spec
  • CSS 2.1 Selectors Spec

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 */ }

However, as of 2022, it is only supported by Safari.

In the meantime, you'll have to resort to JavaScript if you need to select a parent element.

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

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.

How to select the parent's parent in CSS?

No not with CSS. Alternatively you may use a CSS class hen viewing for admin. So for an admin

<div id="maincontent" class="adminBackground">
<div id="content">
<div id="admin"></div>
</div>
</div>

And for normal visitors (notice that the class="adminBackground" attribute is removed):

<div id="maincontent">
<div id="content">
<div id="admin"></div>
</div>
</div>

Then define a role for that class "adminBackground":

.adminBackground {
background: #AAAAAA;
}

How to select Parent Div in CSS

I dont know the context here, but if you can't modify the html, this is possible with jQuery as follows:

<script>
jQuery('div.well').parent('div').css('background', 'red');
</script>

As others have noted, there is no CSS solution.

How can i select the parent element without child?

There are no parent selectors in CSS. Check:

Is there a CSS Parent selector?

Parent selectors in CSS

What you can do is styling both elements and then re-writing the style for the child. e.g.:

h1{
color:blue;
}

h1 > span{
color:black;
}

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>.


Related Topics



Leave a reply



Submit