kooh-q-hook

いわゆる一つの技術メモ

CSSセレクタの優先順位

同一要素に対して複数のセレクタでstyle指定がされている時、
最終的にどのstyleが適用されているのか、といった話。

開発者ツールで、取り消し線が引かれているものと
そうでないものを日頃見てますけど、詳細はどうなっていたっけと。

私の場合、感覚的に長らく以下のようなイメージを持ってました。
ちょうどHTMLElementを検索する時と似たような感じで。

  1. ID (document.getElementById ?)
  2. クラス (document.getElementsByClassName ?)
  3. タグ (document.getElementsByTagName ?)
  4. その他属性 (document.querySelector ?, document.querySelctorAll ?)

でも、これ違うのですね。リファレンス見ましょう。
Selectors Level 4

優先度および評価順

  1. (A) ID
  2. (B) クラス、属性、疑似クラス
  3. (C) タグ、疑似要素

補足

A >> B >> C という越えられない壁があるので、より上位の方法で指定された場合はそちらが優先される。
(#id と .class ならば、#id の方が優先される)

優先度で差がつかない時は、より多くの指定がある方が優先される。
(.class と tag.class は共に A = 0, B = 1。ただし前者は C=0, 後者は C = 1 なので、後者が優先される)

所感

二番目の「より詳しく修飾した方が勝つ」というのが知れて良かったです。

一から作るならバッティングしないように設計すれば良いのですが、
そうもいかずスタイルを上書きするというシナリオは多くありますから。

それと、やはり !important 指定は安易に使ってはいけないと、改めて思い直しました。

セレクタによる指定 << インライン指定 << !important 指定 なので、
一度 !important が出てきてしまうと、対抗するにも !important が必要となってしまいます。

いたるところに「重要」「重要」とマーキングされてたら、
本当に重要なものが何かわからなくなってしまうイメージですね。


SharePoint カスタマイズにおけるCSSスタイル上書きを考える

せっかくなのでSharePoint カスタマイズに話を関連付けてみます。
というよりも、こちらが本題です。

SharePointで生成されるページ内容を見てみると、
ビルトインのCSSクラスやそれを指定したスタイルが溢れている事がわかります。

例えば、リストビューの一覧上のセル(td要素)には "ms-cellStyle" といったクラスが指定されていて、
そのクラスにはスタイルの設定(余白など)がされているわけです。

この設定を上書きする上で、どのような方法が取れるかを考えてみます。

CSSのみで対応する場合

/* 上書きする為にタグを含めて指定 */
td.ms-cellStyle { padding: 0; }

/*
または冗長的ながらクラスを属性として指定
.ms-cellStyle[class] { padding: 0; }
*/

/*
!important 指定は最終手段なので使用しない
.ms-cellStyle { padding: 0 !important; }
*/

JavaScriptで対応する場合

インラインで指定する

var cells = document.getElementsByClassName('ms-cellStyle');
var cellsCount = cells.length;
for (var i = 0; i < cellsCount; i++) { cells[i].style.padding = '0'; }

CSS+JavaScriptで対応する場合

(1) 独自クラスを追加し、既存クラスと併せて指定する

/* ms-cellStyleの内容は変更せず、独自クラスでスタイルを定義する */
/* クラスの多重指定は単一指定より優先される */
.ms-cellStyle.my-cellStyle { padding: 0; }
var cells = document.getElementsByClassName('ms-cellStyle');
var cellsCount = cells.length;
for (var i = 0; i < cellsCount; i++) { cells[i].classList.add('my-cellStyle'); }

(2) カスタムデータ属性を追加し、既存クラスと併せて指定する

/* ms-cellStyleの内容は変更せず、独自属性を加えたセレクタでスタイルを定義する */
/* クラス+属性での指定はクラスの単一指定より優先される */
.ms-cellStyle[data-my] { padding: 0; }
var cells = document.getElementsByClassName('ms-cellStyle');
var cellsCount = cells.length;
for (var i = 0; i < cellsCount; i++) { cells[i].dataset.my = 'true';  }

(3) 独自クラスとカスタム属性を追加して、それを指定する

/* ms-cellStyleの内容は変更せず、独自クラス+カスタム属性でスタイルを定義する */
/* クラス+属性での指定はクラスの単一指定より優先される */
.my-cellStyle[data-my] { padding: 0; }
var cells = document.getElementsByClassName('ms-cellStyle');
var cellsCount = cells.length;
for (var i = 0; i < cellsCount; i++) {
  var cell = cells[i];
  cell.classList.add('my-cellStyle');
  cell.dataset.my = 'true';
}

汎用的に使えるのは、CSS+Javascript でしょうか。
(3) のレベルまで適用すれば、ビルトインのクラス名を指定することもなく、 独自のスタイルで上書きできるようになるのでお勧めです。