複数列かつ縦並べのliタグをやっつける方法・改

複数列かつ縦並べのliタグをやっつける方法・改

前回記事ではわざわざMixinまで作ってGrid Layoutを使った解決法を紹介しました。
しかし・・・よく考えたら実はもっと簡単な方法がありまして。
四角い車輪を発明してしまったような気分ですけども、めげずに解説していきます。

例となるお題の条件等は前回記事を参照ください。
プロセスが違うだけで出力結果は変わらないのですが、
書き方は微妙に変えてあるので別途デモを用意しました。

Flexboxを使った解法

関係ない記述とかはすっ飛ばしてます。


display: gridから始まる一連のスタイルはいらないです。
(現行ブラウザの対応だけなら)ベンダープレフィックスもいらないです。
IEのために子要素に無理矢理どうのこうのも不要です。
そう、最初からこうすれば済む話だった・・・。

一応解説しときますとflex-flow: column wrap;で
「縦並びかつ横に折り返し」という設定をしていて、
あとは折り返し対象となる縦幅と横幅を指定、という運びになっております。
簡単ですね。いたって簡単。
こんなん思いつかないとかアホの極みですね。→アホの書いた記事

ま、まぁその、こういう単純な折り返しだったからFlexboxで済んだだけですからね。
「じゃあやっぱりGrid Layout要らないじゃん!」とか思っちゃダメですよ。
『RWDでスマホサイズの時は下に置いて、そうでない時は横に…』
みたいな場合ではやっぱりGrid Layoutが賢い選択だと思いますよ。
そ、そう!Gridちゃんはレスポンシブでこそ輝く子なんだ!めんどくさいけど

とか言い訳を残して締めくくります。
・・・と思いきや。

またしても立ちはだかるIE

うん、「また」なんだ。済まない。 (´・ω・`)
確かにベンダープレフィックスもIE11用のCSSハックも要らないとは書きました。
でもやっぱIEは別途対策がいるんです。とてもつらい。
上述のようにCSSを書き換えても
IEだと列が折り返されずに項目が縦並びになってしまうんす。

2~3時間ぐらい格闘した結果分かりました。
よく分かんないけどIEのバグっぽいということが分かりました。
参考:
アイテムが潰れた / min-height, min-widthが効かない|flexboxのバグに立ち向かう(flexboxバグまとめ)

参考URLではmin-heightに関する言及ですが、
なんかmax-heightでも同様の症状っぽいです。

アイテムがコンテナの高さを知らない模様

ってことで、アイテムがコンテナのmax-heightを超えていたとしても
無視してどんどん項目が下に積まれてしまうってな話みたいです。エーン

IEでの解決策を考える

max-heightではなくheightを使う

今回みたいにホバー領域が関わってくると使えない場合も出てくる方法ですが、
基本的にこれが一番いい方法だと思います。
利点:
簡単。上述のCSS(貼り付けたソース部分)のmax-heightをheightに変えるだけ
欠点:
必ずしもリストの高さが322pxとは限らないので、今回のケースの場合は相応しくない
(項目数が7個未満の場合が考えられる)

flex-flow: columnしている部分を囲む要素を追加する

下記のソースも参照。
利点:
上記の欠点を解消できる。
項目数が2個や3個の時でもホバー領域は適正に動く
欠点:
CSSだけでなくHTMLを書き換える必要がある


こんな感じで書き換えればいいと思います。が…
さて、ここで今回のお題を振り返ってみましょう。


・・・何もかも裏目だな!
じゃあもうこんな感じの該当コンテナを囲むJSとか書けばいいんじゃないですかね(なげやり)。

$(‘p01_navChild‘).wrap(‘<div class=”p01_navChildwrap” />’);

結局最後はゴリ押しのDOM操作!
IEはアホの子!
終わり!!(えー)


脱線

これで解決(?)したので記事の内容としては終わりなんですけど、蛇足的補足をば。
デモで使ったテクニックの一つに、『ナビゲーションをふわっとアニメーションで表示』
させようとしたした所があるんス。
参考:アニメーションする例(ふわっとする)

こういうやつってdisplay: noneをホバーに応じて書いたり消したり
するのがメジャーなんですけど、それだとアニメーションできないんすよね。
(JS書けばどうとでもなるけど)

参考:アニメーションしない例(ふわっとしない)

だから、display要素で表示を制御しようとせず
『ホバー時にopacityの値をアニメーションさせつつ変化させ、
該当箇所だけを可視化させている』
というカラクリで動かしていたんすよ。

発生した課題

で、デモ上では上手く機能してるんですけど…
デモの記述を上の例に倣ってFlexboxの記述に変えるとホバー領域がバグるんス。
どういうことかっていうとこういうことです。

ギギギ・・・。
確かにふわっと表示されてるのでそこは問題ないのですが、本来であれば
『左端の親項目をホバーした状態で子のリスト群が展開』
されなければならんわけで。
この状態だとリストとは無関係な領域をホバーしているにも関わらず、
子のリスト群が展開されてしまっているのです。

その原因

原因は簡単なんす。
opacityで透過しているとはいえ、リストは画面上に存在しているためです。
一見目に見えないけど実体はあるカメレオンみたいな状態なんで、
ホバーすると出現してしまうのです。

これがdisplay: noneだと上記の問題は起こらないのですよ。
なぜかというと非ホバー時には画面上から”消して”ますからね。
ただ、display: noneだと先述の通りアニメーションが効きません…。

デモ上では、
非ホバー時:width, heightを0に、overflow: hiddenに。z-indexとopacityを0
ホバー時:width, heightをautoに、overflow: visibleに。z-indexとopacityを1
みたいな感じで逃げてたんすけどね。
(非ホバー時の領域は縦横0pxにするみたいな邪法的な解決法です)

これだとFlexboxで組んだ時はうまく動いてくれないみたいでして。

解決策

全ての子要素の幅と高さが0なら自ずと親要素もホバー可能な領域を持たなくなるわけで。


親要素の表示条件を満たしている時だけdisplay: block;にしておけば、
上の方に貼ったGIF動画のような怪現象にも悩まされなくなるという寸法です。

・・・ぶっちゃけ何言ってんだコイツ状態かもしれないですけど、
いちおう「こういうトリッキーなことをやってみたよ」という紹介です。

おわりに

信じられないぐらい長い記事になってしまいました。
こんなに時間をかけるつもりは無かったのに・・・。
ところで、前回および今回のデモではPugを使ってHTMLを出力してたので
また別の機会にPug体験談みたいな記事も書こうかなと思ってます。