水無月ばけらのえび日記

bakera.jp > 水無月ばけらのえび日記 > !importantの誘惑

!importantの誘惑

2012年2月13日(月曜日)

!importantの誘惑

公開: 2012年2月25日23時5分頃

こういう状況がありました。

特定の画面幅のときに要素を消すというのは、Media Queries (www.w3.org)を使ってdisplay: noneにすれば良いだけで、とても簡単です。

……と、思いきや、うまく行かずに難航。調べてみると、消したい要素にstyle属性でdisplay:blockが指定されており、CSSファイル内に書いたdisplay:noneがの指定が負けていたのでした。

jQueryで要素を表示したり非表示にしたりするメソッドは、要素に対してにdisplay:blockやdisplay:noneをセットすることがあります。これはstyle属性でつくので、意外なところにstyle属性がついていて、勝てない場合があるという話です。

CSSで普通にdisplay:noneを指定しても、style属性のdisplay:blockに打ち勝つことはできません。実は昔のCSS2ではstyle属性の優先度ははっきり書かれていなかったのですが、CSS2.1では明記されています。

  • count 1 if the declaration is from is a 'style' attribute rather than a rule with a selector, 0 otherwise (= a) (In HTML, values of an element's "style" attribute are style sheet rules. These rules have no selectors, so a=1, b=0, c=0, and d=0.)
  • count the number of ID attributes in the selector (= b)
  • count the number of other attributes and pseudo-classes in the selector (= c)
  • count the number of element names and pseudo-elements in the selector (= d)

以上、CSS 2.1 6.4.3 Calculating a selector's specificity より

というわけでstyle属性が最強です。Selectors Level3ではどうかというと、

Note: the specificity of the styles specified in an HTML style attribute is described in CSS 2.1. [CSS21].

以上、Selectors Level 3 9. Calculating a selector's specificity より

「CSS2.1を見ろ」というスタンスで、つまりはCSS2.1と同じくstyle属性最強です。"CSS Style Attributes" にもこういう記述があります。

The declarations in a style attribute apply to the element to which the attribute belongs. In the cascade, these declarations are considered to have author origin and a specificity higher than any selector. CSS2.1 defines how style sheets and style attributes are cascaded together.

以上、CSS Style Attributes より

どう転んでもstyle属性最強です。そこで一瞬だけ脳裏をよぎったのが……「!importantを使えば勝てる」という考え。

宣言の後ろに!importantをつけると、普通のスタイル (Author normal style sheets) を上書きできるので、勝つことができるようになります (CSS Cascading and Inheritance Level 3 9. Computing weight (www.w3.org))。

しかし、!importantは禁断の技です。単独のページを作るときならともかく、汎用的なコンポーネントを設計している時に使うべきではありません。そんなことをすると、運用者がカスタマイズできなくなって困ることになるからです。!importantをつけると、それだけで複雑なルールにも勝てますが、他の人が後でこのルールに勝とうとしたとき、地雷を踏むことになります。

しかし、!importantを使ってしまえば、目前の課題はあっさり解決する上、運が良ければ問題が発覚することもない、というのも事実。

誘惑としばらく戦って、結局、このように解決することにしました。

display:noneに限って言えば、親要素に指定すれば子孫要素は全部消えます。子孫要素のstyle属性でdisplay:blockが指定されていても関係ないわけです。

どうせstyleがつくのはJavaScript有効の時だけですから、スクリプトでdivを入れて、そのdivにMedia Queriesで良い感じのスタイルが当たるように調整して完了。

今回は!importantの誘惑を何とか回避できましたが、危ないところでした。

関連する話題: Web / HTML / CSS / JavaScript

最近の日記

関わった本など