jQueryプラグインのslickは、簡単にスライダーが表示できてとても便利であるが、先日仕事でslickを使った際にslick絡みのトラブルが発生した。
slickイベント「setPosition」とは
タブやモーダルなど、ページ読み込み時に非表示になっているコンテンツ内でslickをそのまま使うと高さが取れずにheight: 0px
となり、領域が潰れて表示されないという問題がある。
この問題を回避するために、slickはsetPosition
というイベントを用意している。setPosition
は、位置やサイズが変更された時に再取得を行うイベントである。
/* タブをクリックした際に発火
.tab クリックするタブ
.slider 対象のスライダー */
$('.tab').on('click',function() {
$('.slider').slick('setPostion');
});
このイベントによって、タブ切り替えで非表示コンテンツが表示になった時に、要素の高さが取れるようになる。
しかし、slick対象にsetPosition
を指定したにもかかわらず、なぜか効かないという状況が発生した。焦って「slick setPosition 効かない」で検索してみても、setPostion
イベントを追加するだけで無事解決!(上記の3行を添えて)みたいな記事しかヒットしない。まるで、「setPostion
で解決しない」という状況自体が存在しないようである。
とはいえ、setPostion
で解決できない状況は今まさに目の前で起こっていた(回想風)。
setPositionが効かない状況および現象
どのような状況でどのような現象が起こったのかを整理してみる。
状況:タブコンテンツとslickする要素の関係が親と曾孫
現象:タブを切り替えると非表示コンテンツの高さが大きくなる
最初は、タブコンテンツとslickする要素が親-子ではなく親-曾孫と、階層が深くなったためsetPosition
が効かないのではないかと疑った。しかし、コンテンツの高さが潰れるどころか逆に大きくなっている点が、単なるsetPosition
効いていない問題ではないように思えた。
setPositionが効かない原因
chromeデベロッパーツールで確認したところ、空白部分が破線ストライプに紫色の領域になっているのが分かった。
破線ストライプに紫といえば、flexやgridで余白が発生した時に付く色である。

スライダー要素のcssを確認すると、display: flex; flex-wrap:wrap;
が付与されていた。リストをflexで折り返しの横並びにしたものを、そのままslickのスライドコンテンツとして突っ込んでいたため、このようなcssプロパティが付いていたのだった。
これはflexとslickの干渉と言うべきか…?恐らくは、flexが何らかの悪さを働いたがためにスライダーに謎の余白が生じたというのが実態だろう。どういう原理でそうなったのかまでは分からないが。
こうしてflexに対する疑惑が深まったため、スライダー要素からflexプロパティを取り除いた上でsetPosition
を適用すると、タブ切り替えで非表示コンテンツが表示されるようになった。無事解決したのはよかったが、それまでに4~5時間ほど費やす羽目になった。
まとめ
slickさせる要素にflex関係のcssプロパティが付いていたら直ちに取りましょう。いや、flexをかけたコンテンツをそのままスライダーにぶち込むにするのは止しましょうと言うべきか。
ネットで解決方法を探っても見つからなかったのは、今までそういう無茶なことをする人が居なかったからでしょう。