カスタム要素を定義するには、Polymer.Elementの拡張クラスを作成し、そのクラスをcustomElements.defineメソッドに渡します。作成したクラスにはisという、カスタム要素のHTMLタグ名を返す静的なgetterメソッドが必要です。
仕様では、カスタム要素名は、小文字のASCII文字で始まり、ダッシュ(-)を含まなければなりません。
例:
// define the element's class element
class MyElement extends Polymer.Element {
  static get is() { return 'my-element'; }
  // Element class can define custom element reactions
  connectedCallback() {
    super.connectedCallback();
    console.log('my-element created!');
  }
  ready() {
    super.ready();
    this.textContent = 'I\'m a custom element!';
  }
}
// Associate the new class with an element name
window.customElements.define(MyElement.is, MyElement);
// create an instance with createElement:
var el1 = document.createElement('my-element');
// ... or with the constructor:
var el2 = new MyElement();
上記の通り、カスタム要素のライフサイクルで説明したように要素のクラスにはカスタム要素のリアクションとしてコールバックを定義することができる。
既存の要素を拡張
ES6ではネイティブに提供されるサブクラス化の仕組みを活用することで、ES6の構文を使って定義済みの既存の要素を拡張したりカスタマイズしたりすることができます。
// Subclass existing element
class MyElementSubclass extends MyElement {
  static get is() { return 'my-element-subclass'; }
  static get properties() { ... }
  constructor() {
    super();
    ...
  }
  ...
}
// Register custom element definition using standard platform API
customElements.define(MyElementSubclass.is, MyElementSubclass);
サブクラスにテンプレートを指定しない場合、デフォルトでスーパークラスのテンプレートが継承されます。この動作をオーバーライドしたり、スーパークラスのテンプレートを変更したりするには、サブクラスのtemplateのgetterメソッドをオーバーライドします。
インポートとAPI
Polymer要素を定義するのに三つの主要なHTMLインポートがあります。:
| インポート | 説明 | 
|---|---|
| polymer-element.html | Polymer.Elementクラスをベースに要素を定義します。 | 
| legacy-element.html | Polymer.Elementを拡張し、Poymer 1.xと互換性のあるPolymer.LegacyElementAPIが付加されたPolymer.LegacyElementクラスをベースに要素を定義します。また、レガシーなファクトリメソッドPolymer()を利用して、1.xと2.xのハイブリッド要素を定義することもできます(polymer-element.htmlを含んでいます)。 | 
| polymer.html | Polymerの基底クラスに、1.xでpolymer.htmlのバンドルに含まれていたヘルパー要素( custom-style、dom-bind、dom-if、dom-repeatなど)を加えてインクルードします(legacy-element.htmlを含んでいます)。 | 
リソースを最小限にしたい場合には、polymer-element.htmlをインポートし、必要なヘルパー要素を個別にインポートして下さい。
1.xの後方互換APIが必要な場合には、2.xのクラススタイルの要素を作成する際の基底クラスとしてPolymer.LegacyElementを使用できます。また利用するヘルパー要素は個別にインポートする必要があります。
1.xと2.xの両方で実行できるハイブリッド要素を定義するには、polymer.htmlをインポートして使用します。
クラススタイルの要素でハイブリッドな動作を使用
Polymer.mixinBehavior関数を使用して、クラススタイルの要素にハイブリッドな動作(behavior)を追加することができます。:
class XClass extends Polymer.mixinBehaviors([MyBehavior, MyBehavior2], Polymer.Element) {
  static get is() { return 'x-class'}
  ...
}
customElements.define(XClass.is, XClass);
このmixinBehavior関数は、1.xのレガシーAPIもミックスインするので、Polymer.LegacyElementを拡張したのとほとんど同じことです。これらのレガシーAPIが必要とされるのは、ハイブリッドな動作がそれらに依存しているためです。
メインのHTMLドキュメントで要素を定義する
試験的な実装においては、メインドキュメントから要素を定義するだけで済むかもしれません。本番環境では、常に要素は分割したファイルに定義した上で、メインドキュメントにインポートする必要があります。
メインのHTMLドキュメントで要素を定義するには、要素はHTMLImports.whenReady(callback)で定義します。callbackはドキュメント内の全てのインポートの読み込み(loading)が完了した時点で呼び出されます。
<!DOCTYPE html>
<html>
  <head>
    <script src="bower_components/webcomponentsjs/webcomponents-lite.js">
    </script>
    <link rel="import" href="bower_components/polymer/polymer-element.html">
    <title>Defining a Polymer Element from the Main Document</title>
  </head>
  <body>
    <dom-module id="main-document-element">
      <template>
        <p>
          Hi! I'm a Polymer element that was defined in the
          main document!
        </p>
      </template>
      <script>
        HTMLImports.whenReady(function() {
          class MainDocumentElement extends Polymer.Element {
            static get is() { return 'main-document-element'; }
          }
          window.customElements.define(MainDocumentElement.is, MainDocumentElement);
        });
      </script>
    </dom-module>
    <main-document-element></main-document-element>
  </body>
