あらかじめ日記

2chまとめサイト「ソノウソホント?」の雑記と、ブログで使えるスクリプトとかテクニックとか。その他、音楽やアニメ、漫画の話題とかも。

まとめサイト「ソノウソホント?」と「ムードもりあげ楽団」はこちら。

【CSS】「続きを読む」の記事の折りたたみをJavaScriptを使わないで実装してみる

ブログを投稿する時に、各ブログサービスでは本文と追記を区切るような方法を用いることで「続きを読む」を作ることはできますが、追記を更に区切る方法です。

 スマホサイトは基本的に縦長になり、関連記事や人気記事等を置いたサイドバーは記事の下に置いたりします。この時、メインコンテンツが長くなった時に、途中で離脱する人も考えて記事の途中で記事下の情報が見てもらえれば、この記事は飽きたけど他のページも見てくれるかもしれない、、と言う思いを込めてある程度の長さ以上を折りたたんでおき、更に「続きを読む」見たいなボタンを用意して開閉させよう、と言う訳です。

JavaScriptを使う方法もありますが、CSS3.0ならCSSだけでこの開閉が実装できます。
テクニックとしてはCSS3.0で追加されたcheckedセレクタを利用して、ざっくり言うとこのcheckedと別のセレクタを組み合わせてチェックボックスの(On/Off)の有無で別の要素のスタイルを切り替える、と言うもの。

checkedの詳細はこちらにでも。

developer.mozilla.org

これを利用した開閉ボタンのサンプルは各所で紹介されているのでそれらを参考にして頂いて、、

ここではそのスタイルの切り替えを、max-heightで最大高さを決めておいて、チェック状態の時のスタイルでmax-heightを解除する、と言う方法で対応してみました。

まずはサンプルです。

HTML

<input type="checkbox" id="label_text" />
<div>
  <div id="post_text">
    本文
  </div>

  <div id="continue_button">
    <label for="label_text">続きを表示</label>
  </div>
</div>

CSS

#label_text {
  display:none;
}

#continue_button {
  display:none;
}


@media screen and (max-width: 850px) {
  #post_text {
    max-height: 5000px;
    overflow: hidden;
  }

  #continue_button {
    display: block;
    margin: 10px auto;
    text-align: center;
  }

  #continue_button label {
    padding: 5px;
    border: solid 1px black;
    cursor: pointer;
  }

  input:checked + div {
    display: block;
  }

  input:checked + div > #post_text {
    overflow: visible;
    max-height: initial;
    max-height: auto;
  }

  input:checked + div > #continue_button {
    display:none;
  }
}

まず、チェックボックス要素の直下に切り替える要素を配置。

ボタンは下に置きたいのでlabelで関連付けて、さらにスタイルでボタンに見立てます。

チェックボックスは見せる必要が無いので消しておきます。

あとはPC以外のタブレットスマホ用の場合だけ適用させるために@media screenで条件を入れてみました。

これで、通常時は最大高さ5000pxを超える場合のはみ出る部分は非表示にしますが、チェックがONになると最大サイズを解除して表示される、と言う動きになります。
(max-heightを解除する時のautoはinitial未対応用)

そして、一度開いたらボタンはもう隠したいので表示を消します。
ただし、ここで注意点として、

qiita.comここに書かれているように、iOS Safari含む一部のブラウザで、checkedと隣接セレクタ複数指定した場合が効かないようです。自分はChromeで確認しました。
レンダリングをするタイミングに問題があるとかどうとうか。。)
そのため、サイトのサンプルは関節セレクタですが、自分はこのボタンを消すために全体をdiv要素で囲って隣接はその要素だけにし、子要素として指示することで対応しています。