Skip to content

Instantly share code, notes, and snippets.

What would you like to do?

Proposal: Importable Constructable Stylesheets

We're getting Constructable Stylesheets. This seems like an intuitive value to obtain when importing CSS from JavaScript, since it's the DOM's representation of a Stylesheet:

import stylesheet from './style.css';
console.log(stylesheet);  // CSSStyleSheet

No such system is in place to allow this to work (see whatwg/loader), however frontend build tooling has congregated around this approach as a mechanism for bringing CSS assets into the JavaScript module graph. There are many benefits to be obtained from moving CSS into this graph, however the most important is that imported CSS can be attributed to the consuming JS Module. This allows it to be bundled, optimized, and potentially dead-code-eliminated leveraging static analysis performed on the surrounding module graph.

However, given the existence of CSSStyleSheet as a 1:1 representation of a stylesheet, it's possible we now have a case for why CSS deserves special treatment.

import sheet from './style.css';

// global CSS:
document.adoptedStyleSheets = [sheet];

const node = document.createElement('div');
const shadow = node.attachShadow({ mode: 'open' });
// scoped CSS:
shadow.adoptedStyleSheets = [sheet];

// Updates! (propagates out to all affected trees)
sheet.insertRule('.foo { color: red; }');

// "hot CSS replacement":'style.css', req => {
// in your ServiceWorker: importScripts('polyfill.js')
addEventListener('fetch', e => {
if (e.request.destination === 'script' && e.request.url.endsWith('.css')) {
let res;
.then(r => (res = r).text())
.then(css => {
const headers = new Headers(res.headers);
headers.set('content-type', 'application/javascript');
return new Response(`
let s = new CSSStyleSheet();
export default s;
`, { headers });
Copy link

developit commented Jan 31, 2019

Copy link

littledan commented Mar 6, 2019

Impressive! I'm excited for CSS imports. Nit: Is this form of the CSSStyleSheet constructor, of being called with a string argument, standards-track? I just see an options bag as the argument in the draft spec, and calls without arguments in the explainer.

Copy link

developit commented Apr 18, 2019

@littledan - oops, that was a mistake! Fixed.

Copy link

Jack-Works commented Sep 7, 2019 I made an example (not follow the spec so strict)

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