[go: nahoru, domu]

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-selectors] Improve the usefulness of specificity of Tags & IDs #4690

Closed
jensimmons opened this issue Jan 22, 2020 · 11 comments
Closed

[css-selectors] Improve the usefulness of specificity of Tags & IDs #4690

jensimmons opened this issue Jan 22, 2020 · 11 comments
Labels
Closed as Retracted When the person who raised the issue thinks that there's no issue after all. selectors-5

Comments

@jensimmons
Copy link
Contributor
jensimmons commented Jan 22, 2020

In an effort to modernize the CSS Cascade, and make it more suitable for projects with multiple Authors writing code over many years, @mirisuzanne is thinking about Origins (and how we might extend their power), and about the Specificity of Selectors.

For context:
The Selectors Level 4 defines three levels of sectors / three levels of specificity:

A selector’s specificity is calculated for a given element as follows:
count the number of ID selectors in the selector (= A)
count the number of class selectors, attributes selectors, and pseudo-classes in the selector (= B)
count the number of type selectors and pseudo-elements in the selector (= C)
ignore the universal selector

Miriam wrote on Twitter:

Specificity only has three layers, & only the middle (classes/attributes) layer is flexible enough for most use cases. IDs can only be used once per page, & tags need to be reused semantically. They're useful but very limited.

When everything is in a single layer, minute changes can have major impact. Everything relies on careful counting of selectors, and careful management of source order. Specificity should be more robust.

We need ways to create custom tag-layer – & reusable id-layer – selectors.

Let's talk about this. What would it look like to extend selectors so that:
• IDs can be used more than once per page
• The 'tag layer' has more customizability
• And / or other ways to empower Authors to use all three layers of specificity, instead of flattening their work into one layer.

@jensimmons jensimmons assigned jensimmons and unassigned jensimmons Jan 22, 2020
@jensimmons jensimmons changed the title [css-selectors] Making the Tag-layer and ID-layer [css-selectors] Making the Tag-layer and ID-layer more powerful Jan 22, 2020
@emilio
Copy link
Collaborator
emilio commented Jan 22, 2020

• IDs can be used more than once per page

This is already the case, isn't it?

@mirisuzanne
Copy link
Contributor

According to the HTML living standard, IDs must be unique on a page:

When specified on HTML elements, the id attribute value must be unique amongst all the IDs in the element's tree and must contain at least one character.

