Menu Search
Jump to the content X X
Smashing Conf Barcelona

You know, we use ad-blockers as well. We gotta keep those servers running though. Did you know that we publish useful books and run friendly conferences — crafted for pros like yourself? E.g. our upcoming SmashingConf Barcelona, dedicated to smart front-end techniques and design patterns.

Styling Web Components Using A Shared Style Sheet

Web components1 are an amazing new feature of the web, allowing developers to define their own custom HTML elements. When combined with a style guide, web components can create a component API2, which allows developers to stop copying and pasting code snippets and instead just use a DOM element. By using the shadow DOM, we can encapsulate the web component and not have to worry about specificity wars3 with any other style sheet on the page.

However, web components and style guides currently seem to be at odds with each other. On the one hand, style guides provide a set of rules and styles that are globally applied to the page and ensure consistency across the website. On the other hand, web components with the shadow DOM prevent any global styles from penetrating their encapsulation, thus preventing the style guide from affecting them.

Further Reading on SmashingMag: Link

So, how can the two co-exist, with global style guides continuing to provide consistency and styles, even to web components with the shadow DOM? Thankfully, there are solutions that work today, and more solutions to come, that enable global style guides to provide styling to web components. (For the remainder of this article, I will use the term “web components” to refer to custom elements with the shadow DOM.)

What Should A Global Style Guide Style In A Web Component? Link

Before discussing how to get a global style guide to style a web component, we should discuss what it should and should not try to style.

First of all, current best practices for web components7 state that a web component, including its styles, should be encapsulated, so that it does not depend on any external resources to function. This allows it to be used anywhere on or off the website, even when the style guide is not available.

Below is a simple log-in form web component that encapsulates all of its styles.

<template id="login-form-template">
  <style>
    :host {
      color: #333333;
      font: 16px Arial, sans-serif;
    }

    p {
      margin: 0;
    }

    p + p {
      margin-top: 20px;
    }

    a {
      color: #1f66e5;
    }

    label {
      display: block;
      margin-bottom: 5px;
    }

    input[type="text"],
    input[type="password"] {
      background-color: #eaeaea;
      border: 1px solid grey;
      border-radius: 4px;
      box-sizing: border-box;
      color: inherit;
      font: inherit;
      padding: 10px 10px;
      width: 100%;
    }

    input[type="submit"] {
      font: 16px/1.6 Arial, sans-serif;
      color: white;
      background: cornflowerblue;
      border: 1px solid #1f66e5;
      border-radius: 4px;
      padding: 10px 10px;
      width: 100%;
    }

    .container {
      max-width: 300px;
      padding: 50px;
      border: 1px solid grey;
    }

    .footnote {
      text-align: center;
    }
  </style>

  <div class="container">
    <form action="#">
      <p>
        <label for="username">User Name</label>
        <input type="text" id="username" name="username">
      </p>
      <p>
        <label for="password">Password</label>
        <input type="password" id="password" name="password">
      </p>
      <p>
        <input type="submit" value="Login">
      </p>
      <p class="footnote">Not registered? <a href="#">Create an account</a></p>
    </form>
  </div>
</template>

<script>
  const doc = (document._currentScript || document.currentScript).ownerDocument;
  const template = doc.querySelector('#login-form-template');

  customElements.define('login-form', class extends HTMLElement {
    constructor() {
      super();

      const root = this.attachShadow({mode: 'closed'});
      const temp = document.importNode(template.content, true);

      root.appendChild(temp);
    }
  });
</script>

Note: Code examples are written in the version 1 specification for web components.

Log-in form with user name and password.8

A simple log-in form web component

However, fully encapsulating every web component would inevitably lead to a lot of duplicate CSS, especially when it comes to setting up the typography and styling of native elements. If a developer wants to use a paragraph, an anchor tag or an input field in their web component, it should be styled like the rest of the website.

If we fully encapsulate all of the styles that the web component needs, then the CSS for styling paragraphs, anchor tags, input fields and so on would be duplicated across all web components that use them. This would not only increase maintenance costs, but also lead to much larger download sizes for users.

