第6章 3節 後で困らない要素間のmarginの設定方法を練習問題を通して理解しよう

この節のはじめに

モジュールの再利用をするときやプログラムによって表示要素を出し分けるとき隣接する要素の組み合わせは変化し、その組み合わせが変化したときには、2つの要素間のmarginも変更したい場合があります。

この節では、隣接する要素の組み合わせが変化する具体例をもとに、後で困ることのないmarginの設定方法について学習していきましょう。

margin設定についての練習問題の基礎となるHTML

前の節で作成したmargin-tutorial.htmlの、以下の箇所を基礎として、少し変更しながら説明していきます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<ul class="mod-margin-tutorial-0001">
<li class="mod-margin-tutorial-0001__item-basic">
item-basic
</li>
<li class="mod-margin-tutorial-0001__item-1">
item-1
</li>
<li class="mod-margin-tutorial-0001__item-2">
item-2
</li>
<li class="mod-margin-tutorial-0001__item-3">
item-3
</li>
</ul>

margin設定についての練習問題の基礎となるSCSS

前の節で以下の通り記述した_mod-margin-tutorial-0001.scssを基礎として、少し変更しながら説明していきます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
.mod-margin-tutorial-0001 {
display: flex;
flex-direction: column;
.mod-margin-tutorial-0001__item-basic {
background: #dddddd;
}
.mod-margin-tutorial-0001__item-1 {
background: #ffdddd;
}
.mod-margin-tutorial-0001__item-2 {
background: #ddffdd;
}
.mod-margin-tutorial-0001__item-3 {
background: #ddddff;
}
}

margin設定についての練習問題を始める前に

「基礎となるHTML」では、以下の4つのElementクラスが付与されたli要素をul要素が包括しています。

  • mod-margin-tutorial-0001__item-basic
  • mod-margin-tutorial-0001__item-1
  • mod-margin-tutorial-0001__item-2
  • mod-margin-tutorial-0001__item-3

練習問題の説明をするにあたって、上記した4つのElementクラスが付与されたli要素をそれぞれ以下のように表現します。

  • item-basic
  • item-1
  • item-2
  • item-3

margin設定についての練習問題で想定する条件

このmargin設定についての練習問題では、以下の条件を満たせるようなmarginをElementクラスに設定していきましょう。

  • ul要素の中には、item-basic、item-1、item-2、item-3がランダムで1つまたは2つ表示されるものとします。
  • item-1とitem-1など、同じ要素が2つ表示される場合もあるものとします。
  • いずれか1つだけが表示される場合のmarginは0とします。
  • 隣接要素の無い方向、つまり最初のli要素のmargin-top、最後のli要素のmargin-bottomは0とします。
  • item-basicとitem-1、item-2、item-3のいずれかが隣接する場合、2つの要素間のmarginは20pxとします。
  • item-1、item-2、item-3のいずれか2つが隣接する場合は、2つの要素間のmarginは、item番号×item番号×10pxの式で算出した値を設定するものとします。例えばitem-1とitem-2が隣接する場合のmarginは、1×2×10=20pxとします。

この条件を満たすSCSSを書いてみてください

余裕があれば、_mod-margin-tutorial-0001.scssを編集して、この条件を満たすSCSSをご自身で書いてみてください。

正しい答えの例はこの後に掲載します。

正しい答えの例

表示されるパターンを整理する

まずは表示されるパターンを整理してみます。
表示されるパターンさえ整理されれば、あとは簡単です。

いずれか1つ表示されるパターン

以下のパターンがありますが、いずれの場合もmarginは0です。

  • item-basic
  • item-1
  • item-2
  • item-3

いずれか2つ表示されるパターン

以下のパターンがあります。

item-basicが前にくるパターン

  • item-basic、item-basicの順に表示 margin-top: 20px;
  • item-basic、item-1の順に表示 margin-top: 20px;
  • item-basic、item-2の順に表示 margin-top: 20px;
  • item-basic、item-3の順に表示 margin-top: 20px;

item-1が前にくるパターン

  • item-1、item-basicの順に表示 margin-top: 20px;
  • item-1、item-1の順に表示 margin-top: 10px;
  • item-1、item-2の順に表示 margin-top: 20px;
  • item-1、item-3の順に表示 margin-top: 30px;

item-2が前にくるパターン

  • item-2、item-basicの順に表示 margin-top: 20px;
  • item-2、item-1の順に表示 margin-top: 20px;
  • item-2、item-2の順に表示 margin-top: 40px;
  • item-2、item-3の順に表示 margin-top: 60px;

item-3が前にくるパターン

  • item-3、item-basicの順に表示 margin-top: 20px;
  • item-3、item-1の順に表示 margin-top: 30px;
  • item-3、item-2の順に表示 margin-top: 60px;
  • item-3、item-3の順に表示 margin-top: 90px;

全ての条件を満たせるSCSS

答えはとても簡単です。

第3章 14節 mod-container-0001のコードからポイントを読み取ろう」で学習した「隣接する兄弟要素が変化する可能性のある箇所は隣接兄弟要素セレクタでmarginを制御する」というポイントの通り、以下のように隣接兄弟要素セレクタを使ってmarginを制御します。

