Search code examples
javascripthtmlcssshadow-dom

Change shadow dom rem size


I am using a shadow DOM for CSS isolation. I want the rem font size to use the HTML element font size in the shadow DOM.

The font in <div class="shadow-div">shadow DOM font (should be 100px)</div> should be 100px but the rem size is still 16px.

Here is a small code snippet demonstrating what I want to do.

<style>
  html {
    font-size: 16px;
  }
</style>
<div>light dom font</div>

<div id="root"></div>

<script>
  const root = document.getElementById('root');
  root.attachShadow({ mode: 'open' });

  const html = document.createElement('html')
  html.innerHTML = `
            <head>
                <style>
                    html {
                        font-size: 100px;
                    }

                    .shadow-div {
                        font-size: 1rem;
                    }
                </style>
            </head>
            
            <body>
                <div class="shadow-div">shadow dom font (should be 100px)</div>
            </body>
        `;

  root.shadowRoot.appendChild(html);
</script>


Solution

  • shadowRoots are not Documents, so don't have <html><head><body> markup;
    shadowRoots are more like DocumentFragments

    You style shadow content based from the :host selector; and since shadow DOM is encapsulated, there is less need for classes to target that one DIV

    REMs are always based on the html definition; use em instead inside the Component

    Also note how inheritable properties, like color 'trickle down' into Components and do style content inside shadowDOM (font-size also, but you overload it in the Component in this code)
    see: https://lamplightdev.com/blog/2019/03/26/why-is-my-web-component-inheriting-styles/

    That simplifies your code to:

    <style>
      html { font-size: 10px }
      body { font-size: 3rem; color:green }
    </style>
    
    <div>3rem body font-size = 3 * html font-size</div>
    <div id="root"></div>
    
    <script>
      document.getElementById('root')
        .attachShadow({ mode: 'open' })
        .innerHTML = `<style>
                        :host { font-size: 50px }
                        div   { font-size: 2rem }
                        p     { font-size: .5em }
                     </style>
                     50px Component font-size
                     <div>2rem = 2 * html font-size = 20px</div>
                     <p>.5em = .5 * :host font-size = 25px</p>`;
    </script>