Re: [csswg-drafts] [css-selectors] Lexical Scoping (#4061)

@AmeliaBR Thanks for writing this up. I think it's a good summary and you've called out some important considerations and back-compat issues. I have a few comments:

> It could be very confusing to have two ways of declaring namespace prefixes which affect different selector parts (this proposal for classes & IDs, and XML namespace prefixes for tags and attributes).

This proposal so far has taken the perspective that there can be classnames and ids that are defined by the stylesheet and referenced from html. Given that stylesheets tend to be shared across multiple documents, I think this is not an uncommon mental model for developers to use, but it is contrary to the current model that css is just selecting values from html documents.

It occured to me that we could take a slightly different angle. What if a document could define an attribute namespace based on a stylesheet's url. In this way we keep the idea that the namespace belongs to the document's attributes. The new semantic then introduced would be that a stylesheet can have its class and id selectors placed either explicitly (from the css file) or implicitly (via import/link) into the namespace of the stylesheet.

Updating my first example, everything remains the same, but the markup for a scoped stylesheet link would become:

```html
<!-- scoped.html -->
<link rel="stylesheet" href="navbar.css" namespace="nav">
<aside>
   <ol nav:id="navbar">  <!-- matches, doesn't match #navbar in the global namespace defined by other css files -->
      <li nav:class="element">Home</li>  <!-- matches, doesn't match other .element in the global namespace defined by other css files -->
  </ol>
</aside>
```

Updating the second example, we can now use `@namespace` but a new value of `local()` would have the behavior of changing the meaning of the id and class selectors to be selecting the id and class attributes from the namespace of the stylesheet, it can also provide a scope for the identifiers used in css-only constructs like `@keyframes`.

```css
/* navbar.css */
@namespace local();
#navbar {
  /* main container */
}
.element {
  /* stuff contained by the navbar */
}
```

```html
<!-- unscoped.html -->
<link rel="stylesheet" href="navbar.css">
<aside>
   <ol id="navbar"> <!-- matches #navbar in the global namespace so the idents in navbar.css don't match here.  -->
      <li class="element">Home</li>  <!-- matches .element in the global namespace so the idents in navbar.css don't match here. -->
  </ol>
</aside>
```

```html
<!-- scoped.html -->
<link rel="stylesheet" href="navbar.css" namespace="nav">
<aside>
   <ol nav:id="navbar">  <!-- matches #navbar in the nav namespace -->
      <li nav:class="element">Home</li>  <!-- matches .element in the nav namespace -->
  </ol>
</aside>
```

Updating the multi-namespace example we can now use `@namespace` as a ruleset parent (previously illegal). These would define a namespace against the url of current stylesheet with a hash identifier added on. That is, `@namespace local(foo)` is the same as `@namespace foo url(#foo)` but with the extra semantics of lexical identifier scoping.

```css
/* all.css */
@namespace local(buttons) {
  .button { }
}

@namespace local(links)  {
  .link { }
}

@namespace local(call-to-action) {
  .cta .buttons|button.links|link {
    /* styles for elements having both of these classes */
  }
}
```

```html
<!-- scoped.html -->
<link rel="stylesheet" href="all.css" namespace="#buttons:buttons #links:links #call-to-action:marketing">
<aside marketing:class="cta">
   <a href="signup.html" buttons:class="button" links:class="link"> Sign Up! </a> <!-- matches the selector defined in call-to-action.css -->
</aside>
```

I feel like this provides all the same benefits while at the same time relying on existing browser primitives better.








-- 
GitHub Notification of comment by chriseppstein
Please view or discuss this issue at https://github.com/w3c/csswg-drafts/issues/4061#issuecomment-506458958 using your GitHub account

Received on Thursday, 27 June 2019 18:27:26 UTC