Monday, February 10, 2014

Applying External CSS to Distributed Content with Polymer


While working on the theming chapter in Patterns in Polymer, I realized that I really have no good solution that covers styling the shadow DOM and elements projected into a Polymer's <content>. John Messerly was kind enough to point me to the upcoming Shadow DOM Styling working specification. That looks perfect expect that it does not work anywhere currently. So what to do?

I still have the experimental chrome://flags setting for #enable-experimental-web-platform-features turned on in Chrome:



With that, I can set styles with the "cat and hat" selectors from page level CSS or anywhere else:
pricing-plans ^^ .panel-default > .panel-heading {
  border: 5px green dashed;
}

pricing-plans ^^ strong {
  color: orange;
}
Here, I use the “cat” selector to target panel-heading and strong elements anywhere in my <pricing-plans> Polymer. The hat selector targets not only the shadow DOM of the <pricing-plans>, but also and child element's shadow DOM as well. In fact, it seems to reach down into the projected content as well since the <strong elements that are projected into the Polymer:
    <pricing-plans css="css/mine.css">
      <pricing-plan name="Multi-Language">
        <ul>
          <li>Get the <strong>JavaScript</strong> version!</li>
          <li>Get the <strong>Dart</strong> version!</li>
          <li>Private <strong>GitHub repository</strong> access to see how
            it's done.</li>
        </ul>
      </pricing-plan>
      <pricing-plan name="I Only Like One"><!-- ... --></pricing-plan>
      <pricing-plan name="Extras" type="primary"><!-- ... --></pricing-plan>
    </pricing-plans>
Winds up with the “cat” orange style:



That is of little use to me in the book however. It is not clear that either of these selectors will see the light of web standards day. Even if they do, it will be some time before they are supported by Chrome, let alone other browsers. So the question still remains, is there a simple way to get a single custom theme stylesheet applied to a Polymer's shadow DOM, any child's shadow DOM, and any projected content?

The answer to that seems to be to include that CSS file inside the top-level <pricing-plans> element definition:
<polymer-element name="pricing-plans">
  <template>
    <!-- ... -->
    <link type="text/css" rel="stylesheet" href="/css/page.css">
  </template>
  <script><!-- ... --></script>
</polymer-element>
With that, I have the styles applying correctly in Firefox and Chrome.

That said, these styles are ignored completely in Internet Explorer and Chrome Canary with the “Web Platform” experimental flag enabled. I am not too fussed by the experimental flag in Chrome Canary. I can make things more or less work with the cat and hat selectors (without breaking Firefox or stable Chrome). In the book I could recommend that as a future-proofing strategy (though the standard proposal seems a better option). As for Internet Explorer, it refuses to acknowledge the stylesheet regardless unless it is included from the main page.


Day #1,023

No comments:

Post a Comment