折りたたみが最も簡単 details と summary についてメモ

HTMLの<details>と<summary>を使った折りたたみがシンプルすぎて気に入ったので今更感ありますけどちょっとだけ触れておきます。

素人デジタル部活の部長は折りたたみが大好きです。折りたたみ、アコーディオン、正確に何と言うか知りませんが、10年前に初めてWordPressを触ってみたときも最初に入れたプラグインは「続きを読む」で折りたたまれた本文をペロッと表示するやつでした。

<details>タグと<summary>タグ

クリックで格納・展開するHTMLタグです。JavaScriptも特殊なcssもいらないシンプルな作りです。

これを知ったのはWordPress公式テンプレートのスマホ表示におけるメニューでした。折りたたみが好きなはずなのにあの表示が嫌いで、どこが嫌いかというとアニメーションせずに瞬時に画面が切り替わってしまうところでした。そのせいで画面で何が起きたか分からずうろたえました。

そのスマホ表示のメニューを消すためにソースを見ていて、それでこのタグを知りました。

<details>
	<summary>
		見出し
	</summary>
		展開する中身
</details>

detailsで囲み、隠さない部分をsummaryで囲みます。簡単すぎませんか。試しにやってみたら確かに期待通りに動いたので驚きました。

summary:サンプル見出し

テキストテキストテキスト中身中身

なんと簡単でしょう。▼も自動で付くし。でもなめらかな動きが伴わず瞬時に開閉します。一瞬何が起きたかわからないですね。開く、閉じるが視覚的に分かる挙動がほしいです。昨今の優れたCSSで動きを付け足せばいいだけだな、と最初は簡単に考えていました。

動きが付けられない

散々いろんなことをやったあげくにどうしてもうまくアニメーションしないので検索してこのタグについて調べてみたら(順序逆じゃね?)なんと動きを付けられない仕様なんだとか。

detailsに対してCSSでtransitionは付けられるんです。でもdetailsがうまく動いても肝心の中身が追随しなくて、みっともないアニメーションになるんですよ。開くのに0.3秒かけることはできても、その中身は瞬時に表示されてしまいます。中身が先に表示されているのに開く動きをする姿はかなり間抜けです。

動きを付けられました

いろいろ試したけどうまく行かず、だんだん面倒になってきてやがて興味を失いました。でも久しぶりに使ってみて何となくCSS書いていたら思い通りの動きをしたのでちょっと驚きました。規格が変わったのかブラウザの実装方法が変わったのか私が賢くなったのかどっちでしょう。

その動きと仕組みをサンプルとしてここに載せるやりかたがわからないのでこのサイト内に実例ありますからこちらを御覧ください -> シリーズ記事メニュー

transitionを使ってますから、開く閉じるを表現するために数値で高さを作ってやらないといけなくて、そこだけちょっと不自由です。でも期待通りの理想的な動きが実現しました。

なぜこれまで上手くできなかったのだろうと不思議ですが、いろいろ試したと思い込んでいただけで正解から外れたことばかりやっていたのかもしれないです。高さを固定させるのがどうしても厭だったのかも。

details の HTMLとCSS

htmlで中身のコンテナを作る

コツというほどのことでもありませんが、必要な措置は、detailsの中身コンテナを作っておくことでしょうか。

<details>
  <summary> タイトル </summary>
  <div> 中身 </div>
</details>

divで囲んだだけです。何故必要かというと中身をスクロールさせるためというのもあります。

css概要

transitionを動かす条件として高さを数値で決めなければなりません。detailsとdetails openに高さを付けます。すると中身がうまく収まらないから中身divにもdetails openに合わせた高さを与えて、はみ出る分はoverflow-y:scroll で逃げ切ります。そしてdetails openにoverflow:hiddenを与えます。

detailsのCSS

大外のガワであるdetailsです。開いてるときは open が付きます。逆にいうとopenであるときは開いているということです(当たり前を逆に言わなくてよろしい)

[open]に高さとアニメ設定を設定

[open]に開いたときの高さを指定して、transitionを設定します。

details[open] {
  height: calc( 65vh + 36px);
  transition: all 0.4s;
}

[open] に書くtransitionが開くときのアニメーションになります。これ、私ずっと逆だと思ってました。

この例で高さの指定が変なことになっていますがこれは「中身divの高さ」+「summary分の高さ」です。

素のdetailsにoverflow:hidden

openのつかない素の details のほうには、summary分の高さをheightとして設定しています。そしてoverflow:hiddenを付け足しました。こっちにoverflowを付けるってことを今までは思いつかなかったのかもしれません。

details {
  height: 36px;
  overflow: hidden;
  transition: all 0.2s;
}

ところでopenのつかない素のdetailsに書くtransitionの指定が閉じるときの動きになります。ずっと逆だと思ってた。

中身のdiv

これまで上手くいかないとき、どうも中身divばかりいろいろ弄りすぎていたような気がします。中身divはごく普通に装飾をする以外に特に変わったことはしません。

 [open] いらない taransitionいらない いるのは高さ

ポイントはというと、こちらにもdeatils openに合わせた高さを指定していることと、overflow-y:scrollがdetailsじゃなくてこっちにあることでしょうか。個人的には盲点つかれた感じですがちゃんと知識がある人には何言うとんのというレベルですか。

でもそれより何より、こちらdivでは[open]が不要であるとか、こっちにはアニメーションの設定も不要であるということが重要でした。そこがまた盲点でした。

同じものですがまとめて書くとこうです。高さ以外の装飾的なスタイルは除いています。たったこれだけでベストな動きを手に入れました。

/* HTML */
<details>
 <summary>タイトル部分</summary>
 <div class="detail_content">
  中身
 </div>
</details>
--------

/* CSS */
details[open]  {
	height: calc( 65vh + 36px);
	transition: all 0.4s;
}

details {
	height: 36px;
	overflow: hidden;
	transition: all 0.2s;
}

.detail_content {
	height: 65vh;
	overflow-y: scroll;
}

summary {
 cursor: pointer;
}

シンプルなHTMLとCSSですので、記事の中やテンプレートでも自在に使えます。開閉に動きをつけられないという唯一ですが最悪の欠点を克服できましたので、突如めちゃ使えるタグと化しました。

これまではInternet ExplorerはもういいとしてEdgeがこのタグに対応していませんでした。今は対応したんですか?よくわかりませんが、未対応ブラウザの場合はどう見えるんでしょう。

 

このポストの時点で上記CSSを割り当てているのはシリーズ記事というページだけですけど、近いうちにブログ全体のCSSに適用すると思いますペンギンアイコン mini
広告
カテゴリーWordPress
このエントリーをはてなブックマークに追加

コメントを残す

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください