Skip to content

Exploration of exposing stylesheets across scopes #11364

Open
@KurtCattiSchmidt

Description

@KurtCattiSchmidt

What is the issue with the HTML Standard?

During the discussion of #11019 at Thursday's sync, it was suggested that we discuss some potential proposals for global ID references and how they might work with this feature. Here are a few starting points. This is intended to be an open discussion, so please feel free to add more ideas!

1. Referencetarget inspired solution on <template>

This proposal would allow for elements to list identifiers that are made accessible to their parent tree scope.

<template exportids="foo"><!-- Exports 'foo' to the light DOM -->
  <template exportids="foo, bar">
    <style id="foo">
     ...
    </style>
  </template>
  <link rel="stylesheet" href="#bar"> <!-- 'bar' is in scope due to `exportids` -->
</template>
<link rel="stylesheet" href="#foo"><!-- 'foo' is in the global scope, reference matched -->
<link rel="stylesheet" href="#bar"><!-- 'bar' is not in scope, reference not matched -->

This works nicely for style sharing, however it doesn't address the streaming SSR scenario where ID's may need to be exported from a deeply nested shadow root. This is because the parent <template> has already been emitted and may not have specified exportid's. This could be addressed with wildcard support on exportid's:

<template exportids="global-*"><!-- Exports any id's beginning with 'global-' to the light DOM -->
  <template exportids="global-*"><!-- Exports any id's beginning with 'global-' to the parent shadow root -->
    <style id="global-foo"><!-- Streaming SSR exports a global id -->
    ...
    </style>
  </template>
  <link rel="stylesheet" href="#global-foo"> <!-- 'global-foo' is in scope due to wildcard `exportids` -->
</template>
<link rel="stylesheet" href="#global-foo"> <!-- 'global-foo' is in scope due to wildcard `exportids` -->

This is my preferred solution because it's not limited to style sharing. I would expect that the exported ID's from shadow roots would work everywhere ID's can be referenced in HTML, including in-page anchor references, <link rel="blocking">, and even SVG xlink:href references.

2. XID (WICG/webcomponents#939 (comment))

This proposal would be a GUID (or MD5 hash) of the style contents. I assume that some sort of prefix before the XID will be required where it's referenced, so as not to collide with existing valid identifiers.

<template shadowroot="open">
  <style type="adopted-css" xid="x61h8cys"> <!-- xid identifiers are global -->
   ...
  </style>
</template>

<template shadowroot="open" adopted-styles="">
  <link rel="stylesheet" href="xid:x61h8cys"> <!-- references global xid -->
</template>

Since this proposal expects a hash, there is a question as to what happens if the referenced object changes (in this case, the shared styles being modified). This could be addressed by either requiring that the styles referenced are static (which differs the conclusion we came to on Thursday about how style sharing should work), or perhaps the hash could dynamically update all existing references if the target is updated.

3. Global prefix on idrefs

The idref definition could be updated to support some sort of special global prefix:

<template>
  <template>
    <style id="foo">
    ...
    </style>
  </template>
  <link rel="stylesheet" href="global:#foo">
</template>

The specific global prefix is open to suggestions. A double-octothorpe (##) could be an intuitive alternative. The definition for identifiers allows for any ASCII character, so any option is a potential compatibility-breaking change: https://dom.spec.whatwg.org/#concept-id

This would work nicely with the style sharing scenario, but I have some concerns from an implementation standpoint. This has additional costs of either 1) doing a traversal of all shadow roots to query the element ID or 2) Always storing elements-by-id twice, once in their own tree scope and again globally, even if global references aren't used anywhere.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions