w3c / csswg-drafts

CSS Working Group Editor Drafts
https://drafts.csswg.org/
Other
4.5k stars 667 forks source link

CSS Regex Selector #1010

Open pmaxhogan opened 7 years ago

pmaxhogan commented 7 years ago

This would resolve #1008. It would be very nice to have the ability to do a regex selector on a tag, like this:

/**Match all h1-h6 tags**/
/^h\d$/i{
     font-family: "Roboto", sans-serif;
}
/**Match all ruby elements**/
/^r[a-z]+/i{
     font-weight: bold;
}

and so on. Better yet, allow regex to be used in classes, etc.

/**Match sections with ids of card-1, card-2, etc.**/
section#/card-\d+/i{
     padding: 10px;
     border-radius: 10px;
     background: white;
}

This would be an extremely helpful feature of CSS that would help developers write lean, beautiful code and I would love to see it added to the spec!

patrickdark commented 7 years ago

This feature sounds like overkill; if one needs regular expressions to match element names, then something would seem to be wrong with the design of the language being styled.

In the case of h1/h2/h3/h4/h5/h6, the elements are a historical artifact and shouldn't exist and in practice one should rarely ever need to use more than h1 and h2 given the HTML5 outline algorithm.

In the case of ruby/rt, it'd be less verbose to write a selector without a regular expression and in practice you won't want to style those elements the same anyway.

notoriousb1t commented 7 years ago

@patrickdark When you look at an html document from the perspective of a screenreader, heading tags are important to providing a logical structure. Even a site without a lot of content could under best practices go down to an h4. It is still useful even if not all decide to make websites accessible.

I agree that regex is unnecessary (and think it might be possible hazardous). I think that simple pattern matching the same as attribute selectors have would be more than sufficient to solve this problem and when using a framework that prefixes their custom elements.

patrickdark commented 7 years ago

@notoriousb1t I don't disagree that heading elements are useful, but the paradigm of...

<section>
    <h1></h1>
    <section>
        <h1></h1>
    </section>
</section>

...makes having numbered heading elements redundant for anything other than subheadings since the heading level can be inferred from the number of sections in which a heading element is nested. In those cases, h1 might as well be h; the element is only numbered for historical reasons.

In modern HTML, the only in case where numbered headings are useful are in hgroup elements where h2 et al can be used to mark subheadings. In practice, subheadings are limited to one to two levels, and styling h4/h5/h6 elements will be superfluous.

And even the latter case I think shouldn't exist. It'd be better to infer subheadings via element nesting by doing something like repurposing the hgroup element:

<hgroup>
    <h1></h1>
    <hgroup>
        <h1></h1>
    </hgroup>
<hgroup>
notoriousb1t commented 7 years ago

@patrickdark I respectfully disagree, but I think we should discontinue this conversation in order to keep the issue on topic.

topaxi commented 7 years ago

The heading case could be solved with something like https://drafts.csswg.org/css-extensions/#custom-selectors

The section case could be solved with attribute selectors:

section[id^="card-"] {
     padding: 10px;
     border-radius: 10px;
     background: white;
}

I think RegExp would only add a lot of complexity for everyone.

nico3333fr commented 7 years ago

For some complex real cases, it could be useful, I had a case this afternoon, let's try to explain it simply:

I want to select all elements that have class="foo-<*>-bar" (I have about 6 or 7 same behaviours with small differences), and elements may have other classes attached to them, so impossible to use class^= or class$=, neither class|=.

I had to use: [class*="foo-"][class*="-bar"] (which allowed me to save about 50 lines of CSS, and probably more when the website will become more complex)

Problems with this targeting:

I agree: it is complex, not everyone will need it => but complex cases sometimes needs powerfull solutions.

FremyCompany commented 7 years ago

I'd recommend you to change your class system to have a foo class and a bar class in addition to your foo-xxx-bar class if that is what you need for selecting purposes. Executing regular expression on every attribute of the document would be very expensive. Microsoft Edge's layout team would be opposed to this idea.

Crissov commented 7 years ago

@nico3333fr's specifity problem would be solved if attribute selectors could have multiple alternate values, e.g. [class*="foo-","-bar"] instead of [class*="foo-"][class*="-bar"].

AndreasKarz commented 4 years ago

This feature sounds like overkill; if one needs regular expressions to match element names, then something would seem to be wrong with the design of the language being styled.

In the case of h1/h2/h3/h4/h5/h6, the elements are a historical artifact and shouldn't exist and in practice one should rarely ever need to use more than h1 and h2 given the HTML5 outline algorithm.

In the case of ruby/rt, it'd be less verbose to write a selector without a regular expression and in practice you won't want to style those elements the same anyway.

Have you ever written automated tests? Not always see the problems from your point of view.

AndreasKarz commented 4 years ago

The heading case could be solved with something like https://drafts.csswg.org/css-extensions/#custom-selectors

The section case could be solved with attribute selectors:

section[id^="card-"] {
     padding: 10px;
     border-radius: 10px;
     background: white;
}

I think RegExp would only add a lot of complexity for everyone.

Have you ever written automated tests? Not always see the problems from your point of view.

SebastianZ commented 4 years ago

@AndreasKarz If you have some specific use cases where you think regular expressions would greatly improve what we have so far, you should share them.

I, for myself, also already thought about them being useful, though I can totally understand that implementors are reluctant to the idea of adding regular expressions to selectors because this would definitely come with some performance cost.

The use cases I had so far mainly only required advanced attribute selectors similar to the ones @nico3333fr mentioned.

Sebastian

felippe-regazio commented 4 years ago

Sounds like a cool feature for a preprocessor: https://codepen.io/jimmy8646/pen/yzxRRY

smartin85 commented 4 years ago

This would be nice to select all custom elements (containing hyphens).

rinogo commented 4 years ago

CSS is used in more contexts than simply writing stylesheets. It is commonly used to select specific elements to perform a function on - for example, in client side JS or in a CI testing flow.

Regex attribute selection would, indeed, be useful in those contexts. (Especially since the person writing the JS/tests isn't necessarily the same person writing the CSS)

chriskirknielsen commented 3 years ago

Sorry to dig this up, I ran into a need for RegEx on and landed here. Could we imagine perhaps a CSS attribute selector that accepts a RegEx, instead of a way to match selectors in general? For example:

[data-filters-sections#="(0|9)+"] {
  opacity: 0.5;
}

/* I hate this example, too */
.col-wide-sm[class#="col-([0-9]|1[0-2])"] {
  width: 100%;
}

Two things:

Once again, sorry about the old issue revival, just wanted to share the idea, and I'm happy to create a new issue if that makes more sense!

Crissov commented 3 years ago

Regarding attribute value selectors, also see #354.

WillsterJohnson commented 3 years ago

following on from @chriskirknielsen's idea of limiting CSS-RegEx to attr selectors

im currently trying to make an atomic CSS framework (mainly for personal use) that would have something like prefix-border="x-1-solid-red y-2-dotted-blue" to apply different styles to the inline and block borders. This is currently impossible in CSS without shipping a painfully large stylesheet to the end user. The selectors I've been scratching my head over all weekend are;

[border*="y-"][border*="blue"] {...}
[border*="x-"][border*="red"] {...}

(I have others for n/s/e/w/a => north/south/east/west/all => block-start/block-end/inline-start/inline-end/all) No matter what I do, what order I put them in, where I use !important (which I dont want to do), it simply does not work.

Now extrapolate that to 7 edge selections, 5 border thicknesses, every border style, and however many colors I pass into my config, and dozens of other CSS properties... It gets very messy to use these kind of selectors; [border="n-1-solid-red"], [border="n-2-solid-red"], [border="n-3-solid-red"], etc.

RegEx would solve my issue gracefully. below im using ?= as I really like the syntax and it's a common ligature, and the same RegEx syntax as JS because why make frontend devs learn another RegEx syntax;

[border?=/\s?y-[^\s]+blue/] {...}
[border?=/\s?x-[^\s]+red/] {...}

The selectors at the top of this post are a wonderful thing, they say "elements that have this and this", but we have no way to say "elements that have something containing this and this", no way to differentiate border="x-red y-blue" from border="x-blue y-red", or both blue or both red. The use of RegEx handles that for us, [^\s] "not whitespace". and RegEx does significantly more too. As far as I've been able to find, XML and CSS are the only languages without RegEx. XML understandably, in a phrase, XML is for saying "here's a thing".

I understand CSS is a stylesheet, but looking at the spec and at the way we develop websites these days, we're heading more and more towards smarter CSS, if FORTRAN can have RegEx, why not CSS?

aentwist commented 2 years ago

why not CSS

Well, because there could be huge performance implications.

I am also curious about this and so have landed here. As mentioned above, the main use case is flexible, non-semantic naming schemes.

For example, preprocessors have ways to generate many CSS rules programmatically. Regular expressions with capturing group support could handle this natively (although this is not equivalent, as explained below). Whether it is in-scope is debatable at best and depends on implementation feasibility.

Example use case:

[class*="line-clamp"] {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/*
 * New attribute selector with regex support on the RHS only,
 * since the main use-case is based on classes - not attributes
 */
[class=/line-clamp-(\d+)/] {
  -webkit-line-clamp: $1;
}
Pros vs. Preprocessor Programmatic Generation
Cons