Skip to content

Instantly share code, notes, and snippets.

@treshugart
Last active May 6, 2024 05:04
Show Gist options
  • Save treshugart/b6aeac0df903f7d0efb7fae5b27bca22 to your computer and use it in GitHub Desktop.
Save treshugart/b6aeac0df903f7d0efb7fae5b27bca22 to your computer and use it in GitHub Desktop.

Defining a scoping inner-boundary in CSS

Concretely, I want to implement simulated CSS scoping for react-shade. This uses the imperative Shadow DOM APIs, by default, to enable scoping on the client. However, in order to get fully-scoped CSS when using SSR, we need either:

  • A declarative API for shadow DOM (closed due to lack of implementer interest), or
  • A way to tell CSS to stop selecting elements in slots. So, we'd need to be able to select between an ancestor and a descendant in a given DOM tree.
  • ...?

I am currently able to find solutions for :host and :host-context, and can scope stuff to descendants of a shadow root tree, the hard part is just simulating the exclusion of slotted content.

Notes

  • The content in the slot is meant to represent slotted (light DOM) content as this is how it would have to be SSR'd.
  • When applying simulated scoping, the CSS in <style> would be transformed so that it would do so.
<p class="title">Should *not* be styled by `.title`. This is fairly simple by prefixing `.title` with a something unique to the root.</p>
<root>
<style>
/* This is how it would be written by a consumer. */
.title { ... }
/* This is how it could be transformed to scope to the root. */
[__root_scope="1"] .title { ... }
/* Unsure how we transform it to only apply between the root and the slot. Just a thought for the sake of an example... */
[__root_scope="1"] .title:stop-cascading-at(slot)
</style>
<p class="title">Should be styled by `.title`. As mentioned above, this is pretty straight forward.</p>
<slot>
<p className="title">Should *not* be styled by `.title`. This is the hard part.</p>
</slot>
</root>
@treshugart
Copy link
Author

ah... yeah, wait that isn't going to work more than one deep...

Yeah, that was the problem. I've been fiddling with the transformation.

If you:

  1. Clone https://github.com/treshugart/react-shade.
  2. npm i
  3. npm start
  4. Selectors are transformed at https://github.com/treshugart/react-shade/blob/master/src/internal/css.ts#L33.
  5. You can mess with the example at: https://github.com/treshugart/react-shade/blob/master/pages/index.tsx#L53-L65.

You should be able to see the flash of styling between SSR and client side upgrading when you refresh.

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