この記事をおすすめしたい人
- CSSで溢れた要素をスクロールバーで表示したい人
- スクロールバーで表示させたいのにどうしても失敗する人
- つまりオレ
今回はCSSで、中身が幅を超えた場合に折り返したり幅を押し広げたりするのではなく、スクロールバーを表示する方法を考えます。
こういう↓奴ですね。
は?そんなんネットで探したら一瞬で見つかるやろ。
そうなんです!
「CSS 中身が溢れる」とか「CSS スクロールバー」とかで検索すると、ほんとアホみたいな量の記事が出てきます。
ところがですね。
僕はこの問題にぶつかってからかれこれ数年は経とうというのに未だに解決にいたってなくて、いや、今は解決したんですけども。
この問題にぶつかる度にそれはもう毎度毎度調べ直して、実際に動いているサイトのCSSも何度ものぞきました。 日本だけじゃなくて海外サイトも巡りまくって、
ミーはこの書き方でできたぜ?
みたいなのも試しまくった上で、スクロールバーを表示させることができていませんでした。
こんなサイト作ってるのに今まで内緒で折り返していたとか、
お恥ずかしい限りです。
お前がしょぼいだけちゃうん?
と言われるとその通りなのですが、Googleのサジェストワードを見ていると「表示されない」「効かない」とか「溢れる」とか、これだけ文献があるにも関わらず出来ていない人が一定数いることが伺えます。
というわけで、今回は横に長い文章でスクロールバーを表示させたいのに、
どおおおおおおおしてもできひんねん!!クソガ!!
という人のために、どうにかして挙動だけでも無理矢理合わせる方法を考えていきます。
前提としてオレが失敗していたコード
同じ内容を書いてるサイトがいっぱいあるので、今回も長谷川かすみさんを広告に使ってるこのサイトを参考にします。
先に断っておきますが、今からのコードは失敗します。
上記サイトの名誉のために断言しますが、これは上記サイトのコードが間違っているわけではありません。 同じコードで実際にちゃんと機能しているのを何度も確認しています。
なので、正確には「このコードのまま」では「このサイト」で動かないコードです。
実際にこのサイトでコードを書いてみましょう。
一般的に紹介されているコード
必要最小限のこの↓ようなコードで書いてみました。
<div style="overflow-x:scroll;background:#cff;">
<p style="white-space:nowrap; ">ああああ!スクロールバーがでねええええ!助けてええええ!!誰か助けてええええ!!!!</p>
</div>
実際にHTMLで置いておけばよかったんですが、横に溢れるせいで可読性が著しく下がるので画像↓で用意しました。
画像の上半分は幅100%に収まるテキストを表示した場合、下半分は幅100%を越えるテキストを表示した場合です。
画像からも分かる通り、子要素に「white-space: nowrap;」を指定しているせいで、幅を超えたテキストが親要素の幅を無理矢理広げてしまっています。
上記コードを当サイトでも正常動作させる方法
実は上のコードをうちのサイトでも動作させる方法があります。
それは…
幅をピクセル単位かcalc()で指定することです!
実際にHTML↓を置いてみましょう。
ああああ!スクロールバーがでねええええ!助けてええええ!!誰か助けてええええ!!!!
スマホでも溢れないように幅200pxで指定しました。
そうするとちゃんとスクロールバーが出るんですよね。
ですが実際は幅100%に指定したいわけでして、幅を100%指定すると、幅を指定していない場合と同様に親要素の幅を広げてしまいます。
元のサイトでも今回は幅がpx指定されていますが、今まで正常動作確認してきたサンプルでは幅100%指定でもちゃんと動いてました。
幅指定せにゃならんとなるとレスポンシブ対応でめちゃくちゃめんどくせーし、
また今度でいいや。
を数年続けたきた結果が今の…
いや、昨日までのオレです!
今回の解決法は幅を指定しさえすれば解決する人向けの内容なので、これでも溢れている場合はお役に立てないと思います。
今回、成功したコード
幅を指定すれば動くなら、幅を指定すればいいじゃない!
いや、数年放置してたんで、もう数年放置してもよかったんですが、前回の記事で触ったGoogleアナリティクスのReporting APIのクラス名がこんな↓のでして、
$clause = new Google_Service_AnalyticsReporting_DimensionFilterClause();
クラス名、長過ぎやろ!!
となりまして、さすがのオレも本気出すことにしました。
というわけで、overflowをautoじゃなくてscrollにしたり、word-wrapやoverflow-wrapやword-breakを指定したり、サイドバーにmin-widthを明示したりしなくても、幅を指定しさえすれば意図した挙動になるならそっちに労力をさけばいいんです。
このサイトは、
- コンテンツの幅は上限1020pxで、それ以上では左右に余白
- 896~1020pxではサイドバーを表示したまま、記事部分の幅が縮む
- 896px以下ではサイドバーが記事下部へ移動
という構造になっています。
この3段階のブレイクポイントで幅を無理矢理計算させたのがコレ↓です。
@media screen and (min-width:1020px) {
width: calc(1020px - 40px - 32px - 330px);
}
@media screen and (min-width:897px) and ( max-width:1019px) {
width: calc(100vw - 40px - 32px - 330px);
}
@media screen and (max-width: 896px) {
width: calc(100vw - 20px);
}
あ、ブレイクポイントの境界はテキトーですからね。
各段階での幅を、px単位またはvw単位で指定して、そこからサイドバーの幅や各種マージンやパディングを引いたものになります。
ハードコードで書いてますが、数値を変更した時用にSASS/SCSSの変数を使って各値は定義してる方がいいと思います。
それはまた数年後くらいにやる予定です。
大事なのは溢れさせないことなので(特にスマホ)、
あれ、ここ、box-sizingどうしてたっけな…。
とかなったら倍量引いとけばいいです。 溢れるよりはマシ。
まとめ
CSSで溢れた要素のためにスクロールバーを表示させたいのに、どおおおおおうしても失敗する人は
calc()を使って幅を指定してみてください!
僕のコードの書き方では、このやり方でうまくいきました。
え、それでもうまくいかなかったって?
それはオマエがオマエDEV.comで解説記事を書くんだよ!
以上、WordPressからお届けしました!