</html>
レガシー要素を定義する
レガシーな要素は、要素の登録にPolymer関数が使用できます。関数は新しい要素のプロトタイプを引数に取ります。プロトタイプには、カスタム要素のHTMLタグ名を指定するisプロパティが必要です。
仕様では、カスタム要素の名前はASCII文字で始まり、ダッシュ(-)を含む必要があります。
例:
    // register an element
    MyElement = Polymer({
      is: 'my-element',
      // See below for lifecycle callbacks
      created: function() {
        this.textContent = 'My element!';
      }
    });
    // create an instance with createElement:
    var el1 = document.createElement('my-element');
    // ... or with the constructor:
    var el2 = new MyElement();
Polymer関数は、要素をブラウザに登録し、コードから要素の新たな要素のインスタンスを生成するコンストラクタを返します。
Polymer関数はカスタム要素のプロトタイプチェーンを構築し、それをPolymerのBaseプロトタイプ(Polymerの付加的な機能を提供)につなぎます。そのため開発者が独自のプロトタイプチェーンを構築することはできません。しかし、behaviorsプロパティを使用することで要素間でコードを共有することはできます。
ライフサイクルコールバック
Polymer.Elementクラスは、Polymerのビルトイン機能で必須のタスクを実行するため、標準のカスタム要素のライフサイクルコールバックを実装しています。
Polymerは、要素のDOMの生成と初期化が完了した時点で呼び出されれるreadyという特別なコールバックも用意しています。
| レガシーコールバック | 説明 | 
|---|---|
| created | 要素の作成後、プロパティ値の設定やローカルDOMの初期化前に呼び出されます。 プロパティ値が設定される前のワンタイム設定に利用されます。 ネイティブの constructorに相当します。 | 
| ready | プロパティ値が設定され、ローカルDOMが初期化された後に呼び出されます。 ローカルDOMの初期化後に、コンポーネントのワンタイムな設定を行うのに利用されます。(プロパティ値を元に設定する場合は、オブザーバーの使用を推奨します)。 | 
| attached | 要素がドキュメントに追加(attached)された後に呼び出されます。要素の存続期間中であれば複数回呼び出すことができます。初回の attachedコールバックはreadyコールバックが実行されるまで呼び出されないことが保証されています。ドキュメントレベル(document-level)のイベントリスナーを追加sるのにも利用されます。(ローカルな要素に対してイベントリスナーを設定するには、アノテーション付イベントリスナーやリスナーオブジェクトのような宣言的なイベント処理を利用でき、Polymerはリスナーを自動的に追加します)。 ネイティブの connectedCallbackに相当します。 | 
| detached | 要素がドキュメントから切り離された(detached)された後に呼び出されます。要素の存続期間中であれば複数回呼び出すことができます。 attachedコールバックで追加されたイベントリスナーの削除にも利用されます。ネイティブの disconnectedCallbackに相当します。 | 
| attributeChanged | 要素の属性の一つが変更されたときに呼び出されます。 対応するプロパティが宣言されていない属性の変更を扱う場合に利用できます。(対応するプロパティが宣言されている場合は、属性デシリアライゼーションで説明しているように、Polymerが自動的に属性の変更を処理します)。 ネイティブの attributeChangedCallback相当します。 | 
レガシーなbehavior
レガシーな要素においてはbehaviorsフォームを利用することで要素間でコードを共有することができます。
behaviorにはプロパティ、ライフサイクルコールバック、イベントリスナーやその他の機能を定義することができます。
より詳細なガイドは、Polymer 1.xのドキュメントのBehaviorsのセクションを参照してください。