Skip to content

Declarative Shadow DOM #510

@tabatkins

Description

@tabatkins

One of the promises of early Shadow DOM (and several other Parkour-descended products) was that while we would build the first version as an imperative (JS-based) API, for flexibility and composability, we'd come in later and backfill a declarative version that made it very easy to use for common cases. We haven't done this yet for Shadow DOM, and the spec is stable enough now that I think we can safely do it.


Rough proposal:

<div-or-something>
  <template attach-shadow shadow-mode="open | closed">
    ...shadow content...
  </template>
</div-or-something>

That is, using a <template> element with an attach-shadow attribute automatically (during parsing) attaches its contents to its parent element as a shadow root. The mode is selected by the optional shadow-mode attribute; if omitted, it defaults to "open" (or we can make it required, like the JS API does?).


Reasoning:

Today you can get something close to declarative with JS like:

<parent-element>
</parent-element>
<script>
"use strict";

const shadowRoot = document.currentScript.previousElementSibling.attachShadow({ mode: "open" });
shadowRoot.innerHTML = `<child-element></child-element>`;
</script>

This has several downsides:

  1. Doesn't work nicely with syntax highlighting.
  2. Doesn't work nicely with any tooling that wants to be able to output HTML.
  3. Doesn't nest easily. (That is, having an element in the shadow contain another declarative shadow.)
  4. Can't include <script> in the shadow unless you remember to do the various tricks to avoid having a literal </script> in the string.
  5. Also have to be aware of which quoting character you're using, and remember to escape it when you're writing your page.
  6. Including user-generated content is now more complicated; it not only needs to be escaped as safe HTML, but as safe script and string contents, too, which are decently more complex (and not, afaik, supported by the core libraries in PHP or Python).
  7. Lots of non-trivial typing for something intended to be easy and widespread.
  8. Inline script isn't compatible with safe CSP practice, unless you go the extra mile to add nonces (more effort! must use crypto safely!)
  9. Inline script isn't run for .mhtml archives (at least in Chrome, for historical reasons).
  10. Users with JS turned off won't get any page at all, for no good reason - page might have just been wanting style isolation, but is now tied to JS evaluation.
  11. Inline script halts the speculative parser, I think?
  12. Doesn't allow for server-side rendering (doing as much of the page as possible on the server, only using client-side JS for final fixups and event hookups, etc). The page instead has to do all this work on client-side (which is apparently fairly slow, per Declarative Shadow DOM #510 (comment))

Metadata

Metadata

Assignees

No one assigned

    Labels

    needs implementer interestMoving the issue forward requires implementers to express interesttopic: shadowRelates to shadow trees (as defined in DOM)

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions