Home Start Get started Build an element 1. Get set up 2. Add local DOM 3. Data binding & properties 4. React to input 5. Theming with custom properties Build an app 1. Get set up 2. Create a new page 3. Add some elements 4. Deploy Polymer Feature overview Quick tour Define elements Register an element Declare properties Instance methods Behaviors Local DOM & styling Local DOM Styling Events Handle and fire events Gesture events Data system Data system concepts Work with object and array data Observers and computed properties Data binding Helper elements Tools Tools overview Polymer CLI Document your elements Test your elements Optimize for production Publish an element Advanced tools Services What's new Release notes 1.0 Migration guide About Polymer 1.0 Resources Community Browser compatibility API Reference Polymer.Base array-selector custom-style dom-bind dom-if dom-repeat dom-template Polymer.Templatizer Global settings 2.0 Preview About Polymer 2.0 Upgrade guide App Toolbox What's in the box? Using the Toolbox App templates Responsive app layout Routing Localization App storage Service worker Serve your app Case study Shop News Elements News About Polymer 2.0 Upgrade guide

Polymer 2.0 is designed to support the new custom elements v1 and shadow DOM v1 specifications being implemented by most major browser vendors, while providing a smooth migration path for Polymer 1.x users.

Polymer 2.0 also makes improvements in several areas:

  • Improved interoperability. By removing the need to use Polymer.dom for DOM manipulation, Polymer 2.0 makes it easier to use Polymer components with other libraries and frameworks. In addition, the shady DOM code has been separated out into a reusable polyfill, instead of being integrated into Polymer.
  • Data system improvements. Polymer 2.0 includes targeted improvements to the data system. These changes make it easier to reason about and debug the propagation of data through and between elements. They also improve compatibility with top-down data flow approaches, like Flux.
  • More standard. Polymer 2.0 uses standard ES6 classes and the standard custom elements v1 methods for defining elements, instead of a Polymer factory method. You can mix in features using standard JavaScript (class expression mixins) instead of Polymer behaviors. (The Polymer factory method is still supported using a compatibility layer.)

Unreleased preview code. Currently, Polymer 2.0 is available as a branch of the Polymer library repo on GitHub. This is an active development branch, and should not be used in production. By all means, use the 2.0-preview branch to experiment, to provide feedback, and to familiarize yourself with the latest versions of the custom elements and shadow DOM specifications. Just don't build production code on it quite yet. Please.

Some tests currently fail on non-Chrome browsers; these will be addressed soon, but in the short term Chrome Canary is your best bet.

Polymer 2.0 introduces a number of breaking changes—many of which are required by new custom elements v1 and shadow DOM v1 specifications. Expect to see more changes as this new version nears release.

The following sections describes the major changes in Polymer 2.0. For details on upgrading elements to Polymer 2.0, see the upgrade guide.

Polymer 2.0 elements target the custom elements v1 API, which makes several changes to the v0 version of the spec used in Polymer 1.x. In particular:

  • The custom elements v1 spec defines elements using ES6 classes, instead of prototypes.

Polymer 2.0 lets you use this native ES6 form by providing an ES6 base class (Polymer.Element) for your elements to extend. In addition, legacy elements using the Polymer factory method are supported with a Polymer 1.x compatibility layer.

  • The new spec has some changes to the lifecycle callbacks. In particular, instead of a created callback it invokes the class constructor. The spec also imposes new restrictions on what can be done in the constructor (previously createdCallback).
  • In addition, although they are supported in the specification, Polymer 2.0 does not currently support type-extension elements (is=).

The following sections describe these changes in more detail.

For general information on the custom elements v1 specification, see Custom elements v1: reusable web components on Web Fundamentals.

When creating class-based elements, use the new native lifecycle methods (called "custom element reactions"). When creating legacy elements using the Polymer factory method, use the legacy Polymer callback names.

Reaction/callback name Notes
constructor (native)

created (legacy)

The custom elements v1 spec forbids reading attributes, children, or parent information from the DOM API in the constructor (created callback in the legacy API). Likewise, attributes and children may not be added in the constructor. Any such work must be deferred (for example, until connectedCallback).

The legacy created callback is no longer called before default values in properties have been set. As such, you should not rely on properties set in created from within value functions that define property defaults.

However, you can now set any property defaults within the created callback (in 1.0 this was forbidden for observed properties) in lieu of using the value function in properties.

connectedCallback (native)

attached (legacy)

Polymer 1.x deferred the attached callback until after first render, so elements could measure themselves or their children.
disconnectedCallback (native)

detached (legacy)

attributeChangedCallback (native)

attributeChanged (legacy)

Attributes must be explicitly registered to be observed.

For Polymer elements, only properties explicitly declared in the properties object are tracked for attribute changes. (That is, changing the attribute value invokes the attribute changed callback, and causes Polymer to set the property value from the attribute.)

In custom elements v0, the attributeChangedCallback was generated for any attribute change.

In Polymer 1.x, attributes were deserialized for both explicitly declared properties and implicitly declared properties. For example, a property used in a binding or as the dependency of an observer, but not declared in properties can be considered implicitly declared.

