slot is good to make a reusable web component, however, it has a limit so far. What I faced is the style problem. You just can't define the style inside a component, even you know what the inject content's structure would be.
Details found from my post in github here
I write a component, and try to inject content through slot from the outside and try to add style to the specific content in the component's shadow root.
Demo
HTML file
  <my-navbar>
    <ul>
      <li>link1</li>
      <li>link2</li>
      <li>link3</li>
      </ul>
  </my-navbar>
JS file
customElements.define('my-navbar', class extends HTMLElement {
  constructor () {
    super();
    const sr = this.attachShadow({ mode: 'open' });
    sr.innerHTML = `
      <style>
      /*worked*/
      ::slotted(ul)
      {
        color:green;
      }
      /*
      Suppose I know the outside content is "ul li", and I directly define the 
      style after they injected into component's slot. However, it just doesn't 
      work because the slotted selector is just a compound selector. It can only 
      affect the first layer 'ul'. It can't affect the child dom 'li' */
      ::slotted(ul li)
      {
        color:red;
      }
      </style>
      <slot></slot>
    `;
  }
});
However, it just doesn't work directly because you just can't use a complex selector for ::slot(simple_selector) Reason
I found an indirect solution, and that's to re-append the outside content into the slots inside the component's shadow root. Demo
HTML file
  <my-navbar>
    <!--a dom defined a slot property-->
    <ul slot='t'>
      <li>link1</li>
      <li>link2</li>
      <li>link3</li>
      </ul>
    <!--A dom not define slot property-->
    <span>1234</span>
  </my-navbar>
JS file
customElements.define('my-navbar', class extends HTMLElement {
  constructor () {
    super();
    const sr = this.attachShadow({ mode: 'open' });
    sr.innerHTML = `
      <style>
      ul li
      {
        color:red;
      }
      </style>
      <slot name='t'></slot>
      <slot ></slot>
    `;
    // Do something later...
    setTimeout(this.appendOutsideSlotContentIntoInsideSlot.bind(this), 1000)
  }
    appendOutsideSlotContentIntoInsideSlot()
  {
    // Insert outside dom element which has define slot property into the specify slot inside the shadow root
    debugger;
     for (let objIndex=0;objIndex<this.children.length;) 
     {
        var obj=this.children[objIndex];
        if(obj.slot){
          var slot=this.shadowRoot.querySelector('slot[name='+obj.slot+']');
          if(slot)
          {
              slot.appendChild(obj);
              continue;
           }
       }
       objIndex++;
    }
    // Insert the rest dom which has not define slot property values into the anonymous slot
    var defaultSlot=Array.prototype.slice.call(this.shadowRoot.querySelectorAll('slot')).filter(function(el){ return !el.name})[0];
    debugger;
    if(defaultSlot)
      {
         while (this.children.length>0) 
        {
          defaultSlot.appendChild(this.children[0])
        }
      }
  }
});
Well, it works for the contents which have defined the slot property, but doesn't work again with content that has no slot property.