CSSで華やかなサイトにしたい④～レイアウトを組む(幅、高さ、余白、レイアウト編)～

#レイアウトを組む
レイアウトとは、掲載する様々なコンテンツを、ユーザーが使いやすいようにどう配置するかを設計することです。
デザインする上で大切なところになってきますので、順を追って学習を進めていきましょう:relaxed:
レイアウトを組む時に、各要素をブロック要素でまとめます。その際に必要な知識、幅や高さの指定、余白の調整についても今回学習していきましょう。

今回の記事:arrow_down:

- 幅と高さを指定しよう
     - 幅「auto」で指定とは？
     - 幅を「%」で指定すると？
     - Webサイト上で使う単位について
- 余白を調整しよう
      - 要素の外側の余白「marginプロパティ」
      - 要素の内側の余白「paddingプロパティ」
      - 余白をつかってグループ化する
- レイアウトを組もう～Flexboxで横並び「display:flex;」～
       - 子要素の並ぶ向き「flex-direction」
       - 子要素の折り返し「flex-wrap」
       - 水平方向の揃え「justify-content」
       - 垂直方向の揃え「align-items」
- レイアウトを組もう～CSSグリッドでタイル型レイアウトを作る～
       - グリッドアイテム(子要素)の横幅「grid-template-columns」
       - グリッドアイテム(子要素)同士の余白「gap」
       - CSSグリッドで使える単位「fr」
       - グリッドアイテム(子要素)の高さ「grid-template-row」
       


レイアウトを理解する上でこちらの記事も参考にしてください:point_down_tone2:
[HTMLを理解するコツとは？！ブロック要素でグループ分けをする](https://qiita.com/Yuriko-Y/items/cf6b6f3c739f6c544ccb)

#幅と高さを指定しよう
幅と高さの指定方法を学習していきます。Webサイトの制作ではそれぞれのグループに対してサイズを指定する機会が多々あります。
**幅は「widthプロパティ」**、**高さは「heightプロパティ」**で要素の大きさを指定できます。

**主な値**

|  指定方法              |       説明|  
|:---------------------------|------------------|  
| 数値          |数値に「px」や「rem」、「%」などの単位をつける |
| auto           |関連するプロパティの値によって自動設定|

```HTML:HTML
<div>
   <h1>猫の好きな事</h1>
   <h2>毛づくろいをすることが好き</h2>
   <p>毛づくろいの目的はいくつかありますが、舌にある無数の突起をブラシ代わりにして、体を清潔にすることが大半。
    猫は、起きている時間の30〜50％を毛づくろいに費やすほどキレイ好きなんです。</p>
</div>
```

```css:幅と高さの指定：CSS
div{
    background: aquamarine;
    width: 500px;
    height: 300px;
}
```
<img width="440" alt="コメント 2020-04-15 101711.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562982/3916028d-b584-c7a3-63c2-ab0eeebd524d.png">

####幅「auto」で指定とは？
＜div＞タグや＜p＞タグなどのブロック要素では、「width」の値を指定しない場合は、要素の幅は横いっぱいに広がります。**「auto」**の場合は、要素の幅が自動で決められます。幅が「auto」の時、要素の幅はその要素を囲っている親要素よりも大きくなることはありません。

例：＜div＞という親要素の中に、＜p＞タグがあるとします。＜div＞タグが幅500pxなら、その子要素である＜p＞タグは幅を指定しない限り、自動で500pxになります。
![auto.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562982/363e6833-ba3e-3c25-5ddf-237146ffeb2d.jpeg)


####幅を「%」で指定すると？
widthプロパティの値を「%」で指定すると、その要素を囲っている親要素の幅に対する比率で幅が決定します。つまり**親要素の幅によって変動**します。

例:＜div＞タグの中に＜p＞タグがあり、＜div＞タグの幅500px、その子要素である＜p＞タグの幅が50%の場合、＜p＞タグの幅は親要素の半分の250pxになります。
![percent.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562982/e222ae70-c3ae-287a-be0d-4c6a5a12ba5b.jpeg)

####Webサイト上で使う単位について
CSSでは文字サイズや要素のサイズを指定する際に、単位をつけて数値を指定します。代表的な単位についていくつか紹介していきたいと思います:slight_smile:
まず単位の種類は大きく分けて**「相対単位」**と**「絶対単位」**の2種類があります。

**「相対単位」**
ブラウザーの表示領域や他の要素に指定したサイズを基準として相対的に算出される単位です。基準にするサイズによって大きさが変化します。
**例：「%」,「em」,「rem」,「vh」**

**「絶対単位」**
ブラウザーの表示領域や親要素のサイズに影響されることなく、指定したサイズでそのまま表示される単位です。
**例：「px」**
#余白を調整しよう
余白はただの空きスペースではなく、画面全体を見やすく、文章を読みやすくするデザイン要素です。レイアウトを組む時にも出てくるので、コツをつかんでおきましょう:thumbsup_tone2:

余白のプロパティには**「margin(マージン)」**と**「padding(パディング)」**があります。この二つの違いをおさえておきましょう。
![space.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562982/3e4a1b50-6d01-2fa1-b736-4b41cafd122e.jpeg)
要素を四角い入れ物と考えたとき、**「margin」**はその入れ物からの他の入れ物までの距離、**「padding」**は入れ物のフチから中身（コンテンツ）までの距離です。また、marginとpaddingの間の枠線のことを**「border(ボーダー)」**といいます。

####要素の外側の余白「marginプロパティ」
要素の周りに余白を加えます。marginプロパティでは要素の四辺にすべてに、「margin-top(上)」、「margin-bottom(下)」、「margin-left(左)」、「margin-right(右)」といった指定する方法があり、これらを使えば、どの位置に余白指定をするか設定できます。

```css:marginの例：CSS
div{
    background: aquamarine;
    width: 500px;
    height: 300px;
    margin-top: 30px;
    margin-left: 100px;
}
```
<img width="455" alt="コメント 2020-04-15 115734.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562982/e91f9a23-f81c-27b8-e55d-a2616ec88c3c.png">

また、marginプロパティのみの使用で、半角スペースで区切って上下と左右の余白を指定したり、**上・右・下・左(時計回り)の順**で一括指定することもできます。

|  書き方             |       例|  
|:---------------------------|------------------|  
|margin: 四辺すべて;        |margin: 10px; |
|margin: 上下　左右;          |margin: 10px 20px;|
|margin: 上　左右　下;|margin: 10px 20px 30px;|
|margin: 上　右　下　左; |margin: 10px 20px 30px 40px;|

先程と同様、要素の上に30px、左に100pxの余白を付けるときは、「margin」プロパティだけで以下のようにも記述できます。

```css:marginの例：CSS
div{
    background: aquamarine;
    width: 500px;
    height: 300px;
    margin: 30px 0 0 100px;
}
```
####要素の内側の余白「paddingプロパティ」
要素の内側に余白を付けたいときは**paddingプロパティ**を使います。marginと同様、要素の四辺すべてに、「padding-top(上)」「padding-bottom(下)」「padding-left(左)」「padding-right(右)」と余白を付けたい位置を指定できます。また半角スペースで区切って**上・右・下・左(時計回り)の順**で一括指定することもできます。

```css:paddingの例：CSS
div{
    background: aquamarine;
    width: 500px;
    height: 300px;
    padding: 40px;
}
```
ボックスのフチとテキストの間に40pxの余白ができました。
<img width="436" alt="コメント 2020-04-15 133201.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562982/10fe47df-0a18-0086-72f5-5c9559b77145.png">

####余白をつかってグループ化する
人は複数のものが近くに設置されているとそれらが**関連している**と認識します。
余白を使うことで関連する情報を**グループ化**できます。
レイアウトを考える上で、**関連しない情報は近づけないよう**には注意しましょう。

例を見てみましょう。グループとグループの間にスペースを空けるとグループがわかりやすくなります。
<img width="692" alt="コメント 2020-04-15 143416.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562982/912a1883-49fe-bb1d-02d9-0a5796d05d0c.png">


様々なWebサイトの余白の使い方を研究し、デザインの参考にしてみてください:yum:

#レイアウトを組もう～Flexboxで横並び「display:flex;」～
幅、高さ指定、余白の調整をマスターしたら、次はいよいよレイアウトを組んでいきます。ここではまずFlexboxで横並びにする方法について学んでいきます。
**Flexbox**とは複雑なレイアウトも簡単に組める書き方です。
Flexコンテナーと呼ばれる親要素の中に、Flexアイテムと呼ばれる子要素を入れてHTMLを作成します。
![Untitled Diagram.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562982/29f63966-c3c0-75f6-ac2e-3c8e54fff324.jpeg)

例:HTMLは親要素である「container」というクラスのついた＜div＞タグの中に、子要素である「item」というクラスのついた＜div＞タグが入っています。

```HTML:HTML
    <div class="container">
        <div class="item">Item1</div>
        <div class="item">Item2</div>
        <div class="item">Item3</div>
        <div class="item">Item4</div>
    </div>
```
```css:CSS
.item{
    background-color: rgb(73, 76, 248);
    color: #ffffff;
    margin: 10px;
    padding: 10px;
    width: 200px;
}
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562982/26703518-522c-181f-180a-a30e828a9a56.png)


現状は縦に並んでいますが、これを横並びにしていきましょう:bangbang:
CSSに親要素である「.container」に対して**「display:flex;」**を追加しましょう。

```css:横並びCSS
.container{
    display: flex;
}
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562982/c457d08f-f483-a7c3-5151-f823aa446e76.png)

