2014年7月23日水曜日

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

リンクテキストの右側にアイコンを付けるだけのコンポーネントがあるとします。
  1. <link rel="import" href="../core-icon/core-icon.html">  
  2.   
  3. <polymer-element name="icon-link" attributes="href">  
  4.   <template>  
  5.     <style>  
  6.     a {  
  7.       color: #0277bd;  
  8.       text-decoration: none;  
  9.     }  
  10.     </style>  
  11.   
  12.     <p>  
  13.       <a href="{{href}}" target="new">  
  14.         <content></content>  
  15.         <core-icon icon="launch"></core-icon>  
  16.       </a>  
  17.     </p>  
  18.   
  19.   </template>  
  20.   <script>  
  21.     Polymer({  
  22.     });  
  23.   </script>  
  24. </polymer-element>  
これを、こんな感じで使うと
  1. <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 でも文字部分がリンクになります。
  1. <link rel="import" href="../core-icon/core-icon.html">  
  2.   
  3. <polymer-element name="icon-link" attributes="href label">  
  4.   <template>  
  5.     <style>  
  6.     a {  
  7.       color: #0277bd;  
  8.       text-decoration: none;  
  9.     }  
  10.     </style>  
  11.   
  12.     <p>  
  13.       <a href="{{href}}" target="new">  
  14.         {{label}}  
  15.         <core-icon icon="launch"></core-icon>  
  16.       </a>  
  17.     </p>  
  18.   
  19.   </template>  
  20.   <script>  
  21.     Polymer({  
  22.     });  
  23.   </script>  
  24. </polymer-element>  
  1. <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 でもリンクとして動作する。
  1. <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 だと直ってましたね。
    見当違いのコメント申し訳ないです。

    返信削除