CSSセレクタを活用してDOM操作をもっと快適にする

CSSセレクタ フロントエンド

私の勤務先ではまだまだjQueryが現役です。私は1年間マークアップの業務をしてCSSを学んだあと、エンジニアに転身しましたが、jQueryでDOM操作をしていると、「最初にCSSをやっておいて本当に良かった!」と思います。そんな私がオススメするCSSセレクタ8選です。

論理和(AまたはB)

以下のHTMLで、1行目と2行目のどちらにもヒットさせたいときです。

<div class="class-a"></div>
<div class="class-b"></div>

class-aまたはclass-bは以下のように書きます。

.claass-a, .class-b {...}

カンマ区切りでいくつも指定可能です。同じスタイルを複数の場所に当てたいときに使います。

論理積(AかつB)

以下のHTMLで、3行目のDOMを特定したいときです。

<div class="class-a"></div>
<div class="class-b"></div>
<div class="class-a class-b"></div>

class-aかつclass-bは以下のように書きます。

.class-a.class-b {...}

順序は問いません。クラスまたはIDを、スペースやカンマなしでくっつけて書きます。

子孫セレクタ(Aの子階層のすべてのB)

以下のHTMLの、「ひとつめのpタグです」と「ふたつめのpタグです」をヒットさせたいときです。

<div class="wrapper">
  <p>ひとつめのpタグです</p>
  <div class="box">
    <p>ふたつめのpタグです<p>
  </div>
</div>
<p>みっつめのpタグです</p>

wrapperクラス配下のすべてのpタグを特定するには以下のように書きます。

.wrapper p {...}

子孫セレクタは、親と子孫の間にスペースを開けて記述します。配下にあれば子、孫、曾孫どれもヒットします。

子セレクタ(Aの直下にB)

以下のHTMLの、「直下の子です」と「直下の子のふたつめです」をヒットさせたいときです。

<div class="wrapper">
  <p>直下の子です</p>
  <div class="box">
    <p>孫です<p>
  </div>
  <p>直下の子のふたつめです</p>
</div>
<p>外側のpタグです</p>

wrapperクラス直下のpタグを特定するには以下のように書きます。

.wrapper > p {...}

子セレクタは大なり(>)を使います。孫や曾孫にはヒットしません。

属性セレクタ

まずHTMLの属性とは何かおさらいです。属性とはタグに対して付加する何かしらの設定のことです。以下のように記述します。

<要素名 属性="属性値">

たとえば、imgタグのsrc属性や、aタグのhref属性、汎用的なものだとclass属性、name属性、value属性などたくさんありますね。

属性セレクタとは特定の属性を持つ要素をヒットさせるときに使います。
たとえば、プルダウンで選択されている要素だけ色を変えたいとき。

<select>
  <option value="1">html</option>
  <option value="2" checked>css</option>
  <option value="3">js</option>
  <option value="4">ruby</option>
</select>

cssが選択されているので色を変えたいです。
「select配下のchecked属性がついているoption」を特定するには以下のように書きます。

select option[checked] {...}

タグに続けて大かっこで囲み、属性名を記述します。タグでなくても、クラスでもIDでも属性セレクタをつけることができます。

もうひとつ例です。上記のHTMLで、valueが3のoptionだけ色を変えたいとします。

select option[value="3"] {...}

属性セレクタは、属性を持つかどうかだけでなく値でも特定が可能です。
また、値は前方一致、後方一致、部分一致での検索も可能です。

/* "#" で始まる内部リンク */
a[href^="#"]

/* URL のどこかに "example" が含まれるリンク */
a[href*="example"] 

/* ".org" で終わるリンク */
a[href$=".org"] 

最初の要素

以下のHTMLの、リストの一番上の「バナナ」だけにヒットさせたいときです。

<ul>
  <li>バナナ</li>
  <li>りんご</li>
  <li>みかん</li>
  <li>すいか</li>
  <li>パイナップル</li>
</ul>

子孫セレクタや子セレクタだと難しそうです。一番上のliに対してクラスを付与すれば簡単ですが、操作したい要素すべてにクラスをつけていくのも効率的ではありません。そいういう時にCSSの疑似クラスが使えます。

疑似クラスとは

セレクターに付加するキーワードであり、選択された要素に対して特定の状態を指定します。:hover、:focus、:activeなどが擬似クラスの代表者です。疑似クラスにはN番目系の便利なものもあります。

ul配下のliのうち一番最初の要素を特定するには以下のように書きます。

ul li:first-child {...}

最後の要素

以下のHTMLの、リストの一番下の「パイナップル」だけにヒットさせたいときです。

<ul>
  <li>バナナ</li>
  <li>りんご</li>
  <li>みかん</li>
  <li>すいか</li>
  <li>パイナップル</li>
</ul>

ul配下のliのうち一番最後の要素を特定するには以下のように書きます。

ul li:last-child {...}

N番目の要素

以下のHTMLの、リストの「みかん」だけにヒットさせたいときです。

<ul>
  <li>バナナ</li>
  <li>りんご</li>
  <li>みかん</li>
  <li>すいか</li>
  <li>パイナップル</li>
</ul>

ul配下のliのうち3番目の要素を特定するには以下のように書きます。

ul li:nth-of-type(3) {...}

N番目系の疑似要素で、:nth-of-typeと似たような効果のある:nth-childがありますが、:nth-of-typeの方がオススメです。:nth-childがイマイチな例を示します。

<div class="wrapper">
  <p>バナナ</p>
  <div>ほげ</div>
  <p>りんご</p>
  <p>みかん</p>
  <p>すいか</p>
  <p>パイナップル</p>
</div>
.wrapper p:nth-child(3) {...}

この場合、どの要素がヒットするでしょうか?

答えは「みかん」ではなく「りんご」です。

なぜかというと、:nth-childはwrapper配下のpタグの3つ目を探すのではなく、.wrapper配下の3つ目のタグを探すのです。そのためdivタグもカウントされてしまい、「みかん」ではなく「りんご」が選択されます。

この動作はあまり直感的でなく「アレ?うまくいかない…」という混乱が起こりがちです。:nth-of-typeを使いましょう。

N番目系の疑似要素は他にも便利なものがたくさんあります。N番目以降、奇数だけ、偶数だけ、NからNまで、3つ飛ばしなど。使いこなすと大変便利です。

CSSセレクタのススメ

jQueryでDOM操作をするとき、CSSセレクタでなくても、いろんな方法でDOMを選択できます。例えば、find、parent、next、closestを使って目的の要素を探したり、もしくはjQueryの独自セレクタを使ったりです。でも私としてはCSSセレクタをオススメします。理由はふたつあります。

  • ブラウザのDOM検索パフォーマンスの恩恵を受けられる(つまり他の方法より速い!)
  • 可読性の良さ

CSSセレクタを使うとき、以下の点に注意すると保守性もアップします。これはCSS設計の基礎でもあるのですが、エンジニアさんもぜひ覚えていただきたいです。

  • divやspanなど文書構造として意味を持たないタグはセレクタに含めない(divやspanは消したり追加したり変更が入りやすいためです)
  • クラス名の名前被りに注意する(.buttonとか汎用クラスっぽいものは意図しない箇所にも該当してしまうので子孫セレクタや子セレクタを使うこと)
タイトルとURLをコピーしました