8192.jp

CSSのみで「続きを読む」ボタンを実装&エフェクトも掛けてみる

Web制作 2022/07/15 2022/07/15

有名なテクニックですが、CSSのみで「続きを読む(ReadMore)」ボタンを実装する方法を紹介します。アコーディオンって言ってもいいかな?

あと、後半ではtransition等のエフェクトを掛ける応用パターンも載せておきますんでそちらも参考にどうぞ。

「いや普通にjQueryのslideToggleとか使えばええやん」という声が聞こえてきそうですが、敢えてCSSのみで作る、というのが楽しいので無視しましょう。

目次

    基本形

    まずは基本パターンを紹介。

    See the Pen Untitled by Leo_8192 (@Leo_8192) on CodePen.

    「続きを読む」を押すと下部のコンテンツが出てくるというシンプルな機能ですが、CSSだけでこれを実装するにはどうすればいいか、前知識なしにパッと思い付ける人は少ないんじゃないでしょうか?

    実は仕組みは簡単で、(隠していて見えないですが)チェックボックスのON・OFFの状態に応じてスタイルを切り替えているだけです。

    それではコードの解説に移りましょう。

    HTML

    <div class="content">
    	<input type="checkbox" id="cb">
    	Lorem ipsum ~略~ magna aliqua.
    	<div class="more_wrap">
    	Ut enim ad ~略~ nulla pariatur.
    	</div>
    	<label for="cb" class="more_btn"></label>
    </div>

    labelfor="cb"をセットすることでinputと紐づけされるので、labelをクリックしてもチェックボックスのON・OFFを切り替えることが出来るようになります。

    CSS

    #cb{
    	display: none;
    }
    
    .more_btn{
    	display: block;
    	margin: 1em auto 0;
    	padding: 8px 16px;
    	border: 1px solid #999;
    	cursor: pointer;
    }
    #cb ~ .more_btn::before {
    	content: "続きを読む";
    }
    #cb:checked ~ .more_btn::before {
    	content: "閉じる";
    }
    
    .more_wrap{
    	display: none;
    }
    #cb:checked ~ .more_wrap{
    	display: block;
    }

    ※サンプルの装飾用プロパティは省略しています。

    それでは各コードの解説です。

    1-3行目
    #cb{
    	display: none;
    }
    今回はチェックボックスの「機能」が欲しいだけなので、見た目はdisplay:none;で隠しちゃいましょう。
    12-17行目
    #cb ~ .more_btn::before {
    	content: "続きを読む";
    }
    #cb:checked ~ .more_btn::before {
    	content: "閉じる";
    }
    チェックボックスのON・OFFの状態に応じて、contentに「続きを読む」か「閉じる」のどちらかにセットしています。
    19-24行目
    .more_wrap{
    	display: none;
    }
    #cb:checked ~ .more_wrap{
    	display: block;
    }
    チェックボックスのON・OFFの状態に応じて、.more_wrapの表示・非表示を切り替えています。

    こうやって分割して見ていくと、そんなに難しいことをしている訳ではないのが分かると思います。

    それでは、このコードをベースに少し装飾を強化したVerも作ってみたのでそちらもどうぞ。

    応用パターン

    ※ソースが気になる人はCodePenに飛んで見てね!

    直前の文章にグラデーション

    See the Pen PureCSS_ReadMore_1 by Leo_8192 (@Leo_8192) on CodePen.

    なんかニュースサイトとかでこういうのよく見る気がする。

    transitionを無理矢理使う

    See the Pen PureCSS_ReadMore_3 by Leo_8192 (@Leo_8192) on CodePen.

    最初はheight:0;からheight:auto;に変化させようとしたんですが、これだとtransitionは効かないんですよ…調べたんですが、heightに時間変化を加えるには

    • 数値を固定値にする
    • vhを使う
    • (親要素の高さが固定値の状態で)%で指定する

    …しか無さそうです。ブラウザが変化後の高さを計算できる状態じゃないとtransitionは使えないってことですね。

    んで、結局辿り着いたのがheightは初期値(auto)のままでmax-height0~100vhまで変化させるという方法。これなら一応transitionが効いてくれます。

    ただし、この方法だとほぼ確実に閉じる動作の際に遅延が発生します。

    遅延が発生する理由

    例えば画面の高さが1000pxの環境で、「続きを読む」を押した後のコンテンツの高さは500pxだったとしましょう。んで、transition1slinearと仮定します。

    「続きを読む」を押したとき、heightの高さが500pxに達するのは1秒後ではなく0.5秒後です。残りの0.5秒は、見た目上は何も変わらないですがmax-heightが1000pxまで変化し続けています。

    これだけならまぁ大丈夫なんですが、閉じるときはこの逆の事が起きるので「閉じる」を押してから0.5秒待たないと高さが変化しないことになります。対策不可能、終わりです。

    上2つの組み合わせ

    See the Pen PureCSS_ReadMore_3 by Leo_8192 (@Leo_8192) on CodePen.

    「続きを読む」を押したときはすぐにグラデーションの処理を実行しているんですが、「閉じる」を押したときは0.25秒のディレイを追加しています。理由は見た目上の高さが変化するまでの時間に少しでも近づけるためです。これで、先述したモヤモヤポイントは残りつつも多少は見栄えが整った感じはします。

    でもやっぱりあれだ、こればっかりはCSSだけで作るもんじゃないです。完璧を求めるなら固定値を使うか、閉じる機能は切り捨てるか、大人しくjQueryとか使いましょう。


    以上、CSSのみで「続きを読む」を実装する方法でした。