Instead of encapsulating all of the styles, web components should only encapsulate their unique styles and then depend on a set of shared styles to handle styles for everything else. These shared styles would essentially become a kind of Normalize.css9, which web components could use to ensure that native elements are styled according to the style guide.

In the previous example, the log-in form web component would declare the styles for only its two unique classes: .container and .footnote. The rest of the styles would belong in the shared style sheet and would style the paragraphs, anchor tags, input fields and so on.

In short, the style guide should not try to style the web component, but instead should provide a set of shared styles that web components can use to achieve a consistent look.

How Styling The Shadow DOM With External Style Sheets Used To Be Done Link

The initial specification for web components (known as version 0) allowed any external style sheet to penetrate the shadow DOM through use of the ::shadow or /deep/ CSS selectors. The use of ::shadow and /deep/ enabled you to have a style guide penetrate the shadow DOM and set up the shared styles, whether the web component wanted you to or not.

/* Style all p tags inside a web components shadow DOM */
login-form::shadow p {
  color: red;
}

With the advent of the newest version of the web components specification (known as version 1), the authors have removed the capability10 of external style sheets to penetrate the shadow DOM, and they have provided no alternative. Instead, the philosophy has changed from using dragons to style web components11 to instead using bridges. In other words, web component authors should be in charge of what external style rules are allowed to style their component, rather than being forced to allow them.

Unfortunately, that philosophy hasn’t really caught up with the web just yet, which leaves us in a bit of a pickle. Luckily, a few solutions available today, and some coming in the not-so-distant future, will allow a shared style sheet to style a web component.

What You Can Do Today Link

There are three techniques you can use today that will allow a web component to share styles: @import, custom elements and a web component library.

Using @import Link

The only native way today to bring a style sheet into a web component is to use @import. Although this works, it’s an anti-pattern12. For web components, however, it’s an even bigger performance problem.

<template id="login-form-template">
  <style>
    @import "styleguide.css"
  </style>

  <style>
    .container {
      max-width: 300px;
      padding: 50px;
      border: 1px solid grey;
    }

    .footnote {
      text-align: center;
    }
  </style>

  <!-- rest of template DOM -->
</template>

Normally, @import is an anti-pattern because it downloads all style sheets in series, instead of in parallel, especially if they are nested. In our situation, downloading a single style sheet in series can’t be helped, so in theory it should be fine. But when I tested13 this in Chrome, the results showed that using @import caused the page to render up to a half second slower14 than when just embedding the styles directly15 into the web component.

Note: Due to differences in how the polyfill of HTML imports16 works compared to native HTML imports, WebPagetest.org17 can only be used to give reliable results in browsers that natively support HTML imports (i.e. Chrome).

Bar graph of native web component performance.18

Results from three performance tests show that @import causes the browser to render up to a half second slower than when just embedding the styles directly into the web component.

In the end, @import is still an anti-pattern and can be a performance problem in web components. So, it’s not a great solution.

Don’t Use the Shadow DOM Link

Because the problem with trying to provide shared styles to web components stems from using the shadow DOM, one way to avoid the problem entirely is to not use the shadow DOM.

By not using the shadow DOM, you will be creating custom elements19 instead of web components (see the aside below), the only difference being the lack of the shadow DOM and scoping. Your element will be subject to the styles of the page, but we already have to deal with that today, so it’s nothing that we don’t already know how to handle. Custom elements are fully supported by the webcomponentjs polyfill, which has great browser support20.

The greatest benefit of custom elements is that you can create a pattern library21 using them today, and you don’t have to wait until the problem of shared styling is solved. And because the only difference between web components and custom elements is the shadow DOM, you can always enable the shadow DOM in your custom elements once a solution for shared styling is available.

If you do decide to create custom elements, be aware of a few differences between custom elements and web components.

First, because styles for the custom element are subject to the page styles and vice versa, you will want to ensure that your selectors don’t cause any conflicts. If your pages already use a style guide, then leave the styles for the custom element in the style guide, and have the element output the expected DOM and class structure.

