w3c / csswg-drafts

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

CSS pseudo-selector for h1-h6? #1008

Open pmaxhogan opened 7 years ago

pmaxhogan commented 7 years ago

I frequently find myself writing CSS like this:

h1, h2, h3, h4, h5, h6{
     ...
}

It annoys me that I have to type h1, h2, h3, h4, h5, h6 so much. But it gets worse:

article h1, article h2, article h3, article h4, article h5, article h6{
     ...
}

or even

article h1.bold:hover, article h2.bold:hover, article h3.bold:hover, article h4.bold:hover, article h5.bold:hover, article h6.bold:hover{
     ...
}

Wouldn't it be nice to just type

:heading{
     ...
}

or

article :heading{
     ...
}

or

article :heading.bold:hover{
     ...
}

:heading just matches h1-h6. It would be easy to implement for browser vendors and easy to polyfill. But extremely helpful.

Having a heading selector like :heading would be AWESOME!

notoriousb1t commented 7 years ago

Peanut gallery here. :heading seems ultra specific. Maybe we would be better served by a tag selector? Something like

/h[0-6]/ {
   font-weight: bold;
}

With custom tags in html, there is a good use case for prefixed elements

<react-list-view></react-list-view>

would be selected by

/react-*/ {
   font-weight: bold;
}
SelenIT commented 7 years ago

There is the CSS Custom Selectors proposal (it even has its PostCSS plugin) which would solve this exact issue and much more. But doesn't :matches(h1, h2, h3) from Selectors level 4 already solve the main problem here (code duplication)?

pmaxhogan commented 7 years ago

See #1010

annevk commented 6 years ago

https://github.com/whatwg/html/pull/3499 contains a :heading/:heading() pseudo-class selector proposal. @fantasai wrote that Selectors should maybe define that given that other host languages might have utility for it too. If it's successful for HTML that seems reasonable to me.

tabatkins commented 6 years ago

But doesn't :matches(h1, h2, h3) from Selectors level 4 already solve the main problem here (code duplication)?

No, because HTML has ways of assigning heading levels that go beyond tagnames - h1 nested inside of sectioning elements automatically becomes a second/third/etc level heading, as appropriate. (Plus, :heading really is pretty dramatically shorter to type than :matches(h1, h2, h3, h4, h5, h6), and is a pretty common thing to want to style.)

Crissov commented 6 years ago

Would :heading match any of <caption>, <figcaption>, <label>, <legend> as well?

tabatkins commented 6 years ago

Nah, none of those are "headings" in HTML's semantics. They're labels for some content, which serve a similar purpose, but aren't the same thing.

inoas commented 6 years ago

~Is /h[0-6]/ actually a valid selector (not to my knowledge) But if it is not, why not make that a valid selector?~

tomhodgins commented 6 years ago

@inoas are there any other HTML tag names, other than H1–6 where a regex-like selector like that would make sense?

If you're wanting to select tags by partial tag name like that, though CSS selectors won't currently do it, you can do this with XPath using a selector like: //*[substring-after(name(), "h") > 0]

Demo: https://codepen.io/tomhodgins/pen/ybgMpN

tabatkins commented 6 years ago

It's not a valid selector, but it's also a remarkably complex feature for something as limited as "match this family of tagnames". LIke @tomhodgins says, there's very little call for substring-matching on tagname; insofar as we do want such a thing, prefix/suffix-matching like XPath provides probably provides 90%+ of the desired functionality.

But such a thing wouldn't even work here, because part of the point of a heading-level selector is that it works off of the HTML outline algorithm, not the tagname.

Crissov commented 6 years ago

Hm. Then I guess a related :caption selector would match the elements I mentioned and headings that are the top level in a <section>.

Iʼm not sure what to do with <th> though.

annevk commented 4 years ago

@emilio raised an interesting concern that I don't have a good solution for. If you have

:heading(1) { ... }
:heading(2) { ... }
:heading(3) { ... }

and then for some reason you end up with a level 4 heading on your page, the ideal "failure mode" is that it'll render the same as 3.

Maybe instead what you want is heading-level as a variable that can be used by calc() or some such.

Thoughts?

Unless there's a relative clear answer here I'm inclined to leave this feature out of https://github.com/whatwg/html/pull/3499 and save that for a future iteration.

cc @hober

annevk commented 4 years ago

@js-choi's idea in https://github.com/whatwg/html/issues/3500 might be another way out here, but that looks quite involved as well.

emilio commented 4 years ago

An alternative idea is saying that :heading(n) matches if the heading level is less than or equal to n.

AmeliaBR commented 4 years ago

An alternative idea is saying that :heading(n) matches if the heading level is less than or equal to n.

I wouldn't want that to be the default behavior, but if this selector is adopted, I think it does make sense to add a second syntax that supports inequalities. It could be harmonized with the syntax being discussed in #4140 for nth-child() family of selectors:

(Edit: and now I see that this is the exact proposal from the HTML issue linked by Anne)

AndreasKarz commented 4 years ago

@inoas are there any other HTML tag names, other than H1–6 where a regex-like selector like that would make sense?

If you're wanting to select tags by partial tag name like that, though CSS selectors won't currently do it, you can do this with XPath using a selector like: //*[substring-after(name(), "h") > 0]

Demo: https://codepen.io/tomhodgins/pen/ybgMpN

Don't work with Selenium :-(

a-a-GiTHuB-a-a commented 3 years ago

%heading works…