Edited at

スマートフォンのポップアップ上でアコーディオンパネルを実装する

More than 1 year has passed since last update.

スマートフォンにポップアップを出すというのは、その特性からして適切ではない(エラーダイアログは除く)と思うのだが、業務上、実装する方に倒れてしまう事があるのでメモ。


iOSは動くのに、なぜAndoridで動かん!

今のところ(2014年5月現在)iOSでポップアップを出して、その上でアコーディオンパネルを動かす事は苦ではない。jQueryのslideToggle使えば瞬殺です。

だがしかし。

Androidはどうにも動かん。時々運良く動作する事もあるけど、ほぼ正常に動かない。

どうもAndroid2系からある『z-indexのバグ』が悪さをしている模様(細かいところまでは調査していないけど原因の一つだと思う)。

参考1:Loosely - Androidのposition:fixed;とz-indexのバグ?

参考2:冬通りに消え行く制服ガールは✖夢物語にリアルを求めない。 - Android のブラウザのフォーカスが z-index を無視しているバグがなおらない

こいつはなかなか厄介で、ポップアップの下にainput type=textとかselectがあると、ポップアップ上のリンクを選択したにも関わらず、ポップアップ下のainput type=textとかselectにフォーカスが当たってしまうという摩訶不思議なバグで、デザイナーや開発者泣かせのひとつで、2系からの問題にも関わらず、4系になった今でも絶賛続行中な代物だ。


無理やりAndoridでも動かす

実は方法はある。

かなり鈍い動きをするが、タップすると必ずパネルが表示されるので、今のところどうしても実装しなければならない時に使う奥の手になっている。


CSS

/* タブをタップした時に矢印の方向が変わるスタイル */

.toggle label.title.open,
.toggle label.title.close {
background:#0786c3 url(/images/arrow/icon_arrow_up.png) no-repeat 95% center;
display:block;
padding:2px 5px;
margin-bottom:10px;
cursor:pointer;
}
.toggle label.title.close { background:#0786c3 url(/images/arrow/icon_arrow_down.png) no-repeat 95% center;}

/* チェックボックスは非表示 */
.toggle input[type="checkbox"].on-off {display: none;}

/* 初期値はon-offクラスを持つチェックボックスの隣接の.toggle_bodyは非表示 */
.toggle input[type="checkbox"].on-off + .toggle_body{
height: 0;
overflow: hidden;
}

/* on-offクラスを持つチェックボックスがチェックされたら隣接divを表示。高さを指定する。 */
.toggle input[type="checkbox"].on-off:checked + .toggle_body {height: 310px;}

/* チェックボックスがチェックされた時に表示されるボックスのアニメーション */
.toggle_body {
-webkit-transition: all 0.5s;
-moz-transition: all 0.5s;
-ms-transition: all 0.5s;
-o-transition: all 0.5s;
transition: all 0.5s;
margin: 0;
padding: 0;
}



Javascript

//ラベルをクリックされたらクラスを付け替える

//openだったら一度openを消してcloseを付与し、closeだったらcloseを消してからopenを付与する
$(function(){
$(".toggle label").click(function(){
if($(this).hasClass("open") ){
$(this).removeClass("open").addClass("close");
}
else{
$(this).removeClass("close").addClass("open");
}
});
});



HTML

  <div class="toggle">

<label for="Panel1" class="title open">パネルタイトル1</label>
<input type="checkbox" id="Panel1" class="on-off" checked> /*一番上のパネルはあけておく*/
<div class="toggle_body">
パネルタイトル1の本文
</div>
</div>

<div class="toggle">
<label for="Panel2" class="title close">パネルタイトル2</label>
<input type="checkbox" id="Panel2" class="on-off">
<div class="toggle_body">
パネルタイトル2の本文
</div>
</div>


参考:CSSだけでメニューが開いたり閉じたりするアコーディオンを作る!javascript不要 | 9ineBB

このコードはjsがなくても動きますが、ラベル部分の矢印をOPEN/CLOSEで変更したかったので、ラベルをクリックしたらラベルに付与されているクラスを調べ、openだったら外してcloseを付与、closeだったら外してopenを付与するというjsを追加してます。

矢印などの変化が必要なければjsは不要という素敵なアコーディオンパネルです。参考サイト

には感謝。

Androidで動きますが、非常にもっさり開きます。

結論:スマホのポップアップはやめよう。やめられなくても、せめてその中でアコーディオンパネルを開くのはやめようよ(ほとんど懇願)。