【CSS】display:none に対してアニメーションを付けてみた
CSSを熟知している皆さんにとって、CSSでアニメーションを作成することは簡単なことかもしれません。
しかし、私のようなまだまだ経験の浅いコーダーにとっては、慣れない作業に感じることがあります。
そこで、最近私がコーディングしたアニメーションについて、備忘録として記録しておこうと思います。
実装概要
実装概要としては至ってシンプルでです。
コード(TypeScript × React)は下記のようになります。
import { useState, type FC, type PropsWithChildren } from "react";
import { BsArrowsAngleExpand } from "react-icons/bs";
const Content: FC<PropsWithChildren> = ({ children }) => {
return <div className="content">{children}</div>;
};
export const Example: FC = () => {
const [isEnabled, setIsEnabled] = useState(false);
return (
<div className="example">
<Content>block</Content>
<Content>
<button
className="button"
onClick={() => setIsEnabled((prev) => !prev)}
>
<BsArrowsAngleExpand size="20px" />
</button>
{isEnabled && (
<div className="block">
<span>block</span>
</div>
)}
</Content>
<Content>block</Content>
</div>
);
};
実際の挙動は、ボタンを押すと下記のようにコンテンツが表示される挙動に、アニメーションを実装するといったものです。
さて、実際にアニメーションを追加していきます。
シンプルにコーディング
とりあえず、height
とopacity
だけのシンプルなアニメーションを付けるとして、
{isEnabled && (
<div className="block">
<span>block</span>
</div>
)}
上記のコードのisEnabled
で表示・非表示を分けている部分を、CSS で置き換えるために
<div className="block" data-isenabled={isEnabled}>
<span>block</span>
</div>
データ属性として<div>
にisEnabled
を渡すように変更し、
.block {
--block-height: 200px;
padding-top: 10px;
height: var(--block-height);
opacity: 1;
transition: all 1s;
}
.block[data-isenabled="false"] {
padding-top: 0px;
height: 0px;
opacity: 0;
}
とすると、
アニメーションが動いてますね。
完成!となればいいんですが… 実は、要素としては残ってしまっているんです。
アクセシビリティツリー的に言えば、表示されていないテキストが確認できてしまう状態です。
ということで、機能に寄った実装をしていきます。
display:none を追加
そういった場合は、display:none
を使っていきます。
.block {
--block-height: 200px;
+ display: block;
padding-top: 10px;
height: var(--block-height);
opacity: 1;
transition: all 1s;
}
.block[data-isenabled="false"] {
+ display: none;
padding-top: 0px;
height: 0px;
opacity: 0;
}
実装に加えてあげますと、
アクセシビリティツリー上では表示されなくなりましたが、 見ての通り、追加されていたアニメーションは表示されなくなってしまいました。
困ったときはドキュメント確認ということで、ドキュメントを確認してみると、
display を CSS トランジションでアニメーションさせる場合、 2 つの追加の機能が必要になります。
- @starting-style は、アニメーションする要素が最初に表示されたときからトランジションさせたいプロパティの開始値を提供します。これは予期しない動作を避けるために必要です。既定では、 CSS トランジションは要素の最初のスタイル更新時や、 display の型が none から他の型へ変更された時には発生しません。
- transition-behavior: allow-discrete は、 transition-property 宣言(または一括指定の transition)で display のトランジションを有効にするために設定する必要があります。
しっかりと書いてありました。ということで、実装していきましょう。
@starting-style + transition-behavior + transition-property
ドキュメント通りに実装すると下記のようになるでしょうか。
.block {
--block-height: 200px;
display: block;
padding-top: 10px;
height: var(--block-height);
opacity: 1;
- transition: all 1s;
+ transition-property: display, opacity, height, padding-top;
+ transition-behavior: allow-discrete;
+ transition-duration: 1s;
+ @starting-style {
+ height: 0px;
+ opacity: 0;
+ }
}
.block[data-isenabled="false"] {
display: none;
padding-top: 0px;
height: 0px;
opacity: 0;
}
実装を確認してみると、
アニメーションも実装できて、且つアクセシビリティツリー上でも表示されなくなりましたね。
まとめ
元々、display:none
はアニメーションを付けづらいイメージを持っていて、アクセシビリティツリーを考慮せず、visibility:hidden
で対応していた部分もあったのですが、より「CSS 完全に理解した」コーディングができるようになり、少し感慨深いものがあります。
補足として@starting-style
は firefox では互換性が(2024年7月22日 現在)なかったのですが、 改めて互換性を確認してみると、2024年8月6日 リリースの 129 で対応されるということで気兼ねなく実装できますので、是非参考にしていただければと思います。
この記事を書いた人
-
システムエンジニアへの夢をあきらめきれず、建築業界からIT業界へ転職。
アーティス入社後はフロントエンドエンジニアとして、webアプリケーションサービスの開発に従事している。趣味は、ラーメン屋巡り。
この執筆者の最新記事
- 2024年9月27日WEB話題の『ChatGPT o1』をコーディングに使ってみた(ChatGPT 4oとの比較)
- 2024年7月30日WEB【CSS】display:none に対してアニメーションを付けてみた
- 2024年5月21日LIFE人気のキーボード「Wooting 60HE+」を触ってみた
- 2024年3月27日WEBZodを使用したバリデーション実装ではまったこと【メールアドレス必須エラー 編】
関連記事
最新記事
FOLLOW US
最新の情報をお届けします
- facebookでフォロー
- Twitterでフォロー
- Feedlyでフォロー