<template id="template">
  <style>
    ul {
      padding: 0;
      list-style: none;
    }

    ::slotted(li) {
      padding: 1em !important;
      background: rgb(250, 250, 250);
    }

    ::slotted(li:nth-child(2n - 1)) {
      background: rgb(230, 230, 230);
    }

    .dark ::slotted(li) {
      color: #fff;
      background: rgb(50, 50, 50);
    }

    .dark ::slotted(li:nth-child(2n - 1)) {
      background: rgb(10, 10, 10);
    }
  </style>
  <ul id="list">
    <slot name="items"></slot>
  </ul>
</template>
<div class="wrapper">
  <my-list id="my-list">
    <li slot="items">football</li>
    <li slot="items">baseball</li>
    <li slot="items">basketball</li>
    <li slot="items">golf</li>
    <li slot="items">tennis</li>
  </my-list>
  <div class="btns">
    <button id="light">ライトモード</button><button id="dark">ダークモード</buttoni>
  </div>
</div>
* {
  box-sizing: border-box;
}
.wrapper {
  padding: 1rem;
  min-height: 100vh;
}
.wrapper {
  padding: 1rem;
  min-height: 100vh;
}
.btns {
  margin-top: 2rem;
}
.btns button + button {
  margin-left: 1rem;
}
View Compiled
class MyList extends HTMLElement {
  constructor() {
    super();
    this.theme = "light";
    this.template;
    this.attachShadow({ mode: "open" });
  }

  connectedCallback() {
    this.theme = this.getAttribute("theme") || "light";
    this.render();
  }

  static get observedAttributes() {
    return ["theme"];
  }

  attributeChangedCallback(name, oldValue, newValue) {
    switch (name) {
      case "theme":
        this.theme = newValue;
      default:
        break;
    }
    this.render();
  }

  getTemplate() {
    const template = this.template
      ? this.template
      : document.getElementById("template");
    return template;
  }

  render() {
    this.tempate = this.getTemplate();
    const node = this.tempate.content.cloneNode(true);
    const theme = {
      newValue: this.theme,
      oldValue: this.theme === "light" ? "dark" : "light"
    };
    node.getElementById("list").classList.remove(theme.oldValue);
    node.getElementById("list").classList.add(theme.newValue);
    this.shadowRoot.innerHTML = "";
    this.shadowRoot.appendChild(node);
  }
}

customElements.define("my-list", MyList);

const sortedList = document.getElementById("my-list");
const ascBtn = document.getElementById("light");
const descBtn = document.getElementById("dark");
ascBtn.addEventListener("click", () => {
  sortedList.setAttribute("theme", "light");
});
descBtn.addEventListener("click", () => {
  sortedList.setAttribute("theme", "dark");
});
View Compiled

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.