Open srambach opened 7 years ago
Also see #1176
However, this doesn't allow styling of the parent based on the number of children.
Note that :has
cannot be used in style rules. It can be used by script:
const parents = document.querySelectorAll('a:has(> img)');
for (let parent of parents) {
const numChildren = parent.querySelectorAll('* > img').length;
if (numChildren > ...)
parent.style. ... = ...;
else
...
}
You might want to check out quantity queries which are kind of a selector hack that targets an element based on the number of siblings :D It's functionally similar to what you're asking for and supported in browsers right now, though it is a little ugly to look at and reason with.
Going the JS route, I've implemented responsive conditions like min-characters
, characters
, and max-characters
as element queries a couple of different ways that we can use in the meantime while we wait for browsers to support :has()
. You can use EQCSS as a custom syntax like this with (min-children: n)
or (children: n)
or (max-children: n)
:
<ul>
<li>one
</ul>
<ul>
<li>one
<li>two
</ul>
<ul>
<li>one
<li>two
<li>three
</ul>
<style>
@element ul and (children: 2) {
:self {
background: lime;
}
}
</style>
<script src=https://elementqueries.com/EQCSS.js></script>
as well as in CSS, parsed from CSSOM and run through javascript plugins like this:
<ul>
<li>one
</ul>
<ul>
<li>one
<li>two
</ul>
<ul>
<li>one
<li>two
<li>three
</ul>
<style>
@supports (--element("ul", {"children": 2})) {
[--self] {
background: lime;
}
}
</style>
<script type=module>
import deqaf from 'https://unpkg.com/deqaf/index.js'
import element from 'https://unpkg.com/jsincss-element-query/index.vanilla.js'
deqaf({stylesheet: {element}})
</script>
And I've also written a plugin for supporting the :has()
selector which would work too, if you wanted to target the <ul>
in the way that :has()
would using a quantity query, rather than by targeting the <li>
themselves as the quantity query selector would do:
<ul>
<li>one
</ul>
<ul>
<li>one
<li>two
</ul>
<ul>
<li>one
<li>two
<li>three
</ul>
<style>
ul[--has='"li:nth-last-child(n+2):nth-last-child(-n+2):first-child, li:nth-last-child(n+2):nth-last-child(-n+2):first-child ~ li"'] {
background: lime;
}
</style>
<script type=module>
import deqaf from 'https://unpkg.com/deqaf/index.js'
import has from 'https://unpkg.com/jsincss-has-selector/index.vanilla.js'
deqaf({rule: {has}})
</script>
Allow styling of the parent based on the number of children.
This is possible nowadays, thanks to :has()
:
/* Less than 3 children */
ul:has(> :nth-child(-n+2):last-child) {
border: 1px solid red;
}
/* Exactly 5 children */
ul:has(> :nth-child(5):last-child) {
border: 1px solid blue;
}
/* More than 7 children */
ul:has(> :nth-child(7)) {
border: 1px solid green;
}
Try it out in your browser if it has :has()
support: https://codepen.io/bramus/pen/bGKoZNq?editors=0110
I guess this issue may be closed?
For "Less than 3 children", you probably want to include 0 children, so ul:not(:has(> :nth-child(3)))
.
Also see reductions for An+B of S
cases in https://github.com/w3c/csswg-drafts/issues/5694#issuecomment-722736765
The relational pseudo-class
:has()
is proposed to take a relative selector list as an argument. https://drafts.csswg.org/selectors-4/#relationalIt would be very useful to be able to know how many children (and/or children of a type) the element has. For example, you may want to style a menu differently if it has more than n elements.
Currently, you can use a combination of :nth-last-child, and :first-child to determine at the child level how many siblings there are. (described very well in https://css-tricks.com/extremely-handy-nth-child-recipes-sass-mixins/)
However, this doesn't allow styling of the parent based on the number of children. Presumably it would be desirable to be able to select based on >, <, or = n children.