ブログやサイトのデザインカスタマイズをしていると「先頭や最後のこの要素だけに指定がしたいんじゃぁ~」という場合が多くあります。
力技、というか、まぁ普通にやろうとすれば、先頭の要素や最後の要素だけにクラスを指定して、そのクラスに対してCSSを定義する、なんてことをしますが、これが毎回クラス指定を書く、となると、これが結構面倒なんですね。
そんな時に大活躍するのが「nth-child」と「nth-of-type」。
CSS3で追加されたプロパティですが、使い分け、というか、それぞれの使い所が今一分からず(と私同様に思ってる方、きっと多いと思い)、ここで簡単な例を紹介します。
Contents
簡単な説明
使い出すと便利でしょうがない「nth-child」、「nth-of-type」ですが、簡単に説明すると、
- nth-child(n)
- n番目の要素が指定された要素であれば適用
- 指定された要素でなければ適用しない
- nth-of-type(n)
- 指定した要素のn番目に適用
一般的なブログ形式からの具体例
この2つの違いを、以下の様なブログの一般的な形式から具体例で見てみます。
- <h1>タイトル<h1>
- <p>導入部</p>
- <h2>サブタイトル1<h2>
- <p>本文1</p>
- <h2>サブタイトル2<h2>
- <p>本文2</p>
- <h2>サブタイトル3<h2>
- <p>本文3</p>
- <h2>まとめ<h2>
- <p>まとめ文</p>
ここで「サブタイトル1だけ」にCSSを適用したい、と考えたとします。この場合、1番始めに出てくる<h2>がその対象になりますが、その h2 を指定するには、
- 1)h2:nth-child(1)
- 2)h2:nth-of-type(1)
のどちらが良いでしょうか?
答えは2)。
1)では「nth-child」の定義に従って「最初の要素が h2 であれば適用」、ということになります。
見て分かるように最初の要素はタイトルの h1 であるため、この場合では サブタイトル1の h2 に適用されない、となりますね?
2)では、間になにがあろうと「とにかく最初の h2 に適用」ということになり、バッチリ「サブタイトル1」に適用されます。
ここで特別に「先頭だけ」、「最後だけ」、と指定するには、
- nth-childの場合
- first-child (先頭だけに適用: nth-child(1)に同じ)
- last-child (最後だけに適用)
- nth-of-typeの場合
- first-of-type (先頭だけに適用: nth-of-type(1)に同じ)
- last-of-type (最後だけに適用)
という指定の仕方ができます。
上の例では以下のようになります。
- 1)h2:first-child
- 2)h2:first-of-type
リスト形式からの具体例
では、よく使われるリストなどではどうでしょう?
- <ul>
- <li>リスト項目1</li>
- <li>リスト項目2</li>
- <li>リスト項目3</li>
- </ul>
実際表示すると、以下のようになります。
- リスト項目1
- リスト項目2
- リスト項目3
これを表のように見せたい場合、以下のように ul に外枠を指定して、li には下線を指定し、
1 2 3 4 5 6 7 8 9 10 11 12 |
ul{ border-:1px solid black; /* 黒の外枠 */ padding: .25em 1em .25em; /* 窮屈にならないよう、内側の余白を少し指定 */ } ul li { border-bottom: 1px solid gray; /* 灰色の罫線を各項目の下に表示 */ list-style: none; /* 先頭の丸を非表示 */ } |
このまま表示すると...
- リスト項目1
- リスト項目2
- リスト項目3
表っぽくなりましたが、一番下の下線が周りの線と重複しているように見えて美しくないですね。
この場合、liの項目がいくつになろうが最後のliのみ下線はなし、と指定できればOKなので、以下のように1)または2)を指定します。
- 1) li:last-child{
- border-bottom: none;
- }
- 2) li:last-of-type{
- border-bottom: none;
- }
今回の場合、指定したい要素 li は、li 以外の要素(例えば p とか div など)が間にないので、1),2)のどちらの指定の仕方でもOK、となりますね。
- リスト項目1
- リスト項目2
- リスト項目3
お!すっきりしました。b^-^)v
nth-childとnth-of-typeの使い分け
個人的には、元々 nth-child しか利用してませんでしたが、どうもうまく目的の要素が指定できない、CSSが反映されない、といった事がたまにありました。
なぜうまくできないのだろう、と思いつつ、そんな場合は応急措置的にクラスを指定して対応していたのですが、調べると nth-of-type ものがある、なんだ、そういうことか、と分かった、というわけです。^◇^)ゞ
それでも更に疑問に思ったのは、
- 普通は単純に「特定の要素について何番目のものに適用したい」といった使い方だよね?
- nth-child のように「何番目の要素が指定した特定の要素なら適用」、などといった複雑な使用の仕方はないのでは?
- それなら、nth-child っていらなくない? nth-of-type だけがあれば混乱することもないのに...
といったもの。
とういことで、ここでブログのデザインカスタマイズで有り得そうな nth-child と nth-of-type の使い分けの例を見てみましょう。
具体的使い方 nth-child
例えば、記事の先頭には基本的にアイキャッチとなる画像を入れる、というブログの場合を考えます。
具体的に各記事は以下の様な感じです。ここで「画像1」が記事先頭のアイキャッチ画像。
- <div id="content">
- <img>画像1</img>
- <h2>サブタイトル1</h2>
- <p>本文1</p>
- <h2>サブタイトル2</h2>
- <img>画像2</img>
- <p>本文2</p>
- <h2>まとめ</h2>
- <p>まとめの文</p>
- </div>
この場合、先頭画像(画像1)だけに特別な枠のデザインを付けたい、とすると、先頭画像の指定は、
- 1)#content img:first-child
- 2)#content img:first-of-type
のどちらでもOKです。が!記事によって「先頭の画像がないものもある」となると話は違ってきます。
先頭の画像がない場合(画像1がない場合)、1)では最初の要素が「サブタイトル1」の<h2>になり、指定している要素 img とは異なることから、CSSは適用されません。
2)の場合では、最初の img に対してCSSが適用されるので、画像2に適用されてしまう、ということになります。
ということから、基本は記事の先頭にアイキャッチ画像を入れるが、そうでない場合もある(先頭に画像がない場合もある)と考えれば、柔軟なブログ運営として適切なのは1)の「#content img:first-child」となります。
具体的使い方 nth-of-type
では2つ目の例として、よくある「まとめ文」について見てみます。
記事の最後によくある「まとめ」では「必ずリスト形式を使った箇条書きのまとめがある」という場合を考えます。例えば以下の様な形です。
- <div id="content">
- ~ 中略 ~
- <h2>まとめ</h2>
- <ul>
- <li>まとめ1</li>
- <li>まとめ2</li>
- <li>まとめ3</li>
- </ul>
- <p>全体の感想など</p>
- </div>
ここで、記事最後にあるリストに特定のCSSを適用させたい、つまり、まとめの中にある「まとめのリスト」だけに特定のCSSを適用さて格好良く表みたいに見せたい!、その「まとめのリスト」の指定は、
- 1)#content ul:last-child
- 2)#content ul:last-of-type
さて、どちらが適切でしょうか?
答えは2)です。
#contentに含まれる最後の要素は<p>であり、<ul>は最後から2番めの要素、となるため、1)の指定の仕方では目的とする ul にCSSは適用されません。
ここで、場合によってまとめの中のリストが無い、単に文章だけの場合がある、とすると意図しない本文中の ul にCSSが適用されることになりますので注意が必要です。
(こうなってくると、最後の ul にクラスを指定するのが最も確実、となりますが、これが以外に面倒だったりするんですね...)
今回のまとめ
- nth-child(n) は、n番目の要素が指定された要素であれば適用
- nth-of-type(n) は、指定した要素のn番目のものに適用
- 前後や間に別の要素が入らなければ、どちらも同じ
- 前後や間に別の要素が入る場合、nth-of-type で指定する
nth-child,nth-of-type を使うようになると、工夫次第で色々な場面に色々な効果を出すことが出きます。
それでもどうもうまく指定できない、反映されない、という場合には、nth-child, nth-of-type の使い分けがうまくできていない、と思われますので、もう一度各々の定義を見なおして、どちらを使うべき箇所なのかを見てみてくださいね。