Friday, February 7, 2014

Application CSS in Polymers Redux


This is my favorite time when writing books: when all the stuff I worked on in the first month breaks. This seems inevitable both because my initial work is… well, my first take on a subject. But also, things inevitably break because I am usually working on new stuff under active development. Last night, I ran into the latter kind of breakage.

I have a couple of Polymers, the parent <pricing-plans> and the child (singular) <pricing-plan> element. I used them to write a small amount of custom HTML to generate a lot of Bootstrap structured <div> tags. The end result is that I can write a small amount of meaningful HTML:
<pricing-plans>
  <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-plans>
And get a Bootstrapped styled result:



The page has to include Bootstrap CSS, which the Polymer can then apply with applyAuthorStyles:
    Polymer('pricing-plans', {
      applyAuthorStyles: true
    });
The applyAuthorStyles setting means that the Polymer honors styles from the page in which it is included. Except it doesn't. Not anymore.

As Günter Zöchbauer was kind enough to point out, applyAuthorStyles is deprecated. In fact, it seems this deprecation is imminent in Chrome. When I was mucking about with the cat and hat shadow DOM CSS selectors last night, I had to enable the experimental chrome://flags setting for #enable-experimental-web-platform-features:



When I do that and reload the same page, I no longer see my nicely styled Bootstrap panels. I just see the vanilla styles of the raw HTML:



So, if CSS from the parent document can no longer be applied to Polymers, how do I get those styles in there? Put another way, if I install Bootstrap at the application level, how can it be applied inside the Polymer?

That turns out to be fairly easy (although it does require one weird trick!). I can include the application level Bootstrap via the usual <link> tag, but that <link> tag needs to go inside the Polymer's <template> tag:
<link rel="import" href="../bower_components/polymer/polymer.html">
<polymer-element name="pricing-plans">
  <template>
    <div id="price">
      <div class="container">
        <div class="col-md-12 col-sm-4">
          <content></content>
        </div>
      </div>
    </div>
    <link type="text/css" rel="stylesheet" href="../bower_components/bootstrap/dist/css/bootstrap.min.css">
  </template>
  <script>
    Polymer('pricing-plans');
  </script>
</polymer-element>
As I found last night, CSS that applies to the shadow DOM—the cat and hat CSS selectors—can go outside the <template> tag. The shadow DOM aware selectors can penetrate the shadow DOM to do their styling work. But plain old CSS like that in Bootstrap only applies when included inside the document fragment of the Polymer's shadow DOM.

With that, I have my Polymer properly styled again:



Even the cat and hat styles are applying there. So this would seem to be approximately the proper approach. Now to start rewriting a chapter or two in Patterns in Polymer


Day #1,020

2 comments:

  1. This deprecation is a huge step backward in web component.

    1 - The same style will be parsed and loaded in many, many components when you need and this is so common. Performance hit
    2 - We lost the ability to theme and use global styles. I try to use lightdom but it lost the ability to use

    ReplyDelete
    Replies
    1. This does bother me, but not nearly as much as that. Since this post, I wrote the apply-author-styles Polymer element (http://japhr.blogspot.com/2014/06/a-tag-named-apply-author-styles.html). More importantly, the Polymer team has introduced core-style (http://www.polymer-project.org/docs/elements/core-elements.html#core-style). Bottom line: there are ways to get around this--even if they are not quite as easy as the apply-author-styles property.

      Delete