LoginSignup
15
7

More than 3 years have passed since last update.

height: auto; の要素へ「もっと見る」機能を付ける

Last updated at Posted at 2019-12-02

はじめに

CSSアドベントカレンダー3日目はCSSに関する小ネタです。

記事一覧などのページで「もっと見る」ボタンを実装するときに、height へのCSSアニメーションのよくあるハマりポイントと私が実務で解決したときの実例を紹介したいと思います。

作りたいもの

「もっと見る」ボタンを押して続きが読める機能

「もっと見る」ボタンを押した後に元に戻る機能は考えないものとします。
また、本記事はCSSについての解説がメインなのでJSの実装などは適当もしくは記述しない場合があるので予めご了承ください。

height が実数値のときの「もっと見る」ボタン

まずは、height: auto; じゃないパターンです。
閉じた状態と開いた状態のスタイルを書いて、transition の指定をするだけです。簡単。

.content {
  transition: height 0.5s ease-in-out;
  height: 40px;
}

.content.open {
  height: 80px;
}

See the Pen Open/Close content sample by Sho Ezawa (@ezawa800) on CodePen.

height: auto; にしたい

「もっと見る」ボタンを押したら内容をすべて表示するようにしたいケースでは、height: auto; を指定したいこともあります。

こんな感じです。

.content {
  transition: height 0.5s ease-in-out;
  height: 40px;
}

.content.open {
  height: auto;
}

ただし、これには問題があり…

height: auto; には transition が効かない!

See the Pen Open/Close content sample with height:auto; by Sho Ezawa (@ezawa800) on CodePen.

こればかりは仕様なので仕方がない。
代案を考えます。

max-height を使うと transition が効くようになる

よくある解決策がこちら。

.content {
  transition: max-height 0.5s ease-in-out;
  max-height: 40px;
}

.content.open {
  max-height: 9999px;
}

See the Pen Open/Close content sample with max-height; by Sho Ezawa (@ezawa800) on CodePen.

ただし、まだちょっと問題が…

開いた状態の max-height の値をどうするか問題

開いたときに中身をすべて表示したい場合、文字数制限などがあればいいのですが、

  1. 仕様上の問題で文字数制限を設定できない
  2. あとから仕様が変わって文字数の上限が変わってしまいスタイルが崩れた

などが考えられます。

max-height: 9999px のような指定の問題点

それならば絶対に中身がはみ出さない十分に大きな値を指定すれば!と思うのですが…

サンプルをみてもらうと分かるように、transition に指定した秒数と実際にアニメーションの速さが違ってしまいます。

再掲:


See the Pen
Open/Close content sample with max-height;
by Sho Ezawa (@ezawa800)
on CodePen.


これは、transition はあくまで max-height を指定の秒数で変化させるため、例えば開いた状態の高さが 300px ならば max-height が 300px になった時点でコンテンツが開き切ってしまいます。

さらに、文字数によってアニメーションの速度がバラバラになってしまい、文字数が多い場合は速すぎる、文字数が少ない場合は遅すぎる、ということが起こる可能性があります。

アニメーションをこだわって作る場合にこれではちょっと困ります…。

解決案: オーバーレイを使う

そもそもアニメーションを付けるのは、ユーザーに「画面が変化したことを気づいてもらいやすくする」のが目的なので、必ずしも height に対してアニメーションを付ける必要はないです。

そこで、おすすめなのはオーバーレイを使ったパターンです。

height はアニメーションなしで変化させ、オーバーレイを徐々に透明にしていくことで、擬似的に徐々にコンテンツが現れたような表現にすることができます。

.content .overlay {
  transition: opacity 1s ease-in-out;
  opacity: 1;

  pointer-events: none;
  background: linear-gradient(rgba(255, 255, 255, 0), #fff);
  position: absolute;
  top: 40px; /* = .content height */
  left: 0;
  width: 100%;
  height: 100%;
}

.content.open .overlay {
  opacity: 0;
}

See the Pen Open/Close content sample with overlay by Sho Ezawa (@ezawa800) on CodePen.

上記のサンプルでは、閉じた状態ではオーバーレイは overflow: hidden; で隠れていますが、開く前からコンテンツの上のかぶせて置くことのも良いと思います。その際は、オーバーレイの下のコンテンツが選択できるように pointer-events: none; を付けておくと良いと思います。

まとめ

  • height: auto; だと transition が効かない
  • max-height を使うパターンだと十分じゃないケースもある
  • 解決策としてオーバーレイを使うパターンがおすすめ

その他の解決策

アニメーションの話は、「すべてのケースはこれで解決!」ということは無いと思うので、

  • 他にこんな方法で解決した
  • オーバーレイを使った方式だとこんな問題点があるかも

と言ったアイディア・ご意見があればコメントでもらえると嬉しいです!

15
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
7