CSS  での横幅 (width) 、高さ (height) の指定にキーワード値を使う

CSS で要素の大きさを指定するとき、 `px`, `%`, ... `vw` 以外にも使えるものがたくさんあって、
その要素の内容に応じて幅を伸縮させたりできる。
そのうちのひとつ、 `max-content` を使ってみたら試行錯誤していたものをあっさり解決できたので書いておく。


# width プロパティに指定できるキーワード値
- border-box
- content-box
- max-content
- min-content
- available / fill
- fit-content
- auto

`auto` 以外の値は `width` プロパティで見たことがなかった、というかまだ草案段階らしい。
https://developer.mozilla.org/en-US/docs/Web/CSS/width

これらは `height` や `max-width`, `min-width` でも使えるとのこと。
本記事は `width` を例に進める。


## border-box / content-box
`width: 100px border-box;`
`width: 50% content-box;`
のように指定する。
おそらく、横幅の指定と `box-sizing` の指定をまとめてできるのだと思う。
これも良さそうな指定方法だけど、本記事では割愛する。


## max-content
要素の内容に応じて幅を伸縮させる。
例えば `<p>` タグで、内包するテキストがどれだけ長くなってもそれに合わせてくれる。


## min-content
要素の内容に応じてできるだけ最小値にしてくれる。
最小とはいっても `0px` というわけではなく内包するコンテンツを収められる最小幅にしてくれる。


## available / fill
MDN では `available` という名前だけど、 W3C 的には `fill` という名前になるのかもしれない。
本記事では念のために併記する。
この値を指定した要素の親要素のコンテンツエリアに収まる幅にしてくれる。
つまり、親要素の幅から `padding` とかを引いた値。 (`box-sizing` プロパティに `border-box` を指定してる場合は `border-width` も引く)


## fit-content
`max-content` みたいに内容に応じて伸縮するけど、available / fill の値が上限。
自動的に伸縮させたいけど親要素からはみ出てほしくないときに使えそう。


# これらは何が良いのか
`width: 100%;` ではダメなのか、とか
インライン要素にすれば良いのでは、とか...

でも実際に使ってみると結構便利で、
従来の方法では微妙に手が届かないところに届くようになるし、あるいはトリッキーな技を使わなくてもよくなるかもしれない。
可読性アップにもなりそう。


# 使ってみる
実際に試してみる。
大して変わらないとは思うけど、
要素の中に入れるものがフレージングコンテンツとフローコンテンツとでどのような表示になるか試してみる。


## フレージングコンテンツ
まずはフレージングコンテンツから。
HTML の構造は次の通りで、
`<p>` タグの `width` プロパティにキーワード値を指定していく。

```
<div>
    <p>テキスト</p>
</div>
```

`<div>` タグに赤い枠線をつけ、
`<p>` タグに青い枠線をつけた。

### auto
<img width="465" src="https://qiita-image-store.s3.amazonaws.com/0/125508/be3d3160-7462-2332-02c8-a61e18400483.png">

比較のため、 `auto` を指定したときの表示も載せる。


### max-content
<img width="463" src="https://qiita-image-store.s3.amazonaws.com/0/125508/778dc4c0-c4a0-2cbb-bdaa-6b6006f7f740.png">

内包するテキストの長さの分だけ横幅が伸びている。


### min-content
<img width="465" src="https://qiita-image-store.s3.amazonaws.com/0/125508/766aae4f-5db7-a175-b2f6-de5d6a23704a.png">

このように、できるだけ小さい幅をとるようになっている。
このとき、この文章中で最も長い単語は Northumberland で、
表示のされ方からしてこれが基準になっていると考えられる。


<img width="464" src="https://qiita-image-store.s3.amazonaws.com/0/125508/f558bcdb-ca76-81d0-5a44-6c92055efb4b.png">

文章からこの単語だけを削除してみると、横幅は先ほどよりも短くなった。

<img width="465" src="https://qiita-image-store.s3.amazonaws.com/0/125508/eb925ca6-1aed-4dad-1dfc-31c791a57b03.png">


### available / fill
<img width="464" src="https://qiita-image-store.s3.amazonaws.com/0/125508/f76605f8-07d3-41e0-0cae-af9a1d4a27e8.png">

もっと短い文で確認してみる。

<img width="463" src="https://qiita-image-store.s3.amazonaws.com/0/125508/fe3fcd02-c038-a18e-e8ca-913ca15cd3e0.png">

次に、もう少し長い文にしてみる。

<img width="464" src="https://qiita-image-store.s3.amazonaws.com/0/125508/672747f2-6f3b-b821-7e29-7ff3fec76581.png">


### fit-content
<img width="465" src="https://qiita-image-store.s3.amazonaws.com/0/125508/b5fa4791-9501-684b-53ff-3e502406f0a6.png">

