代码之家  ›  专栏  ›  技术社区  ›  junvar

与自定义HTML元素共享样式?

  •  3
  • junvar  · 技术社区  · 7 年前

    我开始使用自定义元素,但有一件事我搞不清楚,那就是共享样式。例如,如果我有两个自定义元素, <element-1> <element-2> ,两者都包含 <button> 的,我希望所有的按钮都有特定的样式,例如。 font-size:20px .

    我考虑过的选项有:

    1. <stylized-button> 自定义元素而不是 <按钮> 在自定义元素中。这在外部采购时是有问题的 <元素1> color:red )仅打开 < <元素2>

    2. /dead/ :shadow 似乎很有希望,但不再得到支持。

    3. @apply [2] 看起来很有希望,但提议被撤回了。

    4. ::part ::theme [3] 似乎更有希望,但尚未得到支持。

    5. 使用js支持 ●部分 ●主题

    6. class Element1 extends HTMLElement {
          constructor() {
              this.shadowRoot.addElement(sharedStyle);
          }
      }
      

      这似乎非常有限&手动。也可能影响性能?如果你从外部采购也有问题 < .

    现在,我认为#5可能是最好的,因为它似乎是最通用的/最容易使用的,无需专门为它构建,而且它在实现时会使到#4的转换变得微不足道。 但我想知道是否有其他的方法或建议?

    https://www.polymer-project.org/3.0/docs/devguide/style-shadow-dom

    http://tabatkins.github.io/specs/css-apply-rule/

    [3] https://meowni.ca/posts/part-theme-explainer/

    [4] 一个简单的实现和一个使用它的示例: https://gist.github.com/mahhov/cbb27fcdde4ad45715d2df3b3ce7be40

    实施:

    document.addEventListener('DOMContentLoaded', () => {
        // create style sheets for each shadow root to which we will later add rules
        let shadowRootsStyleSheets = [...document.querySelectorAll('*')]
            .filter(element => element.shadowRoot)
            .map(element => element.shadowRoot)
            .map(shadowRoot => {
              shadowRoot.appendChild(document.createElement('style'));
              return shadowRoot.styleSheets[0];
            });
    
        // iterate all style rules in the document searching for `.theme` and `.part` in the selectors.
        [...document.styleSheets]
            .flatMap(styleSheet => [...styleSheet.rules])
            .forEach(rule => {
              let styleText = rule.cssText.match(/\{(.*)\}/)[1];
    
              let match;
              if (match = rule.selectorText.match(/\.theme\b(.*)/))
                shadowRootsStyleSheets.forEach(styleSheet => styleSheet.addRule(match[1], styleText));
              else if (match = rule.selectorText.match(/\.part\b(.*)/))
                shadowRootsStyleSheets.forEach(styleSheet => styleSheet.addRule(`[part=${match[1]}]`, styleText));
            });
      });
    

    以及用法:

    <style>
      .my-element.part line-green {
        border: 1px solid green;
        color: green;
      }
    
      .theme .line-orange {
        border: 1px solid orange;
        color: orange;
      }
    
      /*
        must use `.part` instead of `::part`, and `.theme` instead of `::theme`
        as the browser prunes out invalid css rules form the `StyleSheetList`'s. 
      */
    </style>
    
    <template id="my-template">
      <p part="line-green">green</p>
      <p class="line-orange">orange</p>
    </template>
    
    <my-element></my-element>
    
    <script>
      customElements.define('my-element', class extends HTMLElement {
        constructor() {
          super();
          this.attachShadow({mode: 'open'});
          const template = document.getElementById('my-template').content.cloneNode(true);
          this.shadowRoot.appendChild(template);
        }
      });
    </script>
    
    2 回复  |  直到 7 年前
        1
  •  1
  •   Supersharp    7 年前

    你可以用 @import url 将外部样式表导入不同的自定义元素。

    或者现在你也可以使用 <link rel="stylesheet"> 在自定义元素阴影DOM中:

    <template id="element-1">
      <style> 
          @import url( 'button-style.css' )
      </style>
      <button>B-1</button>
    </template>
    
    <template id="element-2">
      <link rel="stylesheet" href="button-style.css">
      <button>B-2</button>
    </template>
    
        2
  •  -1
  •   object-Object    7 年前

    如果您使用的是css,您可以这样做:

    button {
    
      /* Put Style Here */  
    
    }
    

    您还必须在html的头部添加一个链接:

    <link rel=“stylesheet” href=“the address”>