Flexbox内でSlickの幅が15000pxになる原因と解決方法【min-width:0】

公開日
Flexbox内でSlickの幅が15000pxになる原因と解決方法【min-width:0】

Web制作をしていると、一度はハマるバグがあります。

「Slickを入れたら、なぜか要素の幅が 15000px になっている」

原因が分からないと何時間でも溶けるタイプのやつです。しかも答えが分かると「たったこれだけ?」と拍子抜けします。今回はその原因と、min-width: 0 で一撃解決する仕組みまで整理しておきます。

起こった現象

こんな状況でした。

  • Slickを導入した
  • でも矢印が表示されない
  • right: 20px; にしても表示されない
  • DevToolsで確認すると、要素の幅がとんでもないことになっている

DevToolsで見た幅がこちら。

.index-interview__list {
  width: 15000px; /* ← なぜ?? */
}

「なんで15000px?」——ここで完全に手が止まりました。

最初に疑ったのは「矢印の位置」

矢印が見えないので、真っ先に疑ったのは位置指定です。Slickの初期CSSでは矢印が枠外に飛び出していることがあります。

.slick-next {
  right: -25px; /* 枠の外に出ている */
}

そこで、いったん内側に引き戻してみました。

.slick-next {
  right: 20px;
}

しかし、まったく変わらない

つまり原因は「矢印の位置」ではない、ということが分かりました。矢印が見えないのは結果であって、本当の問題はもっと手前にあります。

DevToolsで構造を追う

Elementsパネルで、Slickが生成した構造を上から追っていきます。

.index-interview__list   ← 自分で用意した要素
 └ .slick-list
     └ .slick-track       ← Slickが自動生成

すると、内側の .slick-track がこうなっていました。

.slick-track {
  width: 15000px;
}

そして、その巨大な幅に引きずられて、外側の .index-interview__list まで15000pxに広がっていたのです。矢印が見えなかったのは、要素が画面外まで伸びきっていたからでした。

原因はFlexboxの min-width: auto

このセクションの構造はFlexレイアウトでした。

.index-interview {
  display: flex;
}

.index-interview__list {
  flex: 1; /* 右側を伸ばしたい */
}

一見ふつうです。ですが、ここに落とし穴があります。

Flexアイテムの min-width は、初期値が auto です。

min-width: auto は「中身(コンテンツ)より小さくならない」という意味を持ちます。つまりFlexアイテムは、中身が大きければ、その中身に合わせてどこまでも広がってしまうのです。

Slickは巨大な .slick-track を作る

Slickはスライドを横一列に並べるため、全スライドを1本の長いレール(.slick-track)の上に配置します。スライド枚数や設定によっては、この幅が平気で数千〜数万pxになります。

.slick-track {
  width: 15000px;
}

ここでFlexboxの min-width: auto が牙をむきます。

中身(.slick-track)が15000px必要なんだな → じゃあこの子要素も15000pxまで広げよう

こうして .index-interview__list 自体が15000pxに膨張してしまう、というわけです。

解決方法:min-width: 0 を足すだけ

対策はこれだけです。

.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: 0 で直るのか

仕組みはシンプルです。

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 が犯人です。方向が変われば効くプロパティも変わる、と覚えておくと迷いません。

Slickだけの話ではない

この「Flexの子要素が中身に引っ張られて伸びる」問題は、Slick固有ではありません。中身に横長の要素を持つライブラリなら、どれでも起こり得ます。

  • Slick
  • Swiper
  • Splide
  • Embla
  • 自作の横スクロール

いずれも、Flexboxの子要素が横に伸びたら、まず min-width: 0 を疑う。これは覚えておくと本当に何度も助けられるテクニックです。

まとめ

  • Flexアイテムの min-width は初期値が auto で、中身より小さくなれない
  • Slick等は巨大な .slick-track を作るため、Flexの子要素がそれに引きずられて伸びる
  • 解決は min-width: 0(必要なら overflow: hidden)を足すだけ
  • 縦並び(column)なら min-height: 0
  • Swiper・Splide・Emblaなど、横長の中身を持つライブラリ全般で同じ対処が効く

「幅がおかしい」「矢印が消えた」ときは、位置指定を疑う前に、まず親のFlexと min-width を見てみてください。

IPPEI FUKUTA(株式会社バッズブルー 代表)

IPPEI FUKUTA(株式会社バッズブルー 代表)

WordPress専門のWeb制作者として15年・150サイト以上を担当。現場でつまずいた問題と解決策を、同じ制作者・フリーランスの方に向けて発信しています。無料のWeb便利ツール集「バドツール」を開発・運営中。