これで横並びになりました:v_tone2:
親要素に**「display:flex;」**を記入した上で、**追加プロパティ**を記述すれば要素の並び方を**カスタマイズ**できます。
どのように並べていきたいかは指定するプロパティによるので、1つ1つ紹介していきます。
####子要素の並ぶ向き「flex-direction」
子要素をどの方向に配置していくかを**flex-direction**プロパティで指定します。横または縦に並べられます。

**flex-directionプロパティで使える値**

|  値             |       説明|  
|:---------------------------|------------------|  
| row(初期値)        |子要素を左から右に配置|
| row-reverse  |子要素を右から左に配置|
|column|子要素を上から下に配置|
|column-reverse|子要素を下から上に配置|

![Untitled Diagram.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562982/f5636957-6e50-da7f-b707-45d9ba645c89.jpeg)

```css:CSS(row-reverse例)
.container{
    display: flex;
    flex-direction: row-reverse;
}
.item{
    background-color: rgb(73, 76, 248);
    color: #ffffff;
    margin: 10px;
    padding: 10px;
    width: 200px;
}
```
<img width="737" alt="コメント 2020-04-16 145050.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562982/0df67ae4-6f5f-42db-0f64-eebea3aa98aa.png">

要素が右から左に横並びになりました。
####子要素の折り返し「flex-wrap」
子要素を1行、または複数行に並べるかを**flex-wrap**プロパティで指定します。複数行にする場合は子要素が親要素の幅を超えてしまった場合、折り返して複数行に配置されます。

**flex-wrapプロパティで使える値**

|  値             |       説明|  
|:---------------------------|------------------|  
| nowrap(初期値)        |子要素を左から右に配置|
| wrap  |子要素を右から左に配置|
|wrap-reverse|子要素を上から下に配置|

![wrap.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562982/cfaf2e4a-c525-244c-6218-436ebd54bcad.jpeg)


```HTML:HTML
    <div class="container">
        <div class="item">Item1</div>
        <div class="item">Item2</div>
        <div class="item">Item3</div>
        <div class="item">Item4</div>
        <div class="item">Item5</div>
        <div class="item">Item6</div>
        <div class="item">Item7</div>
        <div class="item">Item8</div>
    </div>
```