By leaving the styles in the style guide, you will create a smooth migration path for your developers, because they can continue to use the style guide as before, but then slowly migrate to using the new custom element when they are able to. Once everyone is using the custom element, you can move the styles to reside inside the element in order to keep them together and to allow for easier refactoring to web components later.

Secondly, be sure to encapsulate any JavaScript code inside an immediately invoked function expression (IFFE), so that you don’t bleed any variables to the global scope. In addition to not providing CSS scoping, custom elements do not provide JavaScript scoping.

Thirdly, you’ll need to use the connectedCallback function of the custom element to add the template DOM to the element22. According to the web component specification, custom elements should not add children during the constructor function, so you’ll need to defer adding the DOM to the connectedCallback function.

Lastly, the <slot> element does not work outside of the shadow DOM. This means that you’ll have to use a different method to provide a way for developers to insert their content into your custom element. Usually, this entails just manipulating the DOM yourself to insert their content where you want it.

However, because there is no separation between the shadow DOM and the light DOM with custom elements, you’ll also have to be very careful not to style the inserted DOM, due to your elements’ cascading styles.

<!-- login-form.html -->
<template id="login-form-template">
  <style>
    login-form .container {
      max-width: 300px;
      padding: 50px;
      border: 1px solid grey;
    }

    login-form .footnote {
      text-align: center;
    }
  </style>

  <!-- Rest of template DOM -->
</template>

<script>
(function() {
  const doc = (document._currentScript || document.currentScript).ownerDocument;
  const template = doc.querySelector('#login-form-template');

  customElements.define('login-form', class extends HTMLElement {
    constructor() {
      super();
    }

    // Without the shadow DOM, we have to manipulate the custom element
    // after it has been inserted in the DOM.
    connectedCallback() {
      const temp = document.importNode(template.content, true);
      this.appendChild(temp);
    }
  });
})();
</script>
<!-- index.html -->
<link rel="stylesheet" href="styleguide.css">
<link rel="import" href="login-form.html">

<login-form></login-form>

In terms of performance, custom elements are almost as fast23 as web components not being used24 (i.e. linking the shared style sheet in the head and using only native DOM elements). Of all the techniques you can use today, this is by far the fastest.

Bar graph of custom element performance.25

The results from two performance tests show that custom elements are almost as fast as not using web components at all.

Aside: A custom element is still a web component for all intents and purposes. The term “web components” is used to describe four separate technologies26: custom elements, template tags, HTML imports and the shadow DOM.

Unfortunately, the term has been used to describe anything that uses any combination of the four technologies. This has led to a lot of confusion around what people mean when they say “web component.” Just as Rob Dodson discovered27, I have found it helpful to use different terms when talking about custom elements with and without the shadow DOM.

Most of the developers I’ve talked to tend to associate the term “web component” with a custom element that uses the shadow DOM. So, for the purposes of this article, I have created an artificial distinction between a web component and a custom element.

Using a Web Component Library Link

Another solution you can use today is a web component library, such as Polymer28, SkateJS29 or X-Tag30. These libraries help fill in the holes of today’s support and can also simplify the code necessary to create a web component. They also usually provide added features that make writing web components easier.

For example, Polymer lets you create a simple web component in just a few lines of JavaScript. An added benefit is that Polymer provides a solution for using the shadow DOM and a shared style sheet31. This means you can create web components today that share styles.

To do this, create what they call a style module, which contains all of the shared styles. It can either be a <style> tag with the shared styles inlined or a <link rel="import"> tag that points to a shared style sheet. In either case, include the styles in your web component with a <style include> tag, and then Polymer will parse the styles and add them as an inline <style> tag to your web component.

<!-- shared-styles.html -->
<dom-module id="shared-styles">
  <!-- Link to a shared style sheet -->
  <!-- <link rel="import" href="styleguide.css"> -->

  <!-- Inline the shared styles -->
  <template>
    <style>
    :host {
      color: #333333;
      font: 16px Arial, sans-serif;
    }

    /* Rest of shared CSS */
    </style>
  </template>
