The more I investigate styling and theming Polymer elements, the less a grasp I feel like I have on it. The core-style continues to vex. Beyond that, I am also having difficulty applying consistent CSS styles on my elements.
I am unsure if my current problems are with Polymer or with the Core Elements and Paper Elements built on top of Polymer. The most recent issue that I find is that the
<paper-button>
inside of a sample Polymer element that I am trying to create do not share styles. Specifically, the border is not included on all paper-buttons:Both the top buttons and the dialog buttons are
<paper-button>
elements. Both should be covered by my core-style CSS:<polymer-element name="lorem-dialog"> <template> <paper-button label="Bottom" on-tap="{{toggleDialog}}"></paper-button> <paper-button label="Center" on-tap="{{toggleDialog}}"></paper-button> <paper-dialog heading="Bottom Dialog" transition="paper-dialog-transition-bottom"> <!-- ... --> <paper-button label="Accept" affirmative autofocus></paper-button> </paper-dialog>< <!-- ... --> <core-style id="theme"> :host /deep/ paper-button { color: {{g.primaryColor}}; border: 5px solid {{g.secondaryColor}}; padding: 2px 5px; } </core-style> <core-style ref="theme"></core-style> </template> <script> Polymer('lorem-dialog', {/* ... */}); </script> </polymer-element>The core-style CSS is applied with the
/deep/
CSS modifier. My understanding of /deep/
is that my styles should penetrate any shadow DOMs that are under the current element. And it kinda/sorta does what I expect. The primary color, themed from the containing page, is set to orange and it does apply to all paper-button elements. But darn it, why are the borders not in place for the paper-buttons in the dialogs?My first thought is that perhaps this is a native shadow DOM vs. polyfill issue, so I load the demo page up in Firefox. This only makes things worse:
The borders are applied to all paper-buttons, but none of the core-style global settings are in place. Bleh.
Taking a step back, I know from last night that core-style does not like the way that I am using it. I take that out of the equation by removing the id/ref core-style pair of tags, replacing them with a straight forward
<style>
tag:<polymer-element name="lorem-dialog"> <template> <!-- ... --> <style> :host /deep/ paper-button { color: orange; border: 5px solid green; padding: 2px 5px; } </style> </template> <script> Polymer('lorem-dialog', {/* ... */}); </script> </polymer-element>That solve my Firefox problem. The polyfills now correctly style my paper-button elements:
But this remains unchanged in Chrome (stable through unstable). On the surface, it would seem that Polymer styles are just broken at this point, but I refuse to indulge in select-is-broken thoughts. At least not yet.
If I peek at one of the paper-button elements in the Chrome inspector, I find that my border style is being overridden:
But what is that double-colon content thingy? I have no idea how that applies to my paper-button elements, let alone is more specific (in a CSS selector sense) than my
/deep/
paper-button selector. Furthermore, I am hindered by the odd lack of file and line number for this selector. How can I understand and work around the darn thing if I cannot even find it?To the ack machine Robin!
Amazingly, that actually finds something:
$ ack -l ::content bower_components/platform/platform.js bower_components/platform/platform.js.map bower_components/paper-dialog/paper-dialog.css bower_components/core-style/elements.html bower_components/core-component-page/core-component-page.htmlOnly one of those is a CSS file and just so happens to be the element (paper-dialog) that is wrapping my misbehaving paper-buttons. Taking a look at the offending CSS, I find:
polymer-next-selector { content: ':host > *'; } ::content > * { font: inherit; border: 0; }That is exactly the definition of the culprit that I found in the DOM inspector. A quick review of the other matching files reveals that none of them have the same style definition. So the question becomes… what the heck is a
polymer-next-selector
? More importantly, how do I override it?The answer to the first question seems to be that polymer-next-selector is also known as polyfill-next-selector. It seems to be a way to apply styles in the polyfills, but which work natively with the shadow DOM if present. Only, the precedence on these things is crazy high.
Try as I might, I cannot target the distributed nodes of the paper-dialog from my custom element that tries to use paper-dialog. I am surprised that targeting the distributed nodes of paper-dialog has no effect:
<polymer-element name="lorem-dialog"> <template> <!-- ... --> <style> :host /deep/ paper-button { color: orange; border: 5px solid green; padding: 2px 5px; } paper-dialog::content > * { border: 5px dashed blue; } </style> </template> <script> Polymer('lorem-dialog', {/* ... */}); </script> </polymer-element>In the end, I give up trying to work with ::content and simply add an
!important
to the border style:<polymer-element name="lorem-dialog"> <template> <!-- ... --> <style> :host /deep/ paper-button { color: orange; border: 5px solid green !important; padding: 2px 5px; } </style> </template> <script> Polymer('lorem-dialog', {/* ... */}); </script> </polymer-element>That does the trick:
But it feels like a cheat.
I cannot figure out why the ::content distributed node selector has such high precedence or why my attempts to influence it failed. I am probably overlooking some selector combinator that would allow me to target paper-button distributed into paper-dialog, but I wish it were easier to find that combinator. And if there is no easier way to do this, then why is paper-dialog using such a high precedence selector to ensure that none of its nodes have borders?
I have a solution, but I have more questions than answers to go along with that solution. Which makes this feel like a cheat.
Day #163
No comments:
Post a Comment