```css:CSS(wrap例)
.container{
    display: flex;
    flex-direction: row-reverse;
}
.item{
    background-color: rgb(73, 76, 248);
    color: #ffffff;
    margin: 10px;
    padding: 10px;
    width: 200px;
}
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562982/198a9092-2199-55e1-375c-7e826339823c.png)

親要素の右端に到達した地点で、次の行に折り返しがされました。
####水平方向の揃え「justify-content」
親要素に空きスペースがあった場合、子要素を水平方向のどの位置に配置するかを**justify-content**プロパティで指定します。

**justify-contentプロパティで使える値**

|  値             |       説明|  
|:---------------------------|------------------|  
| flex-start(初期値)        |行の開始位置からの配置。左揃え|
| flex-end  |行末から配置。右揃え|
|center|中央揃え|
|space-between|最初と最後の子要素を両端に配置し、残りの要素は均等に間隔をあけて配置|
|space-around|両端の子要素も含め、均等に間隔をあけて配置|

![justify-content.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562982/4114c261-1172-f953-a7de-18ef18e86496.jpeg)

```HTML:HTML
    <div class="container">
        <div class="item">Item1</div>
        <div class="item">Item2</div>
        <div class="item">Item3</div>
        <div class="item">Item4</div>
    </div>
```

```css:CSS(flex-end例)
.container{
    display: flex;
    justify-content: flex-end;
}
.item{
    background-color: rgb(73, 76, 248);
    color: #ffffff;
    margin: 10px;
    padding: 10px;
    width: 200px;
}
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562982/6b38a9c3-b945-f90a-9cbc-313b0904d612.png)
画面の右端に揃いました。

####垂直方向の揃え「align-items」
親要素に空きスペースがあった場合、子要素を垂直方向のどの位置に配置するかを**align-itemsプロパティ**で指定しましょう。

**align-itemsプロパティで使える値**

|  値             |       説明|  
|:---------------------------|------------------|  
| stretch(初期値)      |親要素の高さ、またはコンテンツの一番多い子要素の高さに合わせて広げて配置|
| flex-start  |親要素の開始位置から配置。上揃え|
| flex-end  |親要素の終点から配置。下揃え|
|center|中央揃え|
|baseline|ベースラインで揃える|

![align-items.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562982/84e54c1d-5309-ff9c-3c55-61bad85cd344.png)

```HTML:HTML
    <div class="container">
        <div class="item">Item1</div>
        <div class="item">Item2</div>
        <div class="item">Item3</div>
        <div class="item">Item4</div>
    </div>
```

```css:CSS(center例)
.container{
    display: flex;
    align-items: center;
    height: 100vh;
}
.item{
    background-color: rgb(73, 76, 248);
    color: #ffffff;
    margin: 10px;
    padding: 10px;
    width: 200px;
}
```
※vhはビューボードの高さを基準をした単位。

<img width="807" alt="コメント 2020-04-29 175651.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562982/fb69eb28-e854-3953-c590-24b3e808e195.png">



「height」で高さを指定し、そのちょうど中間の部分に要素が並びます。高さを「100vh」とするとこで、表示領域いっぱいに広げています。

#レイアウトを組もう～CSSグリッドでタイル型レイアウトを作る～
タイル型レイアウトとは、壁にタイルを敷き詰めるように同じ大きさのボックスを等しい間隔で並べていくレイアウトです。ここでは**「CSSグリッド」**という方法を紹介します。

CSSグリッドを使うにはflexboxと同じように親要素と子要素が必要です。グリッドコンテイナーと呼ばれる親要素で全体を囲み、その中に実際に横に並べていくグリッドアイテム(子要素)を配置します。また、グリッドアイテムの間の空白スペースのことをグリッドギャップといいます。
![grid.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562982/06a840fb-8470-85a1-092a-8a2256ec890c.jpeg)
今回はこのタイル型レイアウトを使ってカフェのメニューのようなものを作っていきます:coffee:
<img width="960" alt="コメント 2020-04-17 152227.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562982/58cfe73a-be23-1d9a-b713-5779f988a385.png">


