2014年7月23日水曜日

Polymer <a> 内の <content> は Chrome ではリンクにならない

リンクテキストの右側にアイコンを付けるだけのコンポーネントがあるとします。 <link rel="import" href="../core-icon/core-icon.html"> <polymer-element name="icon-link" attributes="href"> <template> <style> a { color: #0277bd; text-decoration: none; } </style> <p> <a href="{{href}}" target="new"> <content></content> <core-icon icon="launch"></core-icon> </a> </p> </template> <script> Polymer({ }); </script> </polymer-element> これを、こんな感じで使うと <icon-link href="http://y-anz-m.blogspot.com">Y.A.Mの雑記帳</icon-link> Chrome(Version 36.0.1985.125)では <content></content> に挿入される文字がリンクになりません。




一方、Firefox(31.0)ではリンクになります。





次のように <content> ではなく、attributes を使うと Chrome でも文字部分がリンクになります。 <link rel="import" href="../core-icon/core-icon.html"> <polymer-element name="icon-link" attributes="href label"> <template> <style> a { color: #0277bd; text-decoration: none; } </style> <p> <a href="{{href}}" target="new"> {{label}} <core-icon icon="launch"></core-icon> </a> </p> </template> <script> Polymer({ }); </script> </polymer-element> <icon-link href="http://y-anz-m.blogspot.com" label="Y.A.Mの雑記帳"></icon-link>


Web Components に詳しくないので、よくわからないのですが Chrome の挙動は仕様通りなのかしら?


追記:実際に見れるリンクないの?と言われたのでつくりました。http://www.yanzm.net/sample1.html

追記2:Chrome 38(Chrome Canary)だと直っているそうだ。

追記3:以下のように<span>で囲むと Chrome 36 でもリンクとして動作する。 <icon-link href="http://y-anz-m.blogspot.com"><span>Y.A.Mの雑記帳</span></icon-link> しかし、マウスカーソルの形はホバーしても変わらない。。。たぶん、https://code.google.com/p/chromium/issues/detail?id=314488 の問題。


2 件のコメント:

  1. 仕様は確認し切れていませんが、Chrome のほうが正しい動作という気がします。
    以下、推測混じりになってしまいますが...

    <icon-link> の子ノードは、 ShadowDOM の外に配置されているノードです。
    <content> 要素を用いても、外にあるノードだという事実は変化しません。

    ShadowDOM 内部のスタイルやリンク等は ShadowDOM 境界を越えて出て行かないので、<icon-link> の子ノードには適用されないと考えられます。
    (<content>要素でひっぱってきた子ノードに ShadowDOM の中からスタイルを適用するには、 ::content 疑似要素を使います。リンクには ::content 疑似要素に相当するものが無いと思います)

    他方で label 属性にした場合ですが、 DataBinding を用いて文字列を直接 ShadowDOM の中に埋め込んでいるので、リンクが適用されます。

    Firefox で <content> 要素と子ノードの組み合わせがリンクになるのは、 Polyfill では ShadowDOM 境界を技術的に再現できないためだと考えられます。


    この例の場合、解決方法は3種類ありそうです。
    1. 子ノードを使わず、文字列を属性で指定する。
    2. <a> 要素を拡張した <a is="icon-link"> というカスタム要素を定義する。
    3. カスタム要素内で MutationObserver を利用して自身の子ノードを監視し、 ShadowDOM 内に転写する。

    返信削除
  2. Chrome Canary だと直ってましたね。
    見当違いのコメント申し訳ないです。

    返信削除