ready (Polymer specific) Polymer no longer guarantees that the initial light DOM distribution is complete before ready is called.

In addition to changes in the callbacks, note that the lazyRegister option has been removed and all meta-programming (parsing the template, creating accessors on the prototype, and so on) is deferred until the first instance of the element is created.

Polymer 2.0 doesn't support type-extension elements (for example, <input is="iron-input">). Type-extension support is still included in the custom elements v1 spec (as "customized build-in elements"), and scheduled for implementation in Chrome. However, since Apple has said it will not implement is, we will not be encouraging its use to avoid indefinite reliance on the custom elements polyfill. Instead, a wrapper custom element can surround a native element. For example:

<a is="my-anchor">...</a>

Could become:


Users will need to change existing type-extension elements where necessary.

All template type extensions provided by Polymer have now been changed to standard custom elements that take a <template> in their light DOM. For example:

<template is="dom-repeat" items="{{items}}">...</template>


<dom-repeat items="{{items}}">

For the time being, Polymer automatically wraps template extensions used in Polymer element templates during template processing for backward-compatibility, although we may decide to remove this auto-wrapping in the future. Templates used in the main document must be manually wrapped.

The custom-style element has also been changed to a standard custom element that must wrap a <style> element. For example:

<style is="custom-style">...</style>




Polymer 2.0 supports shadow DOM v1. For Polymer users, the main differences in v1 involve replacing <content> elements with v1 <slot> element.

The shady DOM shim that was part of Polymer 1.x has been factored out of Polymer and added to the webcomponents-lite.js polyfill bundle, along with the related shim for CSS Custom Properties. This new version of shady DOM no longer exposes an alternative (Polymer.dom) API but instead patches the native DOM API, so 2.0 users can use the native DOM APIS directly.

For hybrid elements, Polymer 2.0 includes a version the Polymer.dom API that forwards directly to the native API. For 2.0-only elements, Polymer.dom can be eliminated in favor of the native DOM APIs.

Read more on Web Fundamentals. For an overview of shadow DOM, see Shadow DOM v1: self-contained web components on Web Fundamentals.

For a brief but comprehensive set of examples illustrating the shadow DOM v1 spec changes, see What's New in Shadow DOM v1 (by examples) by Hayato Ito.

Polymer 2.0 introduces a number of improvements in the data system:

  • No more dirty checking for objects or arrays. Unlike 1.x, when you make a notifying change to an object or array property, Polymer re-evaluates everything below that property (sub-properties, array items).
  • Simpler array handling. Eliminates the Polymer.Collection abstraction and key-based paths for array items.
  • Batched data changes, which can improve performance as well as correctness.
  • Undefined dependency checks for observers, computed bindings and computed properties have been removed. These are all called once at initialization time.
  • Only properties listed explicitly in properties can be configured from an attribute.
  • Element initialization (including template stamping and data system initialization) is deferred until the the element is connected to the main document. (This is a result of the custom element v1 changes.)
  • Several miscellaneous smaller changes.

The following sections describe these changes in more detail.

Polymer 1.x uses a dirty-checking mechanism to prevent the data system from doing extra work. For example, in 1.x the following code doesn't generate any property effects:

this.property.subproperty = 'new value!';

Because property still points to the same object, the dirty check fails, and sub-property changes don't get propagated. In 2.0, this dirty check is eliminated, so the code above would work as intended. This also lets you batch several changes before invoking property effects:

this.property.arrayProperty.push({ name: 'Alice' });

this.property.stringProperty = 'new value!';

You can also use set or simply set a top-level property to invoke effects:

this.set('property', this.property);
// or
this.property = this.property;

Using set to change a specific subproperty can often be the most efficient way to make changes. However, with this change users of Polymer elements shouldn't need to use this API, making it more compatible with alternate data-binding and state management libraries.

Note that when you re-set a property at the top-level, all property effects for that property and its subproperties, array items, and so-on are re-run. Observers with wildcard paths (like prop.*) are only notified with the top-level change:

// 'property.*' observers fire with the path 'property'
this.property.deep.path = 'another new value';

Using set to set specific paths generates granular notifications:

// 'property.*' observers fire with the path 'property.deep.path'
this.set('property.deep.path', 'new value');

The Polymer.Collection API and its associated key-based path and splice notification for arrays has been eliminated. The Polymer array mutation APIs are still supported, but are no longer required. Because dirty checking is eliminated, you can simply re-set an array to trigger an update.

this.array.push('one', 'two', 'three');

There are several other benefits to this change:

  • Arrays of primitive values are supported.
  • Array items don't need to be unique.
  • Simple observers on an array property are notified when the array is mutated observably. (Before, they were notified only when the array itself changed.)

Array splice notifications are only generated if you use the Polymer array mutation APIs. No splice notifications are generated when you set the top-level property.

// fires observers for the paths 'array' and 'array.length'
this.array.push('one', 'two', 'three');

// fires observers for 'array.splice', 'array', and 'array.length'
this.push('array', 'one', 'two', 'three');

Since key paths have been eliminated, array splice notifications only include the indexSplices property, not keySplices.

