血統の森+はてな

旧はてなダイアリーの自動インポートによるアーカイブです。

Re2: リンクのすぐそばにアイコンをつけるCSS

3か月遅れのレスポンス。

もともとのネタとしては、リンクのすぐそばにつける(たとえばPDFがPDFであるとわかるような)アイコンとして、

/* before */
a[href$=".pdf"] {
  background: url(image/pdf.gif) no-repeat 100% 50%; /* 背景を一度だけリンクの後ろ側に持ってくる */
  padding: 4px 20px 4px 0; /* 余白を上下と左に取る */
}

/* after - 疑似要素で書いてみる */
a[href$=".pdf"]:after {
  content: url(image/pdf.gif); 
  padding: 4px 20px 4px 0;
}

の方がすっきりするよね、というお話。

プロパティの選択については同意見ですが、私は以下のように考えています。

  • 拡張子で判定するのは望ましくない
  • CSSで表現するよりも、サーバーサイドや JavaScript でimg要素を挿入した方がより良い

拡張子の件については、PDFの拡張子が .pdf とは限らないからです。.xls に対する .xlsx のように新しい拡張子が将来出現しないとも限りませんし、サーバーサイドで動的に生成する場合など拡張子がないケースも存在します。そのため、PDFのリンクには type="application/pdf" や class="pdf" を付けるなどPDFであることを明示した方がより良いと思います。
もちろん既存ページに対してCSS改修のみでアイコンを付ける場合など、拡張子で判定せざるを得ないケースはあると思いますが。
また、 background-image にしろ content にしろ、CSSでは代替テキストが設定できないという問題があるため、アイコンはimg要素で挿入した方が良いと思います。

Re: リンクのすぐそばにアイコンをつけるCSS | 富永日記帳

まず1つ目について。確かに指摘のように、拡張子で判定するのが望ましいかというと、決してそうではないでしょう。だからと言ってMIMEタイプで判定できるか?というとそれも微妙です。今回の件とは若干毛色が違うものですが、HTML5.1ではinput要素のtype=fileでファイルの種類について次のような記述があります。

拡張子は曖昧になる傾向があり(たとえば、".dat"拡張子を使用する莫大な数のフォーマットが存在しており、Microsoft Wordの文書でない場合でも、ユーザーは通常、非常に簡単に".doc"という拡張子を持つファイル名に変更できる)、そしてMIMEタイプは信頼性が低くなる傾向がある(たとえば、多くのフォーマットは正式に登録された型を持たず、実際に多くのフォーマットが多数の異なるMIMEタイプを用いて識別される)。ユーザーが敵対的でなく、ユーザーエージェントが完全にaccept属性の要件に従った場合であっても、それが予期されたフォーマットでないかもしれないので、著者は通常、クライアントから受信したデータが慎重に扱われるべきであることに注意する。

4.10.7.1.18 File Upload状態(type=file) ― HTML 5.1

とまあ、MIMEタイプが登録されているようなファイルフォーマットであれば、MIMEタイプで判別しても良いでしょうが、なければ判別できないという事態もありえます。また、MIMEタイプで判定するにも、たとえばOffice 2007 File Format MIME Types for HTTP Content Streaming(blogs.msdn.com)あたりを見ればわかりますが、MS OfficeMIMEタイプって糞長ったらしくて、ExcelのOpenXML形式だと、

<style>
/* こんなセレクタはいやだ */
a[type$="openxmlformats-officedocument.spreadsheetml.sheet"]:after {
  content: url(image/excel.gif); 
  padding: 4px 20px 4px 0;
}
</style>
<a href="example" type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet">Excelファイルでダウンロード</a>
<!-- 拡張子のないMS Excelファイルとかまず無さそうだけど。 -->

とかスマートなHTMLとは思えないし、こんなのを書きたくないなあと(セレクタはもっと短くできるかもですが、type属性は妥当なMIMEタイプを要求される*1以上どうしようもない)。…となるとやはり指摘の通りclass属性を付け足すのが現実解になるんでしょうか。

<style>
/* 無難にマッチング */
a.link-excel:after {
  content: url(image/excel.gif); 
  padding: 4px 20px 4px 0;
}
</style>
<a href="example.xlsx" class="link-excel">Excelファイルでダウンロード</a>
...
<a href="example.xls" class="link-excel">Excelファイルでダウンロード</a>

これならば拡張子やMIMEタイプに頼ることなく確実にアイコンを付与できるでしょう。(class属性を増やすのが個人的にはあまり好きではないので不本意だなーという感じはしますが。)結局のところ、サイト外部にしろ内部にしろ、どういうリソースにリンクを張るのか、というのに依存しそうはあります。


2つめの代替テキストが指定できない、という指摘について。これはHTML5.1仕様にあまたほどあるimg要素の用例の中で、4.8.1.1.17 アイコン画像がもっとも近いですかね。

アイコンは通常、プログラム、アクション、データファイルや概念を表す単純な絵である。アイコンは、視覚ブラウザのユーザーに一目で機能を認識するのを助けることを意図する。
アイコンが同じ意味を伝えるテキストを補足する際に空のalt属性を使用する。
(中略)
アイコンがテキストで使用できない追加情報を伝える場合、代替テキストを提供する。

4.8.1.1.17 アイコン画像 ― HTML 5.1

仕様での用例までは長ったらしいので引用しませんでしたが、今回の件では地の文にアイコンが補足情報を与えるわけですから、そもそも代替テキストを含む必要性がないと思います。

代替テキストを含むべき例が思い浮かばなかったので割愛しますが、仮に私がimg要素を使うとするならば、

<a href="hoge.pdf">詳しくはこちらのPDFで <img src="image/pdf.gif" alt="" /></a>

たとえばこういうリンクテキストを設定すると思うので、代替テキストが入る余地がちょっと無いんですよね…img要素をサーバサイドで埋め込むのはその分だけHTMLの大きさが増えるわけですし、代替テキストを使用する必要が無いという前提に立てばCSSにできることなのでJSをわざわざ使うことも無いと思います。

*1:4.12.2 aおよびarea要素によって作成されるリンク http://momdo.s35.xrea.com/web-html-test/spec/WD-html51-20131029/links.html#attr-hyperlink-type