以下のように書くのが最も基本的な方法だと思います。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
.mod-margin-tutorial-0001 {
display: flex;
flex-direction: column;
.mod-margin-tutorial-0001__item-basic {
background: #dddddd;
& + .mod-margin-tutorial-0001__item-basic,
& + .mod-margin-tutorial-0001__item-1,
& + .mod-margin-tutorial-0001__item-2,
& + .mod-margin-tutorial-0001__item-3 {
margin-top: 20px;
}
}
.mod-margin-tutorial-0001__item-1 {
background: #ffdddd;
& + .mod-margin-tutorial-0001__item-basic,
& + .mod-margin-tutorial-0001__item-2 {
margin-top: 20px;
}
& + .mod-margin-tutorial-0001__item-1 {
margin-top: 10px;
}
& + .mod-margin-tutorial-0001__item-3 {
margin-top: 30px;
}
}
.mod-margin-tutorial-0001__item-2 {
background: #ddffdd;
& + .mod-margin-tutorial-0001__item-basic,
& + .mod-margin-tutorial-0001__item-1 {
margin-top: 20px;
}
& + .mod-margin-tutorial-0001__item-2 {
margin-top: 40px;
}
& + .mod-margin-tutorial-0001__item-3 {
margin-top: 60px;
}
}
.mod-margin-tutorial-0001__item-3 {
background: #ddddff;
& + .mod-margin-tutorial-0001__item-basic {
margin-top: 20px;
}
& + .mod-margin-tutorial-0001__item-1 {
margin-top: 30px;
}
& + .mod-margin-tutorial-0001__item-2 {
margin-top: 60px;
}
& + .mod-margin-tutorial-0001__item-3 {
margin-top: 90px;
}
}
}

参考程度ですが、:not(:first-child)擬似クラスを使用して以下のように書き換えることもできますので、実際のWebサイト制作では、読みやすさや編集効率などを考慮して使い分けると良いと思います。
以下のように擬似クラスを使用する場合と、隣接兄弟要素セレクタを使用する場合ではセレクタの詳細度は等しいため、隣接兄弟要素セレクタの方をより下に記述するようにしてください。
実際のWebサイト制作では、一番よく使う値がわかってきた段階で:not(:first-child)擬似クラスのセレクタで置き換えるとその後の編集効率が良くなります。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
.mod-margin-tutorial-0001 {
display: flex;
flex-direction: column;
.mod-margin-tutorial-0001__item-basic {
background: #dddddd;
&:not(:first-child) {
margin-top: 20px;
}
}
.mod-margin-tutorial-0001__item-1 {
background: #ffdddd;
&:not(:first-child) {
margin-top: 20px;
}
& + .mod-margin-tutorial-0001__item-1 {
margin-top: 10px;
}
& + .mod-margin-tutorial-0001__item-3 {
margin-top: 30px;
}
}
.mod-margin-tutorial-0001__item-2 {
background: #ddffdd;
&:not(:first-child) {
margin-top: 20px;
}
& + .mod-margin-tutorial-0001__item-2 {
margin-top: 40px;
}
& + .mod-margin-tutorial-0001__item-3 {
margin-top: 60px;
}
}
.mod-margin-tutorial-0001__item-3 {
background: #ddddff;
& + .mod-margin-tutorial-0001__item-basic {
margin-top: 20px;
}
& + .mod-margin-tutorial-0001__item-1 {
margin-top: 30px;
}
& + .mod-margin-tutorial-0001__item-2 {
margin-top: 60px;
}
& + .mod-margin-tutorial-0001__item-3 {
margin-top: 90px;
}
}
}

marginの方向について

この練習問題では、margin-topを使用しました。
実際のWebサイト制作でもmargin-topを設定する機会が一番多くなると思います。

少し補足説明をしておきますが、以下のように flex-direction: column-reverse; を設定した場合は視覚的には下から上へ要素が並べられるため、隣接兄弟要素セレクタでmargin-bottomを設定することになります。

1
2
3
4
5
.mod-margin-tutorial-0001 {
display: flex;
flex-direction: column-reverse;
〜略〜
}

以下の場合はmargin-leftを設定することになります。

1
2
3
4
5
.mod-margin-tutorial-0001 {
display: flex;
flex-direction: row;
〜略〜
}

以下の場合はmargin-rightを設定することになります。

1
2
3
4
5
.mod-margin-tutorial-0001 {
display: flex;
flex-direction: row-reverse;
〜略〜
}

この節のおわりに

このmargin設定についての練習問題をやってみることで、「第3章 4節 mod-heading-0001のコードからポイントを読み取ろう」で学習した「2つの要素間のmarginを設定するときは後の要素に設定する」というポイントのメリットや、逆に前の要素にmarginを使用してしまうと、隣接要素の組み合わせが変化した場合に困ることになるということがわかったと思います。

一応補足しておくと、「隣接する2つの要素の組み合わせが変化しない」または「隣接する2つの要素の組み合わせが変化したとしてもmarginは変化しない」ということが決まっている箇所であれば、前の要素にmarginを設定しても問題は起こりませんが、制作や運用の現場では、ときに予期しない変更依頼がくることもあります。

前の要素にmarginを設定することに大きなメリットが無いのであれば「2つの要素間のmarginを設定するときは後の要素に設定する」という方法を選択しておくと、予期しない変更があったときにも柔軟に対応できるのでお勧めです。

続きはこちら

とてもやさしいCSS設計チュートリアルの目次へ戻る