もっと短い文で確認してみる。

<img width="464" src="https://qiita-image-store.s3.amazonaws.com/0/125508/a74d4c59-667d-ce9a-7e5c-b5a23dfd56f3.png">

max-content のように内容に応じた横幅になった。
次に、もう少し長い文にしてみる。

<img width="464" src="https://qiita-image-store.s3.amazonaws.com/0/125508/58bc11c5-9177-541a-9dd9-3f608104c261.png">

このように、伸縮する横幅は available / fill で設定される値を上限とし、それを超えない。


## フローコンテンツ
次にフローコンテンツで試してみる。
HTML の構造は次の通りで、
`<ul>` タグの `width` プロパティにキーワード値を指定していく。

```
<div>
    <ul>
        <li>List Item 1</li>
        <li>List Item 2</li>
        <li>List Item 3</li>
        <li>List Item 4</li>
        <li>List Item 5</li>
        <li>List Item 6</li>
    </ul>
</div>
```

`<div>` タグに赤い枠線をつけ、
`<ul>` タグに青い枠線をつけ、
`<li>` タグに緑色の背景色をつけた。


基本的にはフレージングコンテンツの場合と特に変わらない表示。


### auto
<img width="465" src="https://qiita-image-store.s3.amazonaws.com/0/125508/580d3999-6cf1-ae42-09aa-4651a600462c.png">


### max-content
<img width="464" src="https://qiita-image-store.s3.amazonaws.com/0/125508/9951be82-099c-21ed-ae5b-9f7d270c7ae0.png">

リストアイテムの内容に応じた横幅になっている。


### min-content
<img width="465" src="https://qiita-image-store.s3.amazonaws.com/0/125508/d41eb0bb-85d9-bf5c-d384-e2497f173819.png">

リストアイテムの内容を収められる最低限の横幅になっている。


### available / fill
<img width="464" src="https://qiita-image-store.s3.amazonaws.com/0/125508/c3597697-ae93-da48-2ebe-a77e1e5412a3.png">


### fit-content
<img width="465" src="https://qiita-image-store.s3.amazonaws.com/0/125508/88ee1734-6552-b6d1-bfc3-1d85bf6b24d4.png">


## フローコンテンツを横に並べる
`<li>` タグに `display: inline-block;` を指定して横に並べてみる。


### auto
<img width="465" src="https://qiita-image-store.s3.amazonaws.com/0/125508/9c81bd73-18d7-71f4-90d7-518ecd1d8c5e.png">


### max-content
<img width="465" src="https://qiita-image-store.s3.amazonaws.com/0/125508/6aca7453-e0c8-4ac3-9658-48d305272619.png">

リストアイテムの分だけ横幅が伸縮する。


### min-content
<img width="464" src="https://qiita-image-store.s3.amazonaws.com/0/125508/bbeb3123-cba3-a7fb-64e8-ce74c00ef7aa.png">

`<li>` タグに `display: inline-block;` が指定されてるとはいえ、
親要素 `<ul>` の横幅が小さいので横並びになる余地がない。


### available / fill
<img width="465" src="https://qiita-image-store.s3.amazonaws.com/0/125508/e20815f6-d05b-0b8f-b9e5-4ca1093a4b89.png">


### fit-content
<img width="464" src="https://qiita-image-store.s3.amazonaws.com/0/125508/e16d9dc5-e5b2-5dbf-43af-e0fc5f0d0fa8.png">


###リストアイテムを少なくしたときの available / fill と fit-content
<img width="465" src="https://qiita-image-store.s3.amazonaws.com/0/125508/2c0bf9fb-5071-4ede-2e38-e97cc31d92f6.png">

<img width="465" src="https://qiita-image-store.s3.amazonaws.com/0/125508/00a37465-9b67-ad4f-4d4f-c383c7450543.png">

フレージングコンテンツの場合と同じく、
`fit-content` を指定すると `available / fill` で指定される大きさ以下であれば `max-content` と同様の挙動になる。


# ブラウザ対応状況 (2016/05 時点)
MDN によるとこうなっていて、
<img width="680" src="https://qiita-image-store.s3.amazonaws.com/0/125508/db273548-f4aa-afb6-324f-87a58858c9ef.png">
https://developer.mozilla.org/en-US/docs/Web/CSS/width

「Can I use...」 ではこうなってる
<img width="1269" src="https://qiita-image-store.s3.amazonaws.com/0/125508/e43de52f-da49-929d-b4be-ed8ffe72982a.png">
http://caniuse.com/#search=max-content


実際に使用するには `-webkit-` と `-moz-` のプレフィックスがまだまだ必須。
しかし、IE と Edge はまったく対応していない...ので、SP サイトで使っていきたい。