</dom-module>
<!-- login-form.html -->
<link rel="import" href="../polymer/polymer.html">
<link rel="import" href="../shared-styles/shared-styles.html">

<dom-module id="login-form">
  <template>
    <!-- Include the shared styles -->
    <style include="shared-styles"></style>

    <style>
      .container {
        max-width: 300px;
        padding: 50px;
        border: 1px solid grey;
      }

      .footnote {
        text-align: center;
      }
    </style>

    <!-- Rest of template DOM -->
  </template>

  <script>
  Polymer({
    is: 'login-form'
  });
  </script>
</dom-module>

The only downside to using a library is that it can delay the rendering time of your web components. This shouldn’t come as a surprise because downloading the library’s code and processing it take time. Any web components on the page can’t begin rendering until the library is done processing.

In Polymer’s case, it can delay the page-rendering time by up to half a second compared to native web components. A style module that embeds the styles32 is slightly slower than a style module that links the styles33, and embedding the styles directly into the web component34 is just as fast as using a style module.

Again, Polymer does nothing in particular to make the rendering time slower. Downloading the Polymer library and processing all of its awesome features, plus creating all of the template bindings, take time. It’s just the trade-off you’ll have to make to use a web component library.

Bar graph of Polymer web component performance.35

Results from performance tests show that, using Polymer, web components will render up to half a second slower than native web components.

The Promise Of The Future Link

If none of the current solutions work for you, don’t despair. If all goes well, within a few months to a few years, we’ll be able to use shared styles using a few different approaches.

Custom Properties Link

Custom properties36 (or CSS variables37, as they’ve been called) are a way to set and use variables in CSS. This notion is not new to CSS preprocessors, but as a native CSS feature, custom properties are actually more powerful than a preprocessor variable38.

To declare a custom property, use the custom property notation of --my-variable: value, and access the variable using property: var(--my-variable). A custom property cascades like any other CSS rule, so its value inherits from its parent and can be overridden. The only caveat to custom properties is that they must be declared inside a selector and cannot be declared on their own, unlike a preprocessor variable.

<style>
/* Declare the custom property */
html {
  --main-bg-color: red;
}

/* Use the custom property */
input {
  background: var(--main-bg-color);
}
</style>

One thing that makes custom properties so powerful is their ability to pierce the shadow DOM. This isn’t the same idea as the /deep/ and ::shadow selectors because they don’t force their way into the web component. Instead, the author of the web component must use the custom property in their CSS in order for it to be applied. This means that a web component author can create a custom property API that consumers of the web component can use to apply their own styles.

<template id="my-element-template">
  <style>
  /* Declare the custom property API */
  :host {
    --main-bg-color: brown;
  }

  .one {
    color: var(--main-bg-color);
  }
  </style>

  <div class="one">Hello World</div>
</template>

<script>
/* Code to set up my-element web component */
</script>

<my-element></my-element>

<style>
/* Override the custom variable with own value */
my-element {
  --main-bg-color: red;
}
</style>

Browser support for custom properties is surprisingly good39. The only reason it is not a solution you can use today is that there is no working polyfill40 without Custom Elements version 1. The team behind the webcomponentjs polyfill is currently working to add it41, but it is not yet released and in a built state, meaning that if you hash your assets for production, you can’t use it. From what I understand, it’s due for release sometime early next year.

Even so, custom properties are not a good method for sharing styles between web components. Because they can only be used to declare a single property value, the web component would still need to embed all of the styles of the style guide, albeit with their values substituted with variables.

Custom properties are more suited to theming options, rather than shared styles. Because of this, custom properties are not a viable solution to our problem.

@apply Rules Link

In addition to custom properties, CSS is also getting @apply rules42. Apply rules are essentially mixins for the CSS world43. They are declared in a similar fashion to custom properties but can be used to declare groups of properties instead of just property values. Just like custom properties, their values can be inherited and overridden, and they must be declared inside a selector in order to work.