HTMLはflexboxの例と同じように、親要素である「container」というクラスのついた＜div＞タグの中に、子要素である「item」というクラスのついた＜div＞タグを6つ作ります。この中に画像を入れていきます。
※imgの大きさ400px×250pxに設定しています。

```HTML:HTML
    <div class="container">
        <div class="item">
            <img src="img/coffee.jpg" alt="">
        </div>
        <div class="item">
            <img src="img/latte.jpg" alt="">
        </div>
        <div class="item">
            <img src="img/cocoa.jpg" alt="">
        </div>
        <div class="item">
            <img src="img/tea.jpg" alt="">
        </div>
        <div class="item">
            <img src="img/milk.jpg" alt="">
        </div>
        <div class="item">
            <img src="img/juice.jpg" alt="">
        </div>
    </div>
```

```css:CSS
.container{
    display: grid;
}
```
.containerクラスに対してdisplay: grid;を追加します。この時点ではグリッドアイテムは縦に並んでいるだけです。

![GIF 2020-04-29 16-08-27.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562982/e06c9fee-026f-04a8-5884-9f01c5043664.gif)


####グリッドアイテム(子要素)の横幅「grid-template-columns」
**grid-template-columns**プロパティで各グリッドアイテムの幅を指定することで、**横並び**に設定できます。1列にグリッドアイテムが複数必要な場合は、半角スペースで区切って必要なグリッドアイテムの数だけ幅を指定します。
例えば、１列に3つのグリッドアイテムを各400pxずつ並べる場合は「400px 400px 400px」と指定します。

```css:CSS(横幅400px)
.container{
    display: grid;
    grid-template-columns: 400px 400px 400px;
}
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562982/2b0a8322-f075-5a4e-5440-5110e5259905.png)

グリッドアイテムが1列に3つずつ横並びになりました。
ただ今回のように、アイテムの大きさが決まっている際は、後で紹介する単位「fr」を使うことをお勧めします。

####グリッドアイテム(子要素)同士の余白「gap」
ここでは、グリッドアイテムの間に余白を付けましょう。gapプロパティで余白の幅を指定します。例では、gapを20pxに指定してみます。上下左右の端は親要素であるグリットコンテナーの枠に揃います。

```css:CSS(gap,20px)
.container{
    display: grid;
    grid-template-columns: 400px 400px 400px;
    gap: 20px;
}
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562982/2b46d7a7-266b-e6eb-e477-6b60096838c5.png)

グリッドアイテム同士の間に20pxの余白が付きました。

####CSSグリッドで使える単位「fr」
CSSグリットで使える単位**「fr」**を使ってみます。
親要素から見た子要素の大きさを割合で指定でき、画面の幅に合わせて自動で縮小できます。grid-template-columnsプロパティの指定方法は、gapプロパティと変わりません。値を「1fr 1fr 1fr」とすることで、1:1:1の割合で、グリッドアイテムを表示できます。

```css:CSS(fr使用例)
.container{
    display: grid;
    grid-template-columns: 1fr 1fr 1fr;
    gap: 20px;
}
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562982/76892e90-64d2-6ab6-a2e0-d578086a9314.png)
「px」で幅を指定するとその幅で固定されるので、「fr」を使うと便利です:relaxed:

####グリッドアイテム(子要素)の高さ「grid-template-row」
今回はアイテムの高さが決まっているので使用していませんが、グリッドアイテムの高さはgrid-template-rowプロパティで指定することができます。
列が複数ある場合は、半角スペースで区切って、必要な行の数だけ1行ごとに指定していきます。
例えば2行とも200pxにしたい場合は以下のように記述します。

```css:CSS(高さを指定)
.container{
    display: grid;
    grid-template-columns: 1fr 1fr 1fr;
    gap: 20px;
    grid-template-rows: 200px 200px;
}
```

#参考文献
Mana著、「1冊ですべて身につくHTML＆CSSとWebデザイン入門講座」、SBクリエイティブ株式会社、2019年