スクロールすると背景が途切れる!!!
この記事はCSSに関する知識記事なので、いきなりタイトル回収します。次のコードで説明します。
See the Pen Untitled by tomolatoon (@tomolatoon) on CodePen.
ローカルで試したい人は下のコードを見てください。
スクロールすると背景が途切れてしまうHTMLとCSS
<!DOCTYPE HTML>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>ダメな例</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<code class="codeblock">
<ol class="lines">
<li class="line">'use strict';</li>
<li class="line"> </li>
<li class="line">// 幅を狭くしてスクロールしてみてください</li>
<li class="line">`長くて枠をはみ出る文字列。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。`</li>
</ol>
</code>
</body>
</html>
html {
width: 100%;
height: 100%;
margin: 0;
border: 0;
font-size: 14px;
}
body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
.codeblock {
box-sizing: border-box;
width: 100%;
margin: 0;
padding: 1rem;
border-radius: 0.3rem;
background-color: rgb(233, 233, 233);
display: flex;
flex-direction: column;
overflow-x: auto;
}
.lines {
box-sizing: border-box;
width: 100%;
margin: 0;
padding: 0;
padding-left: 35px;
line-height: 1.5;
}
.line {
width: 100%;
margin: 0;
padding: 0;
white-space: pre;
}
.line:nth-of-type(even) {
background-color: rgb(255, 255, 255);
}
症状
もうお分かりかと思いますが、li
タグに書いてある文章が長くてオーバーフローした時、スクロールするとあった筈の背景色が途中で途切れてしまっています。これ、AtCoder社もやらかしていたりする(2022/2/4現在)のですが、少しCSSを追加すると直すことが出来ます。
原因と間違った解決策
もう見た目から自明なんですが、li
タグの中身がオーバーフローしているのに、li
タグへのスタイルはwidth: 100%;
であるがゆえに適切な横幅を確保できていないのが原因です。
じゃあwidth: max-content;
とかにすればいいじゃんと思う人もいるかもしれませんが、それだとli
タグの中身が少ない時にwidth: 100%;
の場合よりも小さくなってしまいます。要するに行ごとの長さが揃って見えなくなります。
解決策
じゃあどうすればいいのかと言うと、li
タグのwidth: 100%;
を維持したまま、その親要素であるol
タグにwidth: 100%; min-width: max-content;
を適用します。ポイントは親要素にはwidth
とmin-width
を両方使うことですね。
ol
タグはどうなるかというと
こうすると、ol
タグは子要素の幅のうち最大の幅をもつ子要素以上の大きさを持つことになります。かつol
タグの親要素と同じ幅を持つので、画面サイズが大きくても小さくてもいい感じに背景部分が埋まるのがわかると思います。
li
タグたちはどうなるかというと
一方、ol
タグの子要素であるli
タグたちの方はwidth: 100%;
なので、ol
タグと幅を揃えることになり、結果として兄弟関係にあるol
タグのうち最大の幅を持つものに揃うわけなんですね。
結論のコード
結論のコードも貼っておきます。お好きな方をご利用ください。
See the Pen Untitled by tomolatoon (@tomolatoon) on CodePen.
解決したHTMLとCSS
<!DOCTYPE HTML>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>解決例</title>
<link rel="stylesheet" href="correct.css">
</head>
<body>
<code class="codeblock">
<ol class="lines">
<li class="line">'use strict';</li>
<li class="line"> </li>
<li class="line">// 幅を狭くしてスクロールしてみてください</li>
<li class="line">`長くて枠をはみ出る文字列。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。`</li>
</ol>
</code>
</body>
</html>
html {
width: 100%;
height: 100%;
margin: 0;
border: 0;
font-size: 14px;
}
body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
.codeblock {
box-sizing: border-box;
width: 100%;
margin: 0;
padding: 1rem;
border-radius: 0.3rem;
background-color: rgb(233, 233, 233);
display: flex;
flex-direction: column;
overflow-x: auto;
}
.lines {
box-sizing: border-box;
width: 100%;
min-width: max-content;
margin: 0;
padding: 0;
padding-left: 35px;
line-height: 1.5;
}
.line {
width: 100%;
margin: 0;
padding: 0;
white-space: pre;
}
.line:nth-of-type(even) {
background-color: rgb(255, 255, 255);
}
あとがき
やっぱりCSSってパズル的な要素が強いですよね。コードブロックの実装を知りたい人や、背景が途切れてしまって解決策を知りたい人の助けになれば幸いです。(背景って書いちゃったけど、これ背景って言っていいのかな…)