Search code examples
cssflexboxweb-componentshadow-domstenciljs

How to use Flexbox with web components and shadow DOM


I'm working on a web app that uses web components built by StencilJS. All of the components have Shadow DOM turned on. Many of the components use 'slots' to accept child content.

I'm having some trouble using Flexbox to lay out this app. A scenario I keep running into is, I want one component to serve as a Flexbox container, and its children to be Flex items.

I suspect Shadow DOM is blocking my Flexbox. Is there a way to make Flexbox work with web components and Shadow DOM?

Example:

<web-component-a>
  <web-component-b></web-component-b>
  <web-component-b></web-component-b>
  <web-component-b></web-component-b>
</web-component-a>

Solution

  • You can simply style the slot element as shown below:

    class WebComponentA extends HTMLElement {
      constructor() {
        super();
    
        const shadowRoot = this.attachShadow({mode: 'open'});
    
    
        shadowRoot.innerHTML = `
          <style>
            slot {
              display: flex;
              flex-direction: row;
            }
          </style>
          <div>
            <slot></slot>
          </div>
        `;
      }
    
    }
    
    window.customElements.define('web-component-a', WebComponentA);
    

    If you have more than one slot element (named slots), you can use CSS attribute based selector like:

    slot[name=title] {}
    

    If you want to override the styling for slotted content from within the web component, you can use the ::slotted() selector:

    slot::slotted(*) {
      font-size: 2rem;
    }