jQueryのSlideUp、SlideDownを用いて、最初は一部だけ表示して続きはボタンを押すことで表示、非表示にするというような実装をよく見かけます。
今回、jQueryのSlideUp、SlideDownを使ってコンテンツの一部の表示、非表示をトグルさせるようなサイトを構築した際に、対象となるコンテンツのレスポンシブの切り替えが上手くいかないという現象に遭遇しました。解決するまで結構悩んだので、その対処方法をまとめておきたいと思います。
この記事には、レスポンシブで挙動が変わるコンテンツに対してjQueryのSlideUp、SlideDownを適用する際の注意点と解決方法が記載されています。
jQueryのSlideUp/SlideDownはインラインでstyleを書き換える
jQueryのSlideUp/SlideDownを実際に使ってみると、子要素のstyleを直接書き換えることに気が付きます。
SlideUp動作時は、block要素の子要素には『style=display:none』と埋め込まれて非表示になります。
SlideDown動作時は、block要素の子要素には『style=display:block』と埋め込まれて表示されるようになります。
display:flexとなっている子要素があったときには、『style=display:block』ではなく『style=display:flex』となり、CSSを見ているようでstyleの内容が変わります。
一瞬良さそうに思います。
ところが、レスポンシブでdisplayをflexとblockとか切り替えている場合は上手く動きません。CSSのメディアクエリまでは見ていないので画面サイズによってblockとflexを切り替えているケースでは期待した動きになりません。
レスポンシブが効かないのでこれは致命的か?
正直、styleを埋め込むのは非表示にするときだけでよいと思うのですが、なぜか表示する時にもstyleを埋め込んでくるので期待した動きにならないのです。
レスポンシブのCSSの方が優先順位が低いのであれば、必殺importantをつければ良いじゃないか、と思うじゃないですが、そうすると今度はjQueryがインラインでstyleを書き換えるのが効かなくなるので、SlideUp/SlideDownの動きか死にます。
こうなると、jQueryの挙動がアホなんじゃないかと思い始めて、なんかオプションないのかと探しましたが、そんなものはありません。
仕方ないので別の方法はないのかと思い色々調べました。
CSS3だけで同じことができるのか?jQueryを使わない方法はないのか?とか。
しかし、どれもコードも多くなる割に、汎用的には使えず、個別に調整が必要となるのがネックで、とても導入する気にはなりません。
これ無理ゲーなんちゃうの?と思い始めてきたときに、意外と簡単に解決できました。
レスポンシブ対象にラッパーを追加、意外と簡単に解決
今回トラブルが起きたケースをもう少し詳しく説明します。
もともと、とある部分をSlideUp/SlideDownを使って表示非表示を切り替えようとしていました。SlideUp/SlideDownの対象となる部分全体をmoreというclassをつけたdivで全体を囲み、内部は通常のdivとflex-boxが入っている構成。flex部分はレスポンシブで大画面ではdisplay:flex、小画面ではdisplay:blockに切り替えていました。
<div class="more">
<div class="box"></div>
<div class="flex"></div>
<div class="box"></div>
<div class="flex"></div>
</div>
この状態で、jQueryでmore classにSlideUp/SlideDownすると、boxとflexにstyleが追加され、CSSによるレスポンシブの切り替えが優先順位の問題で無視されるというわけです。
最初に、SlideUp/SlideDownを適用した時に、more classの直下にある要素が一斉にstyleが付加されたので気が付かなかったのですが、しばらくしてSlideUp/SlideDownを適用した要素の子要素だけがjQueryで操作され、孫要素はそのままになっていることに気が付きました。
だったら、子要素全体をラッパーで括れば、flexの要素はjQueryでいじられることは無いのではないか?と思って以下の様な記述に変更しました。
<div class="more">
<div class="wrapper">
<div class="box"></div>
<div class="flex"></div>
<div class="box"></div>
<div class="flex"></div>
</div>
</div>
そうすると、どうでしょう。wrapper classのdivだけがjQueryでstyleを付加されるようになり、孫要素に対するレスポンシブのためのCSSがそのまま効くようになりました。
まとめ
jQueryの動きが思い通りにならず、いっそのことjQueryいらんのでは?と思って、別の方法を探してみたら、代わりの方法というのはなかなか手間のかかる方法しかありませんでした。
最近ではjavascriptが高機能になってきているので、jQueryと同じことがjavascriptでも実現できてしまう状況にありますので、重いjQueryを毛嫌いする風潮があります。
しかし、実装の効率を考えるとjQueryを使わないのは非効率に思えて仕方ありません。jQueryでとりあえず実現できて、更に良くする時に他の方法を考えればよいのだと、改めて感じました。