ノラWEB屋 野良人(のらんど)- 個人営業のWEB屋さん

【AMP対応】CSSのみでアニメーションするアコーディオン

2018年4月3日

AMPサイトでもアニメーションするアコーディオンの実装方法を検討しました。

    AMPの仕様に対応してアニメーションするアコーディオンを作る

    AMPではアコーディオンに関して以下のような制約があります。

    • javascript使用不可
    • transitionまたは@keyframes…opasity/transformのみ対応

    こういった制約があるため、AMPでアコーディオンを実装するにはamp-accordionを使うか、チェックボックスを使うことになると思います。しかし、普通にやるとアニメーション無しでカクっと開閉する挙動になってしまうので、アニメーションしながらヌルヌルと滑らかに開閉するアコーディオンを頑張って検討したいと思います。

    デモ

    デモ1:amp-accrodion

    AMPでレイアウト用コンポーネントとして用意されているamp-accrodionを使用したパターン。こちらは、開/閉の切り替えのみでアニメーションさせることはできないようです。

    ほぼリファレンスのサンプルそのままなのでコードは省略。

    デモ2:CSSのみでアコーディオン

    ポイント

    • チェックボックスの状態で開閉
    • transform:translateでアニメーション
    • transform:scaleにするとpositionやz-indexを考えなくていいので楽だが、動作はtranslateの方がキレイ(好みの問題かも)
    • heightを指定せずにtransformだけを指定した場合、後ろの要素があるとボックスの高さ分の空間が空いてしまうのでやむを得ず指定
    • 全部IDを振る必要があるところがちょっと邪魔くさい

    サンプルコード

    HTML
    <div class="wrap">
    	<label class="title" for="box1">クリックして開閉</label>
    	<input type="checkbox" id="box1">
    	<ul class="toggle">
    		<li>なんらか</li>
    		<li>なんらか</li>
    		<li>なんらか</li>
    	</ul>
    </div>
    
    CSS
    .wrap{
    	overflow: hidden;
    }
    
    input{
    	display: none;
    }
    
    .title{
    	position: relative;
    	z-index: 2;
    }
    
    input + .toggle{
    	height: 0;
    	transform: translateY(-100%);
    	transform-origin: top;
    	transition: .3s;
    }
    
    input + .toggle li{
    	opacity: 0;
    }
    
    input:checked + .toggle{
    	height: auto;
    	transform: translateY(0);
    }
    
    input:checked + .toggle > li{
    	opacity: 1;
    }
    

    ※cssは要点のみで装飾は割愛。以下同。

    デモ3:ヘッダーメニューのアコーディオン

    ポイント

    • 基本はデモ2と同じ
    • 他の要素を気にしなくていいのでheightの指定は不要。かわりにposition:absoluteを指定する
    • よって閉じるときもきれいにアニメーションできる
    • 他の要素にz-indexが指定されている場合は、展開する要素にはそれより大きな値を指定しておく
    • 開閉でラベルの記号を切り替える処理もつけてみた。デモ2とはlabelとinputの位置関係とセレクタがちょっと変わる

    サンプルコード

    HTML
    <div id="header">
    	<input type="checkbox" id="menu">
    	<label class="title" for="menu">メニュー</label>
    	<ul class="toggle">
    		<li>なんらか</li>
    		<li>なんらか</li>
    		<li>なんらか</li>
    	</ul>
    </div>
    
    CSS
    #header{
    	position: relative;
    }
    
    input{
    	display: none;
    }
    
    .title{
    	position: relative;
    	z-index: 9999;
    }
    
    .title::before{
    	content: "▼";
    }
    
    input ~ .toggle{
    	position: absolute;
    	z-index: 9998;
    	width: 100%;
    	transform: translateY(-100%);
    	transition: .3s;
    }
    
    input:checked ~ .title::before{
    	content: "×";
    }
    
    input:checked ~ .toggle{
    	transform: translateY(0);
    }
    

    まとめ:腰が痛い

    今日は娘がこども園に初登園の日でした。はやいものですね。

    ところで送っていく途中に突然の腰痛に襲われて今とてもやばい状態です。今日はルルドで揉みほぐしつつ、コルセットでも巻いて休み休み過ごします。痛みが引いたら体幹のトレーニングをちゃんとやろう…。

    と、いうことで、AMPの制約は辛いですが、知恵と工夫で頑張りましょう。

    このエントリーをはてなブックマークに追加