I think there are very good reasons for that – IDs are used to select a single element on the page in various form/ARIA related uses – so I'm not sure that making IDs more flexible is an option here. and it does make sense to me that a unigue-ID direct selection would live at the highest level of specificity. The same is true for tag names living at the lowest level. The two use-cases that would be particularly helpful in development are:

  1. The ability to create more flexible/targeted "defaults" that are easy to override. That could happen in a number of ways, including the proposed !default flag ([css-cascade] !default declarations proposal #2272), custom origins ([css-cascade] Custom Cascade Layers (formerly "custom origins") #4470), a new layer of specificity, or flexible (class-like) additions to the tag layer.
  2. The ability to consider some repeatable "components" more specific than other repeatable "patterns" – like an "article-summary" card is more specific than the "card" pattern it uses, even though both repeat on a page.

While point 2 can be handled with multiple classes, it feels like we're missing out on the power that specificity layering would provide to ensure that specific components always override more general patterns, which always override broad defaults.

I don't think we need a lot of layers – 3-5 seems about right – but our current 3 don't provide the flexibility required for the common use-cases.

@SebastianZ
Copy link
Contributor

According to the HTML living standard, IDs must be unique on a page:

When specified on HTML elements, the id attribute value must be unique amongst all the IDs in the element's tree and must contain at least one character.

Right, but what Emilio referred to was that the Selectors spec. also handles the case of invalid HTML documents defining multiple IDs:

An ID selector represents an element instance that has an identifier that matches the identifier in the ID selector. (It is possible in non-conforming documents for multiple elements to match a single ID selector.)

Sebastian

@mirisuzanne
Copy link
Contributor

Sure. I guess I'd question if that's really something to encourage? Unique IDs seem important for various semantics/accessibility issues, and I'd want to be careful about pushing a solution that might cause more accessibility issues.

@SebastianZ
Copy link
Contributor

Of course it's rather something that should be discouraged. As you say, IDs should be unique. I just mentioned that in regard of Jen's point of IDs being used more than once on a page and Emilio's response to it.

Sebastian

@jensimmons jensimmons changed the title [css-selectors] Making the Tag-layer and ID-layer more powerful [css-selectors] Improve the usefulness of specificity of Tags & IDs Feb 18, 2020
@mirisuzanne mirisuzanne added this to To Consider in Cascade 5 (Layers) Feb 19, 2021
@mirisuzanne
Copy link
Contributor

@jensimmons Is this something we still want to look into more? I think we've basically covered the use-cases here with a combination of @layer (as a higher-level structural fix), and :where()/:is() allowing more detailed specificity manipulation. Should we close the issue?

@jensimmons
Copy link
Contributor Author

If you think it's covered, then it sounds good to me.

@mirisuzanne mirisuzanne added the Closed as Retracted When the person who raised the issue thinks that there's no issue after all. label Feb 9, 2022
@mirisuzanne mirisuzanne moved this from To Consider to Complete in Cascade 5 (Layers) Feb 9, 2022
@ThomasGutmann
Copy link
ThomasGutmann commented Jan 31, 2023

Hi Jen (@jensimmons) and others!

I know this thread is closed already, but I don’t find a place where to put my suggestion on how CSS specificity could be calculated to solve a lot of scope problems. We all know the problem when an precise selector (THIS camel is blue) loses against some selector somewhere else (animals on THIS planet are green).

My suggestion: Instead of calculating a singular specificity for a CSS selector, the specificity should be calculated regarding the DOM element it is matching with. (How specific does the selector describe the target element.)
When the parser compares the selector and the DOM path of the matching element it could rate all the selector’s parts on the basis of there DOM tree level from the element’s point of view: the further up the ID, class or whatever in the selector, the less it counts (because it covers larger scope which is more unspecific).
An easy to understand calculation could be multiplying the selector part’s rating with 0.1^[DOM tree level difference].

Example:

<div id="my-module">
  <ul class="foos">
    <li>Some foo</li>
    <li>A second foo</li>
    <li id="my-foo">My foo</li>
  </ul>
</div>

A frequent case is that several selectors match for one element, take the li #my-foo for instance:

SELECTOR                                   SPECIFICITY
#my-module ul.foos li { color: blue; }  => 0 - 1 - 1 - 2  (inline - ID - class - style)
#my-foo { color: red; }                 => 0 - 1 - 0 - 0

Now #my-foo gets painted blue. Although the first selector doesn’t mention this specific element, it wins over the second selector which actually is more precise.
My suggestion now considers how many DOM tree levels the matching selector’s parts are above the element’s (#my-foo) point of view:

#my-module  1 * 0.1^2  = 0.01  (2 levels above)
ul          1 * 0.1^1  = 0.1   (1 level above)
.foos       1 * 0.1^1  = 0.1   (1 level above)
li          1 * 0.1^0  = 1     (0 levels above)
#my-foo     1 * 0.1^0  = 1     (0 levels above)

The part values then get summated like in the current CSS calculation. That leads to:

#my-module ul.foos li { color: blue; }  => 0.0 - 0.01 - 0.1 - 1.1
#my-foo { color: red; }                 => 0.0 - 1.00 - 0.0 - 0.0

(Redundant decimals here are just for better visibility.)

Now the precise second selector wins in the b (ID) section of a-b-c-d like it should be, because it is more specific. Every “closer” (DOM-tree-wise) description would win now.
This would avoid scope leaks, because we now can narrow the scope. All elements of an HTML code block that has an ID (unique) could now get safely styled if their rules start with the code block’s ID.

Regards,
Thomas

@Loirooriol
Copy link
Contributor

@ThomasGutmann That's what https://drafts.csswg.org/css-cascade-6/#scope-combinator is trying to introduce.

But you can already have something like that with custom properties:

#my-module { --color: blue }
#my-module ul.foos li { color: var(--color); }
#my-foo { --color: red; }   

@ThomasGutmann
Copy link

Thanks, @Loirooriol, for your answer.

My point is that the CSS “specificity” is not really inutitiv, and it rewards over-determined selectors and leads to HTML code wich is cluttered with classes and IDs. My website has easy HTML and almost non design and still I stumbled over the problem where I couldn’t style a specific element because of other selectors.
Your example presuppose that I know about the one #my-foo when writing the general selectors, but an easy KISS (“Keep it simple, stupid!”) approach with the CSS basics should lead to the target, too.
The new introduced mechanics seem like workarounds to me.
Kind Regards,
Thomas

@mirisuzanne
Copy link
Contributor

@ThomasGutmann everything we do here has to be backwards-compatible. We can introduce new features that are unknown in older browsers, but we can't change the behavior of existing CSS syntax. So to that extent, everything we do has to work around what already exists.

There would be ways to work around compatibility problems, by introducing new selector syntax – but I would expect that to have the same issues we're facing with >> and ~~ (which try to address the same problem in a different way). See #8380

(More generally, I would recommend opening new issues for a proposal like this, and linking to prior discussions where they are relevant)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Closed as Retracted When the person who raised the issue thinks that there's no issue after all. selectors-5
Projects
Development

No branches or pull requests

7 participants