<style>
/* Declare rule */
html {
  --typography: {
    font: 16px Arial, sans-serif;
    color: #333333;
  }
}

/* Use rule */
input {
  @apply --typography;
}
</style>

Browser support for @apply rules is basically non-existent. Chrome currently supports it44 behind a feature flag (which I couldn’t find), but that’s about it. There is also no working polyfill for the same reason as there is no polyfill for custom properties. The webcomponentjs polyfill team is also working to add @apply rules, along with custom properties, so both will be available once the new version is released.

Unlike custom properties, @apply rules are a much better solution for sharing styles. Because they can set up a group of property declarations, you can use them to set up the default styling for all native elements and then use them inside the web component. To do this, you would have to create an @apply rule for every native element.

However, to consume the styles, you would have to apply them manually to each native element, which would still duplicate the style declaration in every web component. While that’s better than embedding all of the styles, it isn’t very convenient either because it becomes boilerplate at the top of every web component, which you have to remember to add in order for styles to work properly.

/* styleguide.css */
html {
  --typography: {
    color: #333333;
    font: 16px Arial, sans-serif;
  }

  --paragraph: {
    margin: 0;
  }

  --label {
    display: block;
    margin-bottom: 5px;
  }

  --input-text {
    background-color: #eaeaea;
    border: 1px solid grey;
    border-radius: 4px;
    box-sizing: border-box;
    color: inherit;
    font: inherit;
    padding: 10px 10px;
    width: 100%;
  }

  --input-submit {
    font: 16px/1.6 Arial, sans-serif;
    color: white;
    background: cornflowerblue;
    border: 1px solid #1f66e5;
    border-radius: 4px;
    padding: 10px 10px;
    width: 100%;
  }

  /* And so on for every native element */
}
<!-- login-form.html -->
<template id="login-form-template">
  <style>
    :host {
      @apply --typography;
    }

    p {
      @apply --paragraph;
    }

    label {
      @apply --label;
    }

    input-text {
      @apply --input-text;
    }

    .input-submit {
      @apply --input-submit;
    }

    .container {
      max-width: 300px;
      padding: 50px;
      border: 1px solid grey;
    }

    .footnote {
      text-align: center;
    }
  </style>

  <!-- Rest of template DOM -->
</template>

Due to the need for extensive boilerplate, I don’t believe that @apply rules would be a good solution for sharing styles between web components. They are a great solution for theming, though.

According to the web component specification45, browsers ignore any <link rel="stylesheet"> tags in the shadow DOM, treating them just like they would inside of a document fragment. This prevented us from being able to link in any shared styles in our web components, which was unfortunate — that is, until a few months ago, when the Web Components Working Group proposed that <link rel="stylesheet"> tags should work in the shadow DOM46. After only a week of discussion, they all agreed that they should, and a few days later they added it to the HTML specification47.

<template id="login-form-template">
  <link rel="stylesheet" href="styleguide.css">

  <style>
    .container {
      max-width: 300px;
      padding: 50px;
      border: 1px solid grey;
    }

    .footnote {
      text-align: center;
    }
  </style>

  <!-- rest of template DOM -->
</template>

If that sounds a little too quick for the working group to agree on a specification, that’s because it wasn’t a new proposal. Making link tags work in the shadow DOM was actually proposed at least three years ago48, but it was backlogged until they could ensure it wasn’t a problem for performance.

If acceptance of the proposal isn’t exciting enough, Chrome 55 (currently Chrome Canary) added the initial functionality49 of making link tags work in the shadow DOM. It even seems that this functionality has landed in the current version of Chrome50. Even Safari has implemented the feature in Safari 1851.

Being able to link in the shared styles is by far the most convenient method for sharing styles between web components. All you would have to do is create the link tag, and all native elements would be styled accordingly, without requiring any additional work.

