Inject CSS Modules to Per-Component Style Elements (for portability to shadow root)
Asked Answered
K

2

20

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

Katey answered 16/12, 2019 at 9:29 Comment(4)
Have you checked out react-shade?Beaudette
can you tell me why do you need this ?Manuelmanuela
@AmirRezvani I'm looking to convert existing React components using CSS Modules for styling to run inside shadowRoots. A straightforward solution would be to have each component come with a self-contained style element.Katey
@RossAllen thank you - I'm familiar with react-shade, however AFAIK it requires a rewrite of styling from e.g. CSS Modules (using SCSS in my case) to Styled Components or JS object-based styles.Katey
L
0

Two years too late, but:

I'm not quite sure if this is what you want, but in React you can add style directly into JSX like this:

  <style>
    {`
      body {
        font-family: 'Inter', sans-serif;
        font-size: 14px;
        background-color: #151515;
        color: white;
      }
    `}
  </style>

or using your example:

<style>
    {`
      .myComponent__container__hash123 { 
        background: purple;
      }
    `}
</style>
Live answered 30/8, 2021 at 22:56 Comment(0)
F
0

You can use Webpack "style-loader" plugin with insert parameter.

          {
            loader: "style-loader",
            options: {
              injectType: "lazyStyleTag",
              insert: function insertIntoTarget(element, options) {
                var parent = options.target || document.head;
                parent.appendChild(element);
              },
            },
          },

Refer to this for more details.

Financial answered 8/11, 2022 at 18:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.