Propagation of data through the binding system is now batched, such that complex observers and computing functions run once with a set of coherent changes. There's two ways to create a set of coherent changes:

  • An element automatically creates a set of coherent changes when it initializes its properties.
  • You can programmatically create a set of coherent changes using the new setProperties method.
this.setProperties({ item: 'Orange', count: 12 });

Single property accessors still propagate data synchronously. For example, given an observer that observes two properties, a and b:

// observer fires twice
this.a = 10;
this.b = 20;

// observer fires once
this.setProperties({a: 10, b: 20});

In 2.0, the checks preventing observers from firing with undefined dependencies are removed.


  • Multi-property observers and computed properties run once at initialization if any dependencies are defined.
  • Computed bindings run once unconditionally at initialization, regardless of whether any dependencies are defined.

In both cases, observer or computing functions may now receive undefined as an argument value, and need to handle it correctly.

  • Setting/changing any function used in a computed binding causes the binding to re-compute its value using the new function and current property values. For example, given the binding:

some-property="{{_computeValue(a, b)}}"

Changing the _computeValue function causes the binding to be re-evaluated, even if a and b remain the same:

  this._computeValue = function(a, b) { ... }
  • Property change notifications (property-changed events) aren't fired when the value changes as a result of a binding from the host.
  • In order for a property to be deserialized from its attribute, it must be declared in the properties metadata object. In Polymer 1.x, deserialization is also done for properties that are implicitly declared (for example, by being included in a binding or as an observer dependency).

Polymer 2.0 retains the existing polymer/polymer.html import that current Polymer 1.0 users can continue to import. This import includes the legacy Polymer function for defining elements, and strives to provide a very minimally-breaking change for code written to the Polymer 1.0 API.

For the most part, existing users upgrading to Polymer 2.0 will only need to adapt existing code to be compliant with the shadow DOM v1 API related to content distribution and styling, as well as minor breaking changes introduced due to changes in the custom elements v1 API.

In keeping with a goal of reducing unnecessary code, the new ES6 base element, Polymer.Element, leaves out a number of methods and properties. The removed APIs fall into several categories:

  • Simple sugaring for native DOM APIs. For example fire and transform.
  • Rarely-used attributes and properties, like attributeFollows and classFollows.
  • Methods and properties that don't belong on the instance. For example, in 1.x importHref was an instance method, but it doesn't do anything instance-specific, except for binding the callback.

A comprehensive list of missing or moved APIs will be available after the API for Polymer.Element is finalized.

If you want to create a class-based element but depend on some of the removed APIs, you can extend the Polymer.LegacyElement class instead of Polymer.Element.

class MyLegacyElement extends Polymer.LegacyElement { ... }
  • <array-selector> is not yet implemented.
  • Most of Polymer.dom is emulated, but some APIs may be missing. Please file issues to determine if the missing behavior is an intended breaking change.

When released, Polymer 2.0 should support the same set of browsers as Polymer 1.x—IE 11, Edge, Safari (9+), Chrome, Opera and Firefox.

Polymer 2.0 has been developed alongside and tested with a new suite of v1-spec compatible polyfills for custom elements and shadow DOM. You can test Polymer 2.0 by loading the v1 branch of webcomponents-lite.js, which is included as a bower dependency to Polymer 2.x and loads all necessary polyfills.

Since these polyfills standards are under active development, we recommend testing Polymer 2.0 in Chome 54 or later (Beta or Canary) for best results.


Polymer 2.0 and 2.0 class-style elements are written in ES6, and can be run without transpilation in current Chrome, Safari 10, Safari Technology Preview, Firefox, and Edge. Transpilation is required to run in IE11 and Safari 9. We will be releasing tooling for development and production time to support this need in the future.

The team is in the process of updating the Polymer elements to use the new "hybrid" format compatible with both Polymer 1.7 and 2.0. Many elements repos have 2.0-preview branches in varying degrees of stability. Use at your own risk.

Legacy elements (and hybrid elements) use Polymer 1.x style behaviors. Class-style elements use class-expression mixins instead of Polymer 1.x behaviors.

If you depend on any behaviors supplied by the Polymer team, note that these behaviors are currently only usable with legacy and hybrid elements. If you have dependencies on any of the Polymer behaviors, you should keep using the legacy (or hybrid) element format for now.

You can install the Polymer 2.0-preview branch using bower:

bower install --save Polymer/polymer#2.0-preview

You can also use bower to install any of the available hybrid elements:

bower install --save PolymerElements/paper-button#2.0-preview

Note that all of the 2.0-preview branches are active development branches and may break at any time.

When upgrading an existing project you may want to read through the rest of this doc and the upgrade guide before starting.

If your project uses Polymer elements or behaviors, see Polymer element availability.

  1. Create a copy of your project or create a new branch to work in.

  2. Find any Polymer packages in bower.json and replace the existing version with 2.0-preview branch:

    "polymer": "Polymer/polymer#2.0-preview"

  3. Run bower install.

    bower install

  4. See the upgrade guide for information on getting your code working with 2.0.