ブロック要素の幅を内側のテキストの幅にする
◆ width: fit-content;
div などのブロック要素は自動で親のサイズの 100% の幅になります
下線や背景色など 見た目の都合で 端から端までではなく内側にあるテキストの幅までにしたいことがあります
内側に合わせたいなら単純に inline-block にすればいいです
しかし inline になるので横に要素が入ってくる可能性があります
例えば h1 などの見出しだと横に本文が入ってくると困ります
HTML 構造を変えられるのなら h1 を div でラップすれば h1 の横には他の要素は入ってきません
しかし HTML 構造が変えられないケースもあり そういうときはあまりスッキリとしない回避策に頼るしかありませんでした
古い方法だと inline のように振る舞って左右に要素が来ない display: table を設定するものです
display に table みたいな一部タグ専用みたいなものを指定するのはあまりやりたくないです
それも本来のそのタグをエミューレートする目的でもないところでです
もう少し新しい方法だと display: flex です
親を flex box にして h1 などを flex item にします
縦に並べて align-items: flex-start にすれば h1 の幅は h1 内のテキスト分になります
しかしこれだと
みたいなケースで問題が出ます
b タグは inline で単に太文字にしたいだけなのに flex item になっていることで foo, bar, baz が縦に並んで 3 行になります
これらが p タグで囲まれて
になってれば問題ありませんが この構造なら p タグがブロック要素なので何もしなくても h1 の隣には来ません
見たことないものでしたが名前的に便利そうな予感がします
どういう動きになるのか試してみると 上で書いた問題を解決できるものでした
content つまり要素の中身のサイズに fit してくれます
上の例で h1 タグの中のテキスト分の width になります
似たようなものに max-content というのもありますが こっちは親のサイズを気にせず内側の要素のサイズになります
テキストが長くて 2000px 分あれば h1 の width は 2000px ということです
親の要素のエリアからはみ出しますね
fit-content だと親サイズを超えないようになっています
比較用
下線や背景色など 見た目の都合で 端から端までではなく内側にあるテキストの幅までにしたいことがあります
内側に合わせたいなら単純に inline-block にすればいいです
しかし inline になるので横に要素が入ってくる可能性があります
例えば h1 などの見出しだと横に本文が入ってくると困ります
<!doctype html>
<style>
h1 { display: inline-block; background: #ffe1ea; }
</style>
<div>
<h1>h1</h1>
text
</div>
HTML 構造を変えられるのなら h1 を div でラップすれば h1 の横には他の要素は入ってきません
<!doctype html>
<style>
h1 { display: inline-block; background: #ffe1ea; }
</style>
<div>
<div><h1>h1</h1></div>
text
</div>
しかし HTML 構造が変えられないケースもあり そういうときはあまりスッキリとしない回避策に頼るしかありませんでした
古い方法だと inline のように振る舞って左右に要素が来ない display: table を設定するものです
<!doctype html>
<style>
h1 { display: table; background: #ffe1ea; }
</style>
<div>
<h1>h1</h1>
text
</div>
display に table みたいな一部タグ専用みたいなものを指定するのはあまりやりたくないです
それも本来のそのタグをエミューレートする目的でもないところでです
もう少し新しい方法だと display: flex です
親を flex box にして h1 などを flex item にします
縦に並べて align-items: flex-start にすれば h1 の幅は h1 内のテキスト分になります
<!doctype html>
<style>
h1 { background: #ffe1ea; }
.flex-column { display: flex; flex-direction: column; align-items: flex-start; }
</style>
<div class="flex-column">
<h1>h1</h1>
text
</div>
しかしこれだと
<!doctype html>
<style>
h1 { background: #ffe1ea; }
.flex-column { display: flex; flex-direction: column; align-items: flex-start; }
</style>
<div class="flex-column">
<h1>h1</h1>
foo <b>bar</b> baz
</div>
みたいなケースで問題が出ます
b タグは inline で単に太文字にしたいだけなのに flex item になっていることで foo, bar, baz が縦に並んで 3 行になります
これらが p タグで囲まれて
<!doctype html>
<style>
h1 { background: #ffe1ea; }
.flex-column { display: flex; flex-direction: column; align-items: flex-start; }
</style>
<div class="flex-column">
<h1>h1</h1>
<p>foo <b>bar</b> baz</p>
</div>
になってれば問題ありませんが この構造なら p タグがブロック要素なので何もしなくても h1 の隣には来ません
fit-content
良い解決策がないものとして諦めてましたが fit-content というものを width に指定しているページを見かけました見たことないものでしたが名前的に便利そうな予感がします
どういう動きになるのか試してみると 上で書いた問題を解決できるものでした
content つまり要素の中身のサイズに fit してくれます
上の例で h1 タグの中のテキスト分の width になります
<!doctype html>
<style>
h1 { width: fit-content; background: #ffe1ea; }
</style>
<div>
<h1>h1</h1>
foo <b>bar</b> baz
</div>
似たようなものに max-content というのもありますが こっちは親のサイズを気にせず内側の要素のサイズになります
テキストが長くて 2000px 分あれば h1 の width は 2000px ということです
親の要素のエリアからはみ出しますね
fit-content だと親サイズを超えないようになっています
比較用
<!doctype html>
<meta charset="utf-8"/>
<style>
.box { width: 200px; border: 1px solid skyblue; }
input:checked ~ .box { width: 600px; }
input:checked ~ .hide-checked { display: none; }
input:not(:checked) ~ .hide-unchecked { display: none; }
h2 { background: #ffe1ea; }
.max { width: max-content; }
.fit { width: fit-content; }
</style>
<input type="checkbox"/> ←チェックで親 div の width 切り替え
<div class="hide-checked">width: 200px</div>
<div class="hide-unchecked">width: 600px</div>
<h1>max-content</h1>
<div class="box">
<h2 class="max">テキストテキストテキストテキスト</h2>
foo <b>bar</b> baz
</div>
<hr/>
<h1>fit-content</h1>
<div class="box">
<h2 class="fit">テキストテキストテキストテキスト</h2>
foo <b>bar</b> baz
</div>