Of course, the way browser makers implement the feature will determine whether this solution is viable. For this to work properly, link tags would need to be deduplicated, so that multiple web components requesting the same CSS file would cause only one HTTP request. The CSS would also need to be parsed only once, so that each instance of the web component would not have to recompute the shared styles, but would instead reuse the computed styles.

Chrome does both of these52 already. So, if all other browser makers implement it the same way, then link tags working in the shadow DOM would definitely solve the issue of how to share styles between web components.

Constructable Style Sheets Link

You might find it hard to believe, since we haven’t even got it yet, but a link tag working in the shadow DOM is not a long-term solution53. Instead, it’s just a short-term solution to get us to the real solution: constructable style sheets.

Constructable style sheets54 are a proposal to allow for the creation of StyleSheet objects in JavaScript through a constructor function. The constructed style sheet could then be added to the shadow DOM through an API, which would allow the shadow DOM to use a set of shared styles.

Unfortunately, this is all I could gather from the proposal. I tried to find out more information about what constructable style sheets were by asking the Web Components Working Group55, but they redirected me to the W3C’s CSS Working Group’s mailing list56, where I asked again, but no one responded. I couldn’t even figure out how the proposal was progressing, because it hasn’t been updated in over two years57.

Even so, the Web Components Working Group uses it58 as the solution59 for sharing styles60 between web components. Hopefully, either the proposal will be updated or the Web Components Working Group will release more information about it and its adoption. Until then, the “long-term” solution seems like it won’t happen in the foreseeable future.

Lessons Learned Link

After months of research and testing, I am quite hopeful for the future. It is comforting to know that after years of not having a solution for sharing styles between web components, there are finally answers. Those answers might not be established for a few more years, but at least they are there.

If you want to use a shared style guide to style web components today, either you can not use the shadow DOM and instead create custom elements, or you can use a web component library that polyfills support for sharing styles. Both solutions have their pros and cons, so use whichever works best for your project.

If you decide to wait a while before delving into web components, then in a few years we should have some great solutions for sharing the styles between them. So, keep checking back on how it’s progressing.

Things To Keep In Mind Link

Keep in mind a few things if you decide to use custom elements or web components today.

Most importantly, the web component specification is still being actively developed, which means that things can and will change. Web components are still very much the bleeding edge, so be prepared to stay on your toes as you develop with it.

If you decide to use the shadow DOM, know that it is quite slow61 and unperformant62 in polyfilled browsers63. It was for this reason that Polymer’s developers created their shady DOM implementation and made it their default.

Chrome, Opera and, recently, Safari64 are the only browsers that support the shadow DOM version 065. Firefox is still in development, although it has supported it behind an experiment66 since version 29. Microsoft is still considering it67 for Edge and has it as a high priority on its road map.

However, shadow DOM version 0 is the old specification. Shadow DOM version 168 is the new one, and only Chrome, Safari and Opera fully support it69. Not to mention that custom elements version 070 went through the same upgrade, and only Chrome fully supports custom elements version 171, whereas Safari technical preview supports it as of version 1772. Custom elements version 1 has some major changes in how web components are written, so be sure to fully understand what that entails73.

Lastly, the webcomponentjs polyfill only supports the version 0 implementation of the shadow DOM and custom elements. A version 1 branch of the polyfill74 will support version 1, but it’s not yet released.

(il, vf, yk, al)

