Web制作をしていると、一度はハマるバグがあります。
「Slickを入れたら、なぜか要素の幅が 15000px になっている」
原因が分からないと何時間でも溶けるタイプのやつです。しかも答えが分かると「たったこれだけ?」と拍子抜けします。今回はその原因と、min-width: 0 で一撃解決する仕組みまで整理しておきます。
目次
こんな状況でした。
right: 20px; にしても表示されないDevToolsで見た幅がこちら。
.index-interview__list {
width: 15000px; /* ← なぜ?? */
}
「なんで15000px?」——ここで完全に手が止まりました。
矢印が見えないので、真っ先に疑ったのは位置指定です。Slickの初期CSSでは矢印が枠外に飛び出していることがあります。
.slick-next {
right: -25px; /* 枠の外に出ている */
}
そこで、いったん内側に引き戻してみました。
.slick-next {
right: 20px;
}
しかし、まったく変わらない。
つまり原因は「矢印の位置」ではない、ということが分かりました。矢印が見えないのは結果であって、本当の問題はもっと手前にあります。
Elementsパネルで、Slickが生成した構造を上から追っていきます。
.index-interview__list ← 自分で用意した要素
└ .slick-list
└ .slick-track ← Slickが自動生成
すると、内側の .slick-track がこうなっていました。
.slick-track {
width: 15000px;
}
そして、その巨大な幅に引きずられて、外側の .index-interview__list まで15000pxに広がっていたのです。矢印が見えなかったのは、要素が画面外まで伸びきっていたからでした。
このセクションの構造はFlexレイアウトでした。
.index-interview {
display: flex;
}
.index-interview__list {
flex: 1; /* 右側を伸ばしたい */
}
一見ふつうです。ですが、ここに落とし穴があります。
Flexアイテムの min-width は、初期値が auto です。
min-width: auto は「中身(コンテンツ)より小さくならない」という意味を持ちます。つまりFlexアイテムは、中身が大きければ、その中身に合わせてどこまでも広がってしまうのです。
Slickはスライドを横一列に並べるため、全スライドを1本の長いレール(.slick-track)の上に配置します。スライド枚数や設定によっては、この幅が平気で数千〜数万pxになります。
.slick-track {
width: 15000px;
}
ここでFlexboxの min-width: auto が牙をむきます。
中身(
.slick-track)が15000px必要なんだな → じゃあこの子要素も15000pxまで広げよう
こうして .index-interview__list 自体が15000pxに膨張してしまう、というわけです。
対策はこれだけです。
.index-interview__list {
flex: 1;
min-width: 0;
}
min-width: 0 を指定して初期値の auto を上書きすれば、中身が巨大でも要素側が引きずられなくなります。
必要に応じて、はみ出したトラックを隠すために overflow: hidden を足すと安定します。
.index-interview__list {
flex: 1;
min-width: 0;
overflow: hidden; /* 巨大なtrackがはみ出すのを内側でクリップ */
}
なお width: 0; を追加する例も見かけますが、flex: 1(= flex-basis: 0%)を指定している場合はすでに幅の基準が0扱いなので、基本は min-width: 0 だけで直ります。効かないときに overflow: hidden を足す、くらいの温度感で十分です。
仕組みはシンプルです。
min-width: auto → 中身より小さくなれない(=中身に合わせて伸びる)
min-width: 0 → 中身より小さくなってOK(=親の幅に収まる)
auto から 0 に変えることで、こういう関係が成立します。
親(Flexアイテム) 700px
.slick-track 15000px
トラックが15000pxあっても、外側の要素は親の700pxにきちんと収まり、はみ出した部分はSlickの中でスライドとして扱われる——だから矢印もちゃんと表示される、という流れです。
ちなみに、flex-direction: column(縦並び)で同じ現象が起きたときは、min-width ではなく min-height: 0 が犯人です。方向が変われば効くプロパティも変わる、と覚えておくと迷いません。
この「Flexの子要素が中身に引っ張られて伸びる」問題は、Slick固有ではありません。中身に横長の要素を持つライブラリなら、どれでも起こり得ます。
いずれも、Flexboxの子要素が横に伸びたら、まず min-width: 0 を疑う。これは覚えておくと本当に何度も助けられるテクニックです。
min-width は初期値が auto で、中身より小さくなれない.slick-track を作るため、Flexの子要素がそれに引きずられて伸びるmin-width: 0(必要なら overflow: hidden)を足すだけmin-height: 0「幅がおかしい」「矢印が消えた」ときは、位置指定を疑う前に、まず親のFlexと min-width を見てみてください。