縦に並んだ要素間のcssでの上下の余白対応について

ブロック要素で文章などの要素が縦に続く時、余白を設定するときにどうすればいいか迷う時があったので、備忘録として残しておくことにした。

あくまで自身の見解なので、このやり方が正しいというわけでないことはご了承いただきたい。デモは一番最後に掲載しているので、参考にしていただければと思う。

例えば、下記のようなhtmlコードの場合、要素と要素の間で余白を付けたい場合がある。

<div>
      <p>テキストテキスト</p>
      <p>テキストテキスト</p>
      <ul >
        <li>リスト</li>
        <li>リスト</li>
        <li>リスト</li>
      </ul>
</div>

この要素自体に1つずつcssを指定して余白を作るのは効率が悪いと思う。なぜなら、中身に入るテキストやレイアウトに変更が入るかもしれない。pがulになったり、dlになったり、tableになることもあるかもしれない。

そこで、いろんな書籍を読んだり、WEBサイトで使われているもの、現場で使っているものの3点から、分析した結果、3パターンに分けることができたので、そちらを紹介していきたいと思う。

なお、今回空けたい余白は、pとpの間、pとulの間で考えるものとする。余白は20pxで指定することにする。

隣接セレクタ(+)を用いた余白のつけかた

隣接セレクタの特徴は、同じ階層にある要素Aタグ、要素Bタグと続けて記述されている状況の時に、要素Aタグの後に記述されている要素Bタグに対して、cssを指定できるといったものだ。一般してで伝えるのは難しいので、上述のソースを通してみていきたい。

隣接セレクタを使う場合に気をつけることは、まず同じ階層にどのようなタグが用いられているか確認することである。

今回の例では、pが2つ、ulが1つ用いられている。もしも、pが3つだけで今後も変更されないような状況の場合は、下記のように記述するのが好ましいだろう。

div > p + p {
  margin-top: 20px;
}

このように記述することで、一番目のpタグ以外の上部の余白は20px空くようになる。

しかし、この状況はリスト以外の状況ではそんなに起こらないかと思う。実際はいろんなタグが使われているので、下記の全称セレクタを用いるのが良いかと思う。

div > * + * {
  margin-top: 20px;
}

これでpとpの間、pとulの間でも余白が空くようになるのがわかるかと思う。また、pやulに限らず他のタグが入っても余白が空くようになっている。

否定擬似クラス(not)を用いた余白のつけかた

続いては否定擬似クラス(not)を用いたやり方だ。notは、「:not(●●)」で指定するのだが、●●以外の状況の時に指定できるcssだ。具体的な使い方は「not、否定擬似クラス」とかで検索すると出てくるので、イメージが浮かばない方は調べてみてほしい。

このnotと初めて出会った時は、頭の中が混乱して、〜でない時?ってどういう状況なのか整理するのに時間がかかっていたし、こんなのいつ使うんだよとか思っていたが、今回の指定方法は結構便利だなーと思った。

これもまずタグが同じであるかを確認することから始まる。全てpタグであれば下記のような指定になる。

div > p:not(:first-of-type) {
  margin-top: 20px;
}

注目する点は、first-of-typeである。これとfirst-childをどう使い分けるか、いつも悩まされていたが、簡単にいうと違いは、同じタグが使われているか、いないかの違いである。ここでは深く言及はしないので、詳しく知りたい方は調べてみてほしい。

first-of-typeはタイプが同じである要素の一番目という覚え方がいいのではないかと思う。なので、pだけが指定されている状況や、ulの中のliで使うことが多い。いろんなタグが使われている場合は不向きだ。

一方で、first-childは子供の要素全部に対して一番目という覚え方をしていた(結構無理があると思うけど…)。なので、どんなタグが同じ階層で使われていようが、関係なく一番目の要素に対して指定が可能になる。今回であれば下記の指定がいいだろう。

div > *:not(:first-child) {
  margin-top: 20px;
}

ネガティブマージンを用いた余白のつけかた

最後は、ネガティブマージンだ。これは結構シンプルなやり方で、自分の場合はすんなり理解できた。

単純に一番外側を囲っているdivに対して、下記のようにcssを指定する。

div {
  margin-bottom: -20px;
}

続いて、全称セレクタを用いて下記のようにcssを指定する。

div > * {
  margin-bottom: 20px;
}

これらの指定をすることで、外側の大枠のdivに対しては、下側の余白が-20px、ulの下側の余白が20pxとなり、余白が打ち消される。

cssの記述量が多くなるデメリットはあるが、使いやすいとは思う。

以上、3パターン取り上げたが、個人的に使うのは隣接セレクタかなと思う。こんな感じで書いてみたが、いかがだっただろうか。今回のデモは下記のボタンから確認できるので参考にしてみてほしい。

初めてかいてみたけど、色々間違ってないか不安だ…なんか指摘あったら修正したいと思う。