- Kurt Catti-Schmidt
- Noam Rosenthal
This document is intended as a starting point for engaging the community and standards bodies in developing collaborative solutions fit for standardization. As the solutions to problems described in this document progress along the standards-track, we will retain this document as an archive and use this section to keep the community up-to-date with the most current standards venue and content location of future work and discussions.
- This document status: Active
- Expected venue: WHAT Working Group
- Current version: this document
Modern web development practices have converged towards building reusable components instead of building monolithic documents. Frameworks such as React and Angular have popularized this approach, which has made its way natively to the web platform via Web Components.
Web Components allow for defining custom elements, and these custom elements
often rely on Shadow DOM for ID encapsulation. But Shadow DOM doesn't just
encapsulate ID's - it encapsulates style as well. The current preferred approach
for styling elements under a Shadow DOM is through <link>
tags, but these tags
have several downsides, namely that they must be an external file or a dataURI.
The performance of an external file and developer ergonomics of generating a
dataURI make both of these options difficult to use. Because of that, developers
using Custom Elements have expressed strong interest in addressing these issues.
This explainer proposes a solution to this situation by allowing another option
for sharing styles via the <link>
tag - local references to <style>
elements.
- Allow developers to share styles defined in the Light DOM document into Shadow DOM trees.
- Allow developers to define their CSS up-front in the same document as their HTML when using Shadow DOM.
- Define a mechanism that will allow for more selective style sharing via CSS
@sheet
. - Provide a foundation for allowing inline styles to be defined but not applied
via
@sheet
.
- Anything specific to
@sheet
should be discussed in its dedicated proposal. - Modifications to Shadow DOM scoping behaviors. This proposal depends on existing Shadow DOM behavior as currently defined. Styles defined in a Shadow DOM will remain inaccessible to the Light DOM.
We propose supporting fragment identifiers that reference the id
attribute of
a <style>
or <link>
tag:
<style id="inline_styles">
p {
color: blue;
}
</style>
<p>Outside Shadow DOM</p>
<template shadowrootmode="open">
<link rel="inline-stylesheet" href="#inline_styles" />
<p>Inside Shadow DOM</p>
</template>
With this functionality, the text "Inside Shadow DOM" will by styled blue, due
to the <link rel="inline-stylesheet" href="#inline_styles">
node's stylesheet
applying (along with the color: blue
rule applying via the p
selector in
that stylesheet).
A new value for the rel
attribute is used here to prevent legacy engines from
performing an unnecessary fetch with this markup. The name inline-stylesheet
is preliminary and open to discussion.
<link rel="stylesheet" href="foo.css" id="inline_styles" />
<p>Outside Shadow DOM</p>
<template shadowrootmode="open">
<link rel="inline-stylesheet" href="#inline_styles" />
<p>Inside Shadow DOM</p>
</template>
Developers may want to link to styles pulled into another <link>
tag. These
<link>
references may be internal files (via inline-stylesheet
), or external
files. Loop detection may be necessary for references to another
inline-stylesheet
.
<template shadowrootmode="open">
<style id="inline_styles_from_shadow">
p {
color: blue;
}
</style>
<p>Inside Shadow DOM</p>
</template>
<link rel="stylesheet" href="foo.css" id="#inline_styles_from_shadow" />
<p>
Outside Shadow DOM. Styles defined inside the Shadow Root are not applied, so
this text is not blue.
</p>
Due to existing Shadow DOM scoping behaviors, <style>
tags defined inside the
Shadow DOM cannot be accessed from the Light DOM.
<link>
tags referencing external files are always treated as separate
instances, even when they refer to the same file. This also occurs with CSS
@import
statements as defined in
https://www.w3.org/TR/css-cascade-3/#import-processing.
However, in this situation, it might make more sense to behave like SVG <use>
(and other reference-based SVG elements) by behaving as if it's a reference to
the original stylesheet instead of a deep copy. This will allow for styles to
stay in sync when the stylesheet changes. This behavior could improve developer
ergonomics by keeping stylesheets in sync. This approach could also provide
memory savings due to the fact that there would only be one stylesheet in memory
instead of many copies.
This proposal augments the HTML <link>
tag in two ways:
- A new value for the
<link>
tag'srel
attribute to indicate a local fragment. We are currently using the valueinline-stylesheet
, but this name is open to suggestions. - Fragment identifiers to same-document
<style>
tags are supported in thehref
attribute when therel
attribute isinline-stylesheet
.
- Declarative CSS Modules are another mechanism for sharing styles between Declarative Shadow DOM and Light DOM without the use of JavaScript.
- External CSS files in
<link>
tags - these are always asychronous (which may not be desired), and may have negative performance implications due to the need to fetch another resource. - CSS-encoded DataURI references in
<link>
tags - this approach avoids some of the issues with 2), but has poor developer ergonomics due to dataURI encoding. Furthermore, there is no ability to automatically synchronize dataURI values.
- "Deep Clone vs Reference" listed above is the biggest outstanding issue.
- The name
inline-stylesheet
can be refined (or revisited if it's not necessary to define a newrel
value).
Many thanks for valuable feedback and advice from:
- Alison Maher
- Andy Luhrs
- Daniel Clark
- Kevin Babbitt
- Rob Glidden