Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CSS Regex Selector #1010

Open
pmaxhogan opened this issue Feb 7, 2017 · 18 comments
Open

CSS Regex Selector #1010

pmaxhogan opened this issue Feb 7, 2017 · 18 comments

Comments

@pmaxhogan
Copy link

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
Copy link
Contributor

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
Copy link

@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
Copy link
Contributor

@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
Copy link

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

@topaxi
Copy link

topaxi commented Feb 15, 2017

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
Copy link

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:

  • if the CSS classes are not perfectly namespaced => kaboom.
  • if I want to factorize all commons properties for class="foo-<*>-bar" and surcharge after with specific cases - which is a current pattern with CSS - => the specificity of [class*="foo-"][class*="-bar"] is too big, I have to use .foo-one-bar.foo-one-bar to override specificy of the double attribute class, a regexp selector would avoid me to do so.

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

@FremyCompany
Copy link
Contributor

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
Copy link
Contributor

Crissov commented Apr 26, 2017

@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"].

@fantasai fantasai added selectors-5 and removed selectors-4 Current Work labels Jan 1, 2018
@AndreasKarz
Copy link

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
Copy link

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
Copy link
Contributor

@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
Copy link

felippe-regazio commented May 16, 2020

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

@smartin85
Copy link

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

@rinogo
Copy link

rinogo commented Oct 31, 2020

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
Copy link

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:

  • Not sure which symbol works to best represent "Regular Expression". Personally, I like #= but I also recognise the very potential confusion with the CSS ID selector. I could also see /= as an alternative but that might have been floated for another type of selector so not too sure. I thought about ?= and while looks very "RegExy", it feels like an optional attribute selector of sorts to me (optional chaining, non-capturing group, etc.), so not too keen on that one.
  • Maybe this should be ignored on [value] for security reasons, like we've seen people use [value$="…"] to grab data from user input. This might be overzealous as a regular expression won't provide the string (until we have a regex($1) function for values, ha) and I've not really run into this issue in the past as I usually have a vanilla approach, but I figured I'd point that out.

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
Copy link
Contributor

Crissov commented May 17, 2021

Regarding attribute value selectors, also see #354.

@WillsterJohnson
Copy link

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
Copy link

aentwist commented Nov 10, 2022

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
  • More flexible: match values described by a regex instead of using values from a predefined list
  • Ship significantly less code: especially, flexible, non-semantic frameworks (faster CSS load speed, no difference in maintainability)
    • How much this could be done is debatable given that CSS is not a PL
Cons
  • No advantages when not using a flexible, non-semantic naming scheme
  • Decreasing CSS size is not an efficient optimization for page speed
    • In the modern web the size has nothing on JavaScript
    • CSS does not present challenges this way as-is
  • Potential for poor selector performance
  • Described naming scheme almost becomes a shortcut for using style, which goes against separation of concerns

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests