[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-cascade-6] A way for <style> elements to scope to their parent element #6606

Closed
dfabulich opened this issue Sep 13, 2021 · 12 comments · Fixed by #8463
Closed

[css-cascade-6] A way for <style> elements to scope to their parent element #6606

dfabulich opened this issue Sep 13, 2021 · 12 comments · Fixed by #8463

Comments

@dfabulich
Copy link
dfabulich commented Sep 13, 2021

https://drafts.csswg.org/css-cascade-6/#scoped-styles

The explainer references this issue: Please bring back scoped styles.

Either there's something missing from the spec or I'm missing it, which is a way to have a <style> element that gets scoped to its own parent element.

<div>
  <style scoped>p { color: red; }</style>
  <p>red</p>
</div>

<style scoped> would guarantee that the color only applied to children of the parent div.

I could do it by adding a unique ID or attribute:

<div id="foo">
  <style>#foo p { color: red; }</style>
  <p>red</p>
</div>

… this is basically what Vue does at build time. But I want the same effect without a build step!

I think we'd want something like @scope(:style-parent).

<div>
  <style>@scope(:style-parent) { p { color: red; } }</style>
  <p>red</p>
</div>

Otherwise, even with @scope back in play, I'd still have to use a build tool (or something) to generate an ID for the upper bound of the scope.

@mirisuzanne mirisuzanne added this to Relevant Issues in Cascade 6 (Scope) Sep 13, 2021
@mirisuzanne
Copy link
Contributor

If I understand this right, the new feature required for this is a :style-parent pseudo-class (:style-root? :style-host?) which:

  • For stylesheets in the document <head> refers to the document root.
  • For nested stylesheets, refers to their parent element.

I don't see any particular reason it should be restricted to use in @scope if we add it. Could also be used for basic child/descendant selectors, or the :in() pseudo-class. I'm not sure if that's feasible from an implementation perspective, but it's an interesting idea.

@dfabulich
Copy link
Author
dfabulich commented Sep 13, 2021

As is typical for spec bugs, I think I've got two ideas piled into one:

  1. I've got a problem: I want to be able to scope styles to the nested <style> element's parent.
  2. I suggest a solution: A new pseudo-class :style-parent (or :style-root or :style-host, yeah) that would refer to the parent element of a nested <style>. (As you point out, that would not be meaningful for stylesheets in the <head>, so presumably in that case we'd want it to refer to :root.)

If :style-parent isn't feasible for some reason, I'd still wish for some solution to the problem. I guess I could try to invent a handful of other solutions…? (The scoped attribute <style scoped> could literally be another alternative, for example.)

@mirisuzanne
Copy link
Contributor

Right. But I think one of the issues with <style scoped> is that it has backwards-compatibility problems. Browsers that don't understand the scoped attribute will continue to apply those styles globally (the current behavior) — which is not the ideal fallback here.

I like the pseudo-class idea because it avoids that issue, while building on top of the more flexible CSS-selector driven approach to @scope.

@Malvoz
Copy link
Contributor
Malvoz commented Oct 14, 2021

one of the issues with <style scoped> is that it has backwards-compatibility problems. Browsers that don't understand the scoped attribute will continue to apply those styles globally

Couldn't authors just use a polyfill (i.e. https://github.com/samthor/scoped)?

@Malvoz
Copy link
Contributor
Malvoz commented Oct 14, 2021

Going a bit off-topic (feel free to hide the comment as such):

People are wanting to scope IDREFs in HTML: https://discourse.wicg.io/t/relative-element-references-in-html/5627/, someone suggested a refscope attribute, but I wonder - iff an attribute to scope IDREFs is a viable option - couldn't scoped be extended to apply to HTML elements for IDREF scoping? Or is it a bad idea to have one attribute scope different things depending on which element it is applied to?

@bitdivine
Copy link

Regarding the backwards compatibility issue, would it be possible to define a CSS selector that refers to the current location of a style tag? If the browser does not recognize it, the CSS selector would match nothing, rather than everything.

That way we could have:

<some-parent>
  <style>
    @here button {some css}
  </style>
  <button>CSS APPLIES HERE</button>
</some-parent>

@bitdivine
Copy link

Regarding the issue of not wanting CSS to apply to all child elements, or "toroidal css", is that not a separate issue from local scoping? It feels as if it should be possible to define selectors indicating "style this element but not its children" (non-inherited styles) or "style this element like its parent" (explicit inheritance of normally non-inherited styles) but that trying to combine inheritance constraints with local scoping makes things complicated.

@mirisuzanne
Copy link
Contributor

@bitdivine The current scope proposal (and this thread) do not have any impact on inheritance. The donut scope applies to selector targeting only.

I do like the approach of a syntax for pointing to style location, whatever form that might take.

@Malvoz The problem is not for authors that want to use the new feature, but for legacy sites that already have nested style tags which apply globally. Authors can recreate a scoped attr using a polyfill, but any browser support for that would break legacy styles, and that's not an option. There's no way to polyfill opting-out all legacy sites from a new feature.

@mirisuzanne
Copy link
Contributor

I think this should be resolved by a combination of:

The first one there allows scoped imports using @import (which we could propose to the WHATWG as an attribute, similar to the proposed layer attribute). The second means you can get the desired behavior by using the @scope rule in the nested style sheet, without waiting for an HTML attribute:

<div>
  <style>
    /* scoped to the div, since no scope root selector is given */
    @scope { p { color: red; } }
  </style>
  <p>red</p>
</div>

Closing this issue as accepted by those resolutions. If we want to work on an additional scope attribute for HTML, that will need to happen in the WHATWG rather than the CSSWG.

@mirisuzanne mirisuzanne moved this from ToDo to Done in Cascade 6 (Scope) Sep 21, 2022
@yisibl
Copy link
Contributor
yisibl commented Oct 27, 2022

@andruud As far as I know, this is not currently implemented in Chrome, can you implement the new behavior in Chrome?

Finally, we could allow @scope without any selector clauses, which would scope the styles to the parent of the stylesheet's owner node (or the containing tree for constructable stylesheets with no owner node).
https://github.com/oddbird/css-sandbox/pull/22/files#diff-959903105b7abdfb2fa2540f104fdd8d7f347e6f339814fdf5e57f7e65f235e9

<div>
  <style>
    @scope {
      p { color: red; }
    }
  </style>
  <p>this is red</p>
</div>
<p>not red</p>

That would be equivalent to:

<div id="foo">
  <style>
    @scope (#foo) {
      p { color: red; }
    }
  </style>
  <p>this is red</p>
</div>
<p>not red</p>

@mirisuzanne mirisuzanne moved this from Done to Needs Edits in Cascade 6 (Scope) Oct 27, 2022
@andruud
Copy link
Member
andruud commented Oct 31, 2022

@yisibl Right, yes, the current Chrome prototype predates the resolution add that kind of scoping. It will be added eventually. I filed crbug.com/1379844 if you want to follow that for updates.

@yisibl
Copy link
Contributor
yisibl commented Oct 31, 2022

@andruud Thanks! I am very much looking forward to the implementation of this feature.

andruud added a commit to andruud/csswg-drafts that referenced this issue Feb 17, 2023
@mirisuzanne mirisuzanne moved this from Needs Edits to Done in Cascade 6 (Scope) Feb 17, 2023
mirisuzanne added a commit that referenced this issue Feb 17, 2023
* [css-cascade-6] Add implicit scopes

Resolves #6606.

* Allow lower bounds when root is implicit

---------

Co-authored-by: Miriam Suzanne <miriam@oddbird.net>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Development

Successfully merging a pull request may close this issue.

6 participants