Footnotes Link

  1. 1 https://developers.google.com/web/fundamentals/getting-started/primers/customelements?hl=en
  2. 2 http://engineering.lonelyplanet.com/2014/05/18/a-maintainable-styleguide.html
  3. 3 https://www.smashingmagazine.com/2007/07/css-specificity-things-you-should-know/
  4. 4 https://www.smashingmagazine.com/2017/01/styled-components-enforcing-best-practices-component-based-systems/
  5. 5 https://www.smashingmagazine.com/2010/12/using-the-less-css-preprocessor-for-smarter-style-sheets/
  6. 6 https://www.smashingmagazine.com/2015/02/deep-dive-into-adobe-edge-reflow/
  7. 7 http://webcomponents.org/articles/web-components-best-practices/
  8. 8 https://www.smashingmagazine.com/wp-content/uploads/2016/11/login-form-preview-opt.png
  9. 9 https://necolas.github.io/normalize.css/
  10. 10 http://hayato.io/2016/shadowdomv1/#shadow-piercing-combinators
  11. 11 http://meowni.ca/posts/styling-the-dome/
  12. 12 https://www.stevesouders.com/blog/2009/04/09/dont-use-import/
  13. 13 https://github.com/straker/webcomponent-perf/tree/master/shared-styles
  14. 14 https://www.webpagetest.org/result/161023_VK_9ZC/
  15. 15 https://www.webpagetest.org/result/161023_2X_9ZB/
  16. 16 http://webcomponents.org/polyfills/html-imports/#polyfill-notes
  17. 17 https://www.webpagetest.org/
  18. 18 https://www.smashingmagazine.com/wp-content/uploads/2016/11/native-web-components-perf-preview-opt.png
  19. 19 https://developers.google.com/web/fundamentals/getting-started/primers/customelements?hl=en
  20. 20 https://github.com/webcomponents/webcomponentsjs/tree/v1#browser-support
  21. 21 https://medium.com/dev-channel/the-case-for-custom-elements-part-1-65d807b4b439
  22. 22 https://stackoverflow.com/questions/40181683/failed-to-execute-createelement-on-document-the-result-must-not-have-childr
  23. 23 https://www.webpagetest.org/result/161025_CE_60T/
  24. 24 https://www.webpagetest.org/result/161023_5D_9ZA/
  25. 25 https://www.smashingmagazine.com/wp-content/uploads/2016/11/custom-elements-perf-preview-opt.png
  26. 26 https://developer.mozilla.org/en-US/docs/Web/Web_Components
  27. 27 https://medium.com/dev-channel/the-case-for-custom-elements-part-1-65d807b4b439#7d6c.tlzb4zis3
  28. 28 https://www.polymer-project.org/
  29. 29 https://github.com/skatejs/skatejs
  30. 30 https://x-tag.github.io/
  31. 31 https://www.polymer-project.org/1.0/docs/devguide/styling#style-modules
  32. 32 https://www.webpagetest.org/result/161101_AT_73B/
  33. 33 https://www.webpagetest.org/result/161101_CB_73C/
  34. 34 https://www.webpagetest.org/result/161101_XK_73A/
  35. 35 https://www.smashingmagazine.com/wp-content/uploads/2016/11/polymer-web-components-perf-preview-opt.png
  36. 36 https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_variables
  37. 37 https://www.youtube.com/watch?v=2an6-WVPuJU
  38. 38 http://csswizardry.com/2016/10/pragmatic-practical-progressive-theming-with-custom-properties/
  39. 39 http://caniuse.com/#search=custom%20properties
  40. 40 https://github.com/webcomponents/shadycss/issues/11
  41. 41 https://github.com/Polymer/polymer/tree/2.0-preview#polymer-20-goals
  42. 42 https://tabatkins.github.io/specs/css-apply-rule/
  43. 43 https://blog.hospodarets.com/css_apply_rule
  44. 44 https://www.chromestatus.com/feature/5753701012602880
  45. 45 https://w3c.github.io/webcomponents/spec/shadow/#inertness-of-html-elements-in-a-shadow-tree
  46. 46 https://github.com/w3c/webcomponents/issues/530
  47. 47 https://github.com/whatwg/html/pull/1572
  48. 48 https://www.w3.org/Bugs/Public/show_bug.cgi?id=22539
  49. 49 https://codereview.chromium.org/2177163002/
  50. 50 https://jsfiddle.net/straker/vj6vc7pn/
  51. 51 https://developer.apple.com/safari/technology-preview/release-notes/
  52. 52 https://github.com/w3c/webcomponents/issues/282#issuecomment-122186756
  53. 53 https://github.com/w3c/webcomponents/issues/530#issuecomment-231310687
  54. 54 http://tabatkins.github.io/specs/construct-stylesheets/
  55. 55 https://github.com/w3c/webcomponents/issues/501
  56. 56 https://lists.w3.org/Archives/Public/www-style/2016May/0218.html
  57. 57 https://github.com/tabatkins/specs/tree/gh-pages/construct-stylesheets
  58. 58 https://github.com/w3c/webcomponents/issues/82#issuecomment-197300382
  59. 59 https://github.com/w3c/webcomponents/issues/99#issuecomment-197685253
  60. 60 https://github.com/w3c/webcomponents/issues/530#issuecomment-231310687
  61. 61 https://github.com/Polymer/polymer/issues/2389
  62. 62 https://news.ycombinator.com/item?id=11654362
  63. 63 https://www.polymer-project.org/1.0/blog/shadydom#shadow-dom-is-awesome-why-is-there-a-shady-dom
  64. 64 https://developer.apple.com/library/prerelease/content/releasenotes/General/WhatsNewInSafari/Articles/Safari_10_0.html
  65. 65 http://caniuse.com/#feat=shadowdom
  66. 66 https://developer.mozilla.org/en-US/docs/Web/Web_Components#Enabling_Web_Components_in_Firefox
  67. 67 https://developer.microsoft.com/en-us/microsoft-edge/platform/status/shadowdom
  68. 68 http://hayato.io/2016/shadowdomv1/
  69. 69 http://caniuse.com/#feat=shadowdomv1
  70. 70 http://caniuse.com/#feat=custom-elements
  71. 71 http://caniuse.com/#feat=custom-elementsv1
  72. 72 https://webkit.org/blog/7071/release-notes-for-safari-technology-preview-17/
  73. 73 https://developers.google.com/web/fundamentals/getting-started/primers/customelements
  74. 74 https://github.com/webcomponents/webcomponentsjs/tree/v1

