TL:DR
How can I get CSS of React components to work inside of a shadow root, while keeping the
encapsulation benefits of CSS Modules class? I'd like to insert per-component <style>
elements instead of inside of <head>
or another arbitrary element.
What I have
I'm currently using CSS Modules in React with a custom Webpack script; [style-loader, css-loader, sass-loader]
in the traditional way. The resulting compiled CSS is injected as <style>
tags in head
.
// MyComponent.jsx
import React from 'react';
import styles from './MyComponent.scss';
export const MyComponent = () => {
return <div className={styles.container}>Hello!</div>
}
// MyComponent.scss
.container {
background: purple;
}
result
<!-- rendered page -->
<head>
...
<style>.myComponent__container__hash123 { background: purple }</style>
</head>
<body>
...
<div class="myComponent__container__hash123">Hello!</div>
</body>
What I want
For use inside of a shadow root, I would like to instead inject each component's compiled CSS into a <style>
tag on its root.
<!-- rendered page -->
<head>
...
</head>
<body>
...
<div>
#shadow-root
<div class="myComponent__container__hash123">Hello!</div>
<style>.myComponent__container__hash123 { background: purple }</style>
#end shadow-root
</div>
</body>
What I tried
1. insert
This will not work for component libraries which compile themselves, where I cannot know the end consumer in advance.
2. to-string-loader
https://www.npmjs.com/package/css-to-string-loader
When combined with style-loader
, the result is classnames aren't resolved (e.g. styles.container === undefined
).
Ideally I would have import styles from './MyComponent'
contain the compiled CSS string in addition to classname mapping - however this is not supported as per style-loader docs