Add a Rule to an Element Only If It Has a Certain Child

add a rule to an element only if it has a certain child

If it is not possible with CSS, then it is not possible with LESS, which compiles to plain old vanilla CSS.

The problem is, that the LESS is compiled without knowledge of the HTML it is applied to, and without any client side scripting. Therefore, it is impossible to achieve anything with LESS that can not be achieved by using CSS alone.

You could achieve what you want by using client side javascript, or you could wait until CSS4 comes out, and use the parent selectors to the same effect as what you want.

CSS selector - element with a given child

Is it possible to select an element if it contains a specific child element?

Unfortunately not yet.

The CSS2 and CSS3 selector specifications do not allow for any sort of parent selection.



A Note About Specification Changes

This is a disclaimer about the accuracy of this post from this point onward. Parent selectors in CSS have been discussed for many years. As no consensus has been found, changes keep happening. I will attempt to keep this answer up-to-date, however be aware that there may be inaccuracies due to changes in the specifications.


An older "Selectors Level 4 Working Draft" described a feature which was the ability to specify the "subject" of a selector. This feature has been dropped and will not be available for CSS implementations.

The subject was going to be the element in the selector chain that would have styles applied to it.

Example HTML
<p><span>lorem</span> ipsum dolor sit amet</p>
<p>consecteture edipsing elit</p>

This selector would style the span element

p span {
color: red;
}

This selector would style the p element

!p span {
color: red;
}

A more recent "Selectors Level 4 Editor’s Draft" includes "The Relational Pseudo-class: :has()"

:has() would allow an author to select an element based on its contents. My understanding is it was chosen to provide compatibility with jQuery's custom :has() pseudo-selector*.

In any event, continuing the example from above, to select the p element that contains a span one could use:

p:has(span) {
color: red;
}

* This makes me wonder if jQuery had implemented selector subjects whether subjects would have remained in the specification.

Inject css rule for specific element children

Give the specific container an additional, generated class name and add a style element (here's how) with the relevant rule, e.g.:

.array-container.width-28 > span { width : 28px }

...if the width you want is 28px.

You'd change this line:

container.setAttribute('class','array-container');

to

container.className = 'array-container width-' + width;

Keep track of the style elements you add so that if you need a value twice, you don't have to add a second style element for the same value.

Here's a really quick and dirty example: Live Copy

<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>Dynamic Style Example</title>
<style>
.array-container span {
display: inline-block;
border: 1px solid #08f;
height: 1em;
}
</style>
</head>
<body>
<label>Add elements with width:
<input type="number" value="10" min="10" max="10000" id="width-to-use">
</label>
<input type="button" value="Add" id="btn-add">
<script>
(function() {
document.getElementById("btn-add").onclick = function() {
var width, div, css, style;

width = parseInt(document.getElementById("width-to-use").value, 10);
if (isNaN(width)) {
return;
}

div = document.createElement('div');
div.innerHTML =
"<span></span>" +
"<span></span>" +
"<span></span>";
div.className = "array-container width-" + width;

if (document.getElementById("style-width-" + width) === null) {
css = ".array-container.width-" + width + " span { " +
"width: " + width + "px; " +
"}";
style = document.createElement('style');
style.id = "style-width-" + width;
style.type = "text/css";
if (style.styleSheet){
style.styleSheet.cssText = css;
}
else {
style.appendChild(document.createTextNode(css));
}
document.getElementsByTagName("head")[0].appendChild(style);
}

document.body.appendChild(div);
};
function display(msg) {
var p = document.createElement('p');
p.innerHTML = String(msg);
document.body.appendChild(p);
}
})();
</script>
</body>
</html>

Apply CSS styles to an element depending on its child elements

As far as I'm aware, styling a parent element based on the child element is not an available feature of CSS. You'll likely need scripting for this.

It'd be wonderful if you could do something like div[div.a] or div:containing[div.a] as you said, but this isn't possible.

You may want to consider looking at jQuery. Its selectors work very well with 'containing' types. You can select the div, based on its child contents and then apply a CSS class to the parent all in one line.

If you use jQuery, something along the lines of this would may work (untested but the theory is there):

$('div:has(div.a)').css('border', '1px solid red');

or

$('div:has(div.a)').addClass('redBorder');

combined with a CSS class:

.redBorder
{
border: 1px solid red;
}

Here's the documentation for the jQuery "has" selector.

Apply a CSS rule to an element if it only occurs once in a parent

You can do that with :only-of-type:

h2:only-of-type {
padding-bottom: 20px;
}

If you need to apply the style only when the lone h2 is the first child, you should not replace the :first-child with :only-of-type but add it so you have both pseudo-classes:

h2:first-child:only-of-type {
padding-bottom: 20px;
}

How to generalize a CSS rule to specific children of the same element without repeating the parent's reserved word?

As G-Cyrillus suggested, you can use one of the pseudo-classes :is() or :where() to list multiple element types at the end of your article > … selector:

article > :is(h2, h3, p, picture) {
margin-left: 16px;
margin-right: 16px;
}
<article>Inside an article:
<h1>h1 (shouldn’t be styled)</h1>
<h2>h2</h2>
<p>p</p>
<picture>Inside a pic:
<h2>h2 that is not a direct child of the article (shouldn’t be styled)</h2>
</picture>
</article>

different css style only for children of a certain div

You're looking for the descendant combinator: A space. For instance:

#navbar li {
/* styles */
}

That will only apply the styles to li elements that are descendants of #navbar.

You have to use it on every rule. If you want syntax more like what you have in your question, there are preprocessors that do that sort of thing: Sass, Less, and such.

But with just CSS itself, you need to repeat the #navbar on every rule.

How to add CSS if element has more than one child?

You can't directly 'count' total numbers of elements in CSS, so there's no way to only apply the class if there's 2 or more divs (you'd need JavaScript for that).

But a possible workaround is to apply the class to all divs in the td...

td > div {
margin-bottom: 10px;
}

... and then override/disable it with a different style when there's only one element. That indirectly lets you add the style when there's 2+ more child elements.

td > div:only-child {
margin-bottom: 0px;
}

Alternatively you can apply to every div after the first one, if that happens to work for your situation.

td > div:not(:first-child) {
margin-bottom: 10px;
}

Edit: Or as Itay says in the comment, use a sibling selector

td > div + div {
margin-bottom: 10px;
}


Related Topics



Leave a reply



Submit