↑ Back to top Tweet itShare on Facebook

Steven Lambert is a lead web developer and accessibility advocate at FamilySearch.org. He has over 7 years of industry experience and specializes in design systems, performance, and accessibility. On the side, he is a hobbyist game developer and freelance web developer.

  1. 1

    > If all goes well, within a few months to a few years, we’ll be able to use shared styles using a few different approaches.

    > in a few years we should have some great solutions for sharing the styles between them.

    Cool, see you in a few years!!

    1
  2. 2

    I ended up using Riot JS, at least untill Web Components are mature enough. Usually standards take a few years to come, but seeing all the internal disagreement, change of specs and the like looks like this time it will take a few more years.

    Using Riot feels like how Web Components should really have worked and has a minimal footprint compared to current polyfills.

    I know that getting things right is difficult but it’s a bit of a shame how the Web Components Working Group is going through this.

    0
  3. 3

    On a side note: Things that make me cringe (no matter the context): Usage of querySelector for picking out an ID instead of using getElementById ..

    cu, w0lf.

    0
  4. 4

    I enjoy whatever you guys are typically up too. These kinds of clever work and reporting! Continue the wonderful works guys I’ve included you guys to blog roll.

    1
  5. 5

    Thank a lot for this post that was very interesting. It’s really helpful for all of us. Keep posting like those amazing posts, this is really awesome.

    1
  6. 6

    Great article! As someone who isn’t necessarily at the forefront of CSS technologies, this was both a nice overview and a nice confirmation that the path forward isn’t exactly clear-cut once you know how these things work. I have been struggling with using global styles inside of Angular 2 components. Angular has the /deep/ operator in their simulated style encapsulation. And, after using it, I started to feel guilty that I wasn’t using encapsulation the “right way.” But, after reading this article, I am wondering if Angular 2’s approach is kind of the best of both worlds — in that it allows for both style encapsulation and /deep/ for global styles (such as for all Input elements).

    2
  7. 7

    Thank you for this post, very good blog!

    0
  8. 8

    I am really happy with articles quality and presentation.Thanks a lot for keeping great stuff. I am very much thankful for this site.

    0

↑ Back to top