Csswg-drafts: [selectors] Number-of-siblings pseudoclass proposal

Created on 6 Apr 2017  路  5Comments  路  Source: w3c/csswg-drafts

I鈥檓 working on something right now that requires I change the style of some child elements when there are 4 or more of them. To do this presently, I do something like this.

/* The <a> within an <li> of 4 or more children within .some-thing */

.some-thing li:nth-last-child(n+4) a, .some-thing :nth-last-child(n+4) ~ li a { /* styles go here */ }

This seems far removed from what I was trying to express. Would it be possible to add a syntax so that I only have to write this?

/* The <a> within an <li> of 4 or more children within .some-thing */

.some-thing li:of-child(n+4) a { /* styles go here */ }

Similarly, I may want to change the style of some child elements when there are 3 or less of them. Again, to do this presently, I use:

/* The <a> within an <li> of 3 or less children within .some-thing */

.some-thing li:nth-last-child(-n+3):first-child, .some-thing :nth-last-child(-n+3):first-child ~ li a { /* styles go here */ }

And again, it would be nice to express my intentions more clearly.

/* The <a> within an <li> of 3 or less children within .some-thing */

.some-thing li:of-child(-n+3) a { /* styles go here */ }

Does this seem like a reasonable request? :of-child() and hey maybe :of-type() if we feel like being fully consistent?

Prior art: https://alistapart.com/article/quantity-queries-for-css

selectors-5

Most helpful comment

Well, :sibling-count(), and it would use the of <selector> syntax that the other structural pseudos use.

All 5 comments

I've been doing something similar with CSS Element Queries using the children responsive feature. Consider the following demo:

<ul>
  <li>Item 1
</ul>

<ul>
  <li>Item 1
  <li>Item 2
</ul>

<ul>
  <li>Item 1
  <li>Item 2
  <li>Item 3
</ul>

<style>
  @element ul and (min-children: 3) {
    $this {
      background: lime;
    }
  }
</style>

<script src=http://eqcss.com/EQCSS.js></script>

The key part of this is @element ul and (min-children: 3) which will only apply the block of styles below if at least one element matches that selector and responsive condition.

I've written about this functionality in my CSS Element Queries spec, and you can find more demos of this functionality on CodePen here:

Is this the sort of functionality you're looking to express? The way we count it's the same number as elements[j].children.length would give :D

If :has() were easier to implement, I think you could use

.some-thing:has(> nth-child(4)) > li > a { /* 4 or more elements */ }
.some-thing:not(:has(> nth-child(4))) > li > a { /* 3 or less elements */ }

I don't think there is a strong need for :of-child. I think the real annoyance here is that the combinator ~ is not inclusive. Say ~= was a combinator like ~ but inclusive, then you could use

.some-thing > :nth-last-child(n+4) ~= * > a { /* 4 or more elements */ }
.some-thing > :first-child:nth-last-child(-n+3) ~= * > a { /* 3 or less elements */ }

It would also be helpful for other kinds of problems. For example, say you want to split the elements into groups of three elements, allowing the last group to have one or two elements, and then select the elements in the last group.

Currently I think the best way to do this is

.some-thing > :nth-last-child(-n+3):nth-child(3n+1) > a,
.some-thing > :nth-last-child(-n+3):nth-child(3n+1) ~ * > a

But with ~=, it would be simpler:

.some-thing > :nth-last-child(-n+3):nth-child(3n+1) ~= * > a

Imagine if :has() was as easy to implement as one of these examples:

/* Emulating section:has(h2) */

/* if (condition) "selector" */
@element 'section' {
  eval('if (querySelector("h2")) "$this"') {
    border: 1px solid lime;
  }
}

/* condition ? "selector" : "" */
@element 'section' {
  eval('querySelector("h2") ? "$this" : ""') {
    box-shadow: purple 10px 10px 0;
  }
}

/* condition && "selector" */
@element 'section' {
  eval('querySelector("h2") && "$this"') {
    background: darkblue;
  }
}

Working demo: http://codepen.io/tomhodgins/pen/yMpdOz

I believe a :children() or :child-count() pseudo-class would be more readable, where the parameter syntax would be something like <integer> | <simple-selector> , <integer>.

Sebastian

Well, :sibling-count(), and it would use the of <selector> syntax that the other structural pseudos use.

Was this page helpful?
0 / 5 - 0 ratings