【社内勉強会】CSSの基礎(ボックス) (2017/06/07)



# 0.はじめに

------------------
## 対象者
* CSS初心者


### 前提知識

* 前回の勉強会スライド「[CSSの基礎](http://qiita.com/yuji38kwmt/items/bdb72a92542b38007b70)」 を読んだ人

* 簡単なJavaScript


------------------
## 伝えたいこと
* displayプロパティとボックスの関係
* flexbox

------------------
## 参考図書

[演習で力がつく HTML/CSSコーディングの教科書](https://www.amazon.co.jp/%E6%BC%94%E7%BF%92%E3%81%A7%E5%8A%9B%E3%81%8C%E3%81%A4%E3%81%8F-HTML-CSS%E3%82%B3%E3%83%BC%E3%83%87%E3%82%A3%E3%83%B3%E3%82%B0%E3%81%AE%E6%95%99%E7%A7%91%E6%9B%B8-%E7%A3%AF%E5%8D%9A/dp/4797382082)

![参考図書.jpg](https://qiita-image-store.s3.amazonaws.com/0/37903/7b645d6c-d738-65fb-c901-46bbacafdad4.jpeg)


------------------
## 目次

1. displayプロパティ
2. ボックスモデル

------------------
# 1. displayプロパティ

------------------
## displayプロパティとボックスの種類

HTMLのどの要素にも、「ボックス」という四角形の領域が存在する。
displayプロパティの値によりボックスの種類が決まる。

以下、主なボックスの種類。

* ブロックボックス(`display:block;`)
    - 横いっぱいに広がる
    - 上から下へ縦方向に配置される（改行される）
* インラインボックス(`display:inline;`)
    - 左から右へ横方向に配置される
    - 折り返して表示される 
* 分割不可能なインラインレベルボックス(`display: inline-block;`)
    - インライボックスと同様に左から右へ横方向に配置される
    - 複数の行に分割されない

------------------
## displayプロパティの初期値は各要素で決まる

おもなdisplayプロパティの値とボックスの種類(参考図書 p133 引用)

| display値 | ボックスの種類 | 主な要素 |
|:-----------|:------------|:------------|
| block       | ブロックボックス        | div, form, h1~h5, p|
| inline(非置換インライン要素)     | インラインボックス      | a, em, label, span, strong      |
| inline(置換要素)       | 分割不可能なインラインレベルボックス       |iframe, img, video|
|inline-block|分割不可能なインラインレベルボックス|button, input, select, textarea         |


>HTML では、display プロパティのデフォルト値は、HTML 仕様に記述されたふるまいか、ブラウザー/ユーザーのデフォルトのスタイルシートに記述されたふるまいから採られます。

[MDN displayプロパティ](https://developer.mozilla.org/ja/docs/Web/CSS/display) より引用
[CSS default property](https://www.w3schools.com/cssref/css_default_values.asp)
[Appendix D. Default style sheet for HTML 4](https://www.w3.org/TR/CSS2/sample.html)

------------------
### [補足] 置換要素

>img要素のように、文字列ではない別のものに置き換えれて表示されるインライン要素を置換要素といいます。
 ～
置換要素は、他のインライン要素と異なり、分割されずに1つのかたまりとして行に流し込まれます。

参考図書 p068 引用

主な置換要素は「canvas, iframe, img, input, button, select, textarea 」など。

http://taneppa.net/display-inline-block/ 
http://htmlcss.jp/html/replaced_elements.html
http://www.w3.org/TR/html5/rendering.html#replaced-elements


------------------
## [Try] ボックスの種類を確認

[JSFiddle](https://jsfiddle.net/yuji38kwmt/6qhqh0hj/) で動作確認

* ブロックボックス
    - 改行されている
* インラインボックス
    - 分割されている
* 分割不可能なインラインレベルボックス
    - 分割されていない

```html
<h4>display:block;</h4>
<p>
寿限<span>無寿限無</span><span>五劫</span>の
</p>
<h4>display:inline;</h4>
<p>
寿限<span>無寿限無</span><span>五劫</span>の
</p>
<h4>display:inline-block;</h4>
<p>
寿限<span>無寿限無</span><span>五劫</span>の
</p>
```

```css
p {
  width:50px;
  border:solid 2px blue;
}
span {
  border: solid 1px red;
}
p:nth-of-type(1) > span {
  display:block;
}
p:nth-of-type(2) > span {
  display:inline;
}
p:nth-of-type(3) > span {
  display:inline-block;
}
```


------------------
## CSS displayプロパティの考え方まとめ

![displayプロパティのまとめ.png](https://qiita-image-store.s3.amazonaws.com/0/37903/4697c6f4-6996-36a0-0d3d-31f6b2022cbf.png)

[イメージで学ぶ！CSSのdisplayの使い方を総まとめ](https://saruwakakun.com/html-css/basic/display#section4) より引用


------------------
## 幅、高さ、余白の指定

### 幅、高さ
* `inline`ではwidth, heightが指定できない。文字の長さや大きさできまる。
* `block, inline-block`では、width, heightが指定できる。

### 余白
* `block, inline-block`では、上下左右のmargin, paddingが指定できる。
* `inline`では、上下マージンは指定できない。

### 位置揃え
* `block`では、text-align, vertical-alignを指定できない。


------------------
## JavaScriptでdisplayプロパティを参照

`element.style`はstyle属性で指定された値を取得する。
`window.getComputedStyle`を使用すれば、実際のCSSプロパティが取得できる。

```html
<input id="sample">
```

```js
let elm = document.getElementById("sample");
console.log(elm.style.display); // ⇒ ""
console.log(window.getComputedStyle(elm).display); // ⇒ "inline-block"
console.log($(elm).css("display")); // ⇒ "inline-block"
```

[JSFiddle](https://jsfiddle.net/yuji38kwmt/qvo63en4/) で動作確認。


------------------
## JavaScriptで表示/非表示切り替える

```js
let elm = document.getElementById("sample");
elm.style.display = "none"; //非表示
elm.style.display = ""; //表示
$(elm).hide(); //非表示
$(elm).show(); //表示
```


* 【注意】非表示から表示に戻す際、`elm.style.display="block";`のように具体的なdisplay値を指定しないこと。戻すべき値がその値とは限らない。


------------------
# ボックスモデル

------------------
## ボックスモデルの図

![ボックスモデル.png](https://qiita-image-store.s3.amazonaws.com/0/37903/d683297f-d2b3-8dc0-2c9d-edd1094f607d.png)

[今更聞けない！エンジニアのための CSS の基礎講座](https://nulab-inc.com/ja/blog/nulab/css-basics-for-engineer-boxmodel/) より引用

* width, heightはpadding,border領域を含まない。
* `box-sizing: border-box;`を指定すると、width, heightはborder,padding領域を含む。（後述)

https://developer.mozilla.org/ja/docs/Web/CSS/box-sizing
https://developer.mozilla.org/ja/docs/Web/CSS/box_model


------------------
## [補足] border-boxのメリット

* paddingやborderの変更によるレイアウト崩れを防ぐ。
http://phiary.me/css3-box-sizing/
https://saruwakakun.com/html-css/reference/box-sizing

* Bootstrap3では全ての要素をborder-boxにしている。

```css:bootstrap.css
* { box-sizing: border-box; }
```

>Better box model by default. Everything in Bootstrap gets box-sizing: border-box, making for easier sizing options and an enhanced grid system.

[The Bootstrap Blog](http://blog.getbootstrap.com/2013/08/19/bootstrap-3-released/) より引用



------------------
## widthプロパティ

* 初期値は`auto`
* 長さ、パーセント値で指定できる。
* パーセント値は、親要素の幅に対する比率。
* `width:auto;`の場合は、マージンまで含めたボックスの幅が親要素の幅となるように、幅が自動的に決まる。 ボックスの幅は、**外側から内側へ**と順に決まる。一番外側のボックスはWebページの表示領域(ブラウザのサイズ)。
* widthが指定されて、margin-left, margin-rightがautoの場合は、中央寄せになる。


https://saruwakakun.com/html-css/basic/width-height 参考


```html
<div class="parent">
  <div>a</div>
  <div style="margin-left:20px; margin-right:50px;">b</div>
  <div style="width:50px; margin-left:auto; margin-right:auto;">c</div>
</div>
```

```css
.parent {
  width: 100px;
  border: solid 1px black;
}
.parent > div {
  border: solid 1px red;
}
```

[JSFiddle](https://jsfiddle.net/yuji38kwmt/1jdqytx0/) で動作確認。



------------------
## heightプロパティ


* 初期値は`auto`
* 長さ、パーセント値で指定できる。
* パーセント値は、親要素の高さに対する比率。
* `height:auto;`の場合は、ボックスの高さは要素内容がピッタリとおさまるように自動的に設定される。ボックスの高さは、**内側から外側へ**と順に決まる。
* heightが指定されていて、ボックスにおさまりきらない場合は、オーバフローする。この状態の表示方法を`overflow`プロパティで指定できる。



------------------
## max-width, min-width, max-height, min-heightの使いどころ

* レスポンシブデザイン(スマホ用)

>
widthを%で指定したときに、min-widthはセットで使うと便利です。たとえばwidth:50%のとき、ウェブページを見る端末（ブラウザ）のサイズによって要素が小さくすぎたり、大きすぎたりするわけです。

[サルワカ 【CSS】便利なmax-widthとmin-widthの使い方まとめ](https://saruwakakun.com/html-css/basic/max-min-width) 引用

* ある領域内で画像の縦横比を保つ。max-width, max-heightを使用。

```html
<div class="wrapper">
  <img src="sample.jpg">
</div>
```

```css
.wrapper {
  width: 100px;
  height: 100px;
  border: solid 1px black;
}

img {
  max-width: 100%;
  max-height: 100px;
}
```



-------------------
# フレックスボックス


-------------------
## フレックスボックスとは？

* 柔軟なボックス。
* `display:flex;`を指定されたボックスは、ボックスの配置を縦横いずれの方向にも配置できる。また、適切に伸縮させてピッタリおさめることができる。
* IE11以上なら利用可能（[Can I use](https://caniuse.com/#search=flex)参照）


[CSS3 Flexbox の各プロパティの使い方をヴィジュアルで詳しく解説](http://coliss.com/articles/build-websites/operation/css/css3-flexbox-properties-by-scotch.html) 参考


[Flexbox Playground（フレックスボックスを試せる)](https://demos.scotch.io/visual-guide-to-css3-flexbox-flexbox-playground/demos/) 



### floatプロパティ
フレックスボックスができるまでは、横並びにする際floatプロパティが使われていた。

以下、floatプロパティのデメリット

* 毎度解除しなきゃいけない
* 解除の方法が多様すぎる。人によってやり方に差がありすぎる。
* vertical-align使えない
* 高さが違うと一気に崩れる

[最近float使わなくなってきた](http://mugiyuki.hatenablog.jp/entry/2015/08/07/143725) より引用。


-------------------
## フレックスボックスのサンプル

書式 "flex: 伸び率 縮み率 基本幅"




```html
<div id="parent">
  <div id="first">a</div>
  <div id="second">b</div>
  <div id="third">c</div>
</div>
```

```css
div {
  height:100px;
}
#parent {
  width: 200px;
  border: solid 1px black;
  display: flex;
}
#parent > div{
  border: solid 1px red;
}
#first {
  width:50px;
}
#second {
  flex:2 1 50px;
}
#third {
  flex:1 1 50px;
}

```

[JSFiddle](https://jsfiddle.net/yuji38kwmt/2gya8fuj/) で動作確認。


-------------------
## フレックスボックスで縦横中央寄せ

justify-content, align-contentプロパティを使用。


```html
<div id="parent">
  <div id="child">

  </div>
</div>

```

```css
#parent {
  width: 100px;
  height: 100px;
  border: solid 1px black;
  display: flex;
  justify-content: center;
  align-items: center;
}

#child {
  width: 50px;
  height: 50px;
  border: solid 1px red;
}

```

[JSFiddle](https://jsfiddle.net/yuji38kwmt/yt37ud1n/) より引用。
[CSS3 Flexboxを使った史上最短の上下中央揃え2016年版](http://qiita.com/tonkotsuboy_com/items/a5aaa4a69fecfaf546a3) 参考。



------------------
# 付録

------------------
## 知っておいて欲しい用語、機能

* ベンダープレフィックス
* calc関数：数値の計算。`width: calc(100% - 80px)`のように異なる単位での計算も可能。
https://developer.mozilla.org/ja/docs/Web/CSS/calc

* マージンの相殺。上下に隣り合うブロックボックスのマージンは、相殺されて**大きい方**が採用される。
https://developer.mozilla.org/ja/docs/Web/CSS/CSS_Box_Model/Mastering_margin_collapsing

* メディアクエリ。デバイスの状態を判定できる。
https://developer.mozilla.org/ja/docs/Web/Guide/CSS/Media_queries

------------------
## まだ話せていないこと

* table関係
* form関係