Monday, April 18, 2016

Polymer and the [hidden] attribute

The hidden attribute is a "fairly new" convenience attribute (fairly new = not implemented in IE<=10) to hide page elements that are not relevant in the current context/state of the website.

It is especially useful in a Polymer web app, since you can use attribute binding to show/hide elements based on (computed) properties, without having to make your own display: none; styles.

There are several cases where you will have to be careful with this attribute though.

Sample usage


One of the most common scenarios where I personally use the hidden attribute, is to show/hide different elements, while waiting for data to arrive from the backend, i.e. to display a "Loading, please wait..." spinner before there is actual data to be displayed.
I mostly use a computed binding instead of a separate loading property, which would need to be set explicitly.

...but...


This works fine until you want to add some flex layout to those divs. Setting display to flex (or anything else really) in your CSS will most likely override the hidden style, since the default implementation of [hidden] { display: none; } has a very low CSS specificity, and if you want it to work you will have to add your own more specific code.

<paper-card hidden$="[[someProperty]]">...<paper-card> might sound tempting as well, but would fail because of the paper-card's custom CSS:
So you would have to handle hidden paper-cards with your own CSS again:
Some (but not many) custom elements actually define their own :host([hidden]) style, e.g. paper-item, which is probably the cleanest way to make sure this functionality works as intended, but would require checking all elements and creating appropriate PRs.

iron-flex-layout to the "rescue"


Now, you might not actually have noticed this problem, since with Polymer it is very likely that you are using iron-flex-layout, if not directly then indirectly via one of the many elements that import it. iron-flex-layout comes with this piece of code:
While this might seem harmless at first, it actually causes the hidden style to be enforced across all boundaries in all browsers while in Shady DOM (because it is not defined as a custom-style).
As soon as you switch to Shadow DOM though, it will have much less effect because it won't effect hidden attributes inside of custom elements.
This issue is currently being investigated and hopefully fixed soon.

Summing up...


There are two points you should take away from this post:
  1. Don't blindly rely on the hidden attribute. It might not actually do what you think it should do.
  2. Test your pages in Shady DOM and Shadow DOM from the beginning to prevent ugly surprises later on.

Final words