Proposal for property value based selector

selectors
Tags: #<Tag:0x00007faaa15c09b0>

#1

Hereby I propose a new type of selector, one that is based on used property values.

Examples:

There is plenty of ways to select an element based on source (like class selectors, ID selector, attribute selectors, etc.) and structure (siblings, children, descendants). There is plenty of ways to specify values for CSS properties. But there is no way to select an element if the used value of some of its CSS properties matches a given criterion.

Image you want the set the top margin for the first block element. The :first-child selector matches any child.

  • *:first-child { margin-top: 2em; }

Another selector might be:

  • *:nth-child(1 of :matches(div,p,aside,…)) { … }

The problem here is that one has to enumerate a quite large list of supposedly block elements. No major implements the ‘of’ qualifier for :nth-child and :nth-last-child, so one would actually have to write a long list of full selectors. The main problem, however, is that the display property is not restricted to any element: display:block may be applied to any inline element while display:inline may be applied to any block element. In addition, some other properties force display to a predefined value (e.g. float forces display to block). A quite simple solution would be:

  • *:nth-child(1 of :style(display:block)) { … }

Example #2: Imagine you want a table cell to display text vertically but only if the cell is not wide enough to display the text horizontally. This would be quite easy to achieve with a selector like this:

td:style(width < 2.5ch) { writing-mode: sideways-lr; }

A selector like this would match an element only if the used value of the width property (no matter if its fixed in previous declaration or is calculated automatically) is less than 2.5ch converted to pixels. A more sophisticated rule might use a combination of checks, e.g.

:style(height > 1px and width < 2.5ch) { … }

:style(1px < width < 2.5ch) { … }

  • Operators <, >, <=, >=, = and <> would be applicable to properties that calculate to numbers like ‘width’ does;
  • For properties whose values are strings the same operators as for the attribute selector would apply;
  • For properties whose values are selected from a closed set of keywords, the only syntax allowed would be e.g. :style(display:block) and :not(:style(:block)).

#2

It looks like you main use case here would be covered by element queries. Are there any other (major) use cases that can’t be done with the current proposals?


#3

This is in fact a generalized proposal. The issues I have encountered in my practice are the two examples: how to apply styling to the first block child element and how to make a cell text turn sideways if the cell is too narrow and The first issue is easily solved with well structured markup (e.g. never use HTML like <div>some text, then some <i>italic</i> text and finally <p>a standalone paragraph.</p></div>). The second one, however, requires JavaScript which I would like to avoid.


#4

The second example you mentioned would be solved with element queries, once (if) implemented.