私は最近、Learn WCs をリリースしました。これをご覧になった方は、色付きの円が画面上で斜めに移動する背景のアニメーションに気づいたかもしれません。次のようになります:
Chrome と Safari では問題なく動作しますが、Firefox ではパフォーマンスが大幅に低下することに気付きました。
パフォーマンスが非常に悪かったので、Firefox でこのアニメーションをすぐに無効にしました。
アニメーションは 2 つのネストされた div を使用して構築されます。外側の div は、サイトの body タグの最初の子です。
.background-gradient 要素は、親コンテナの幅と高さ全体にわたるグラデーションを作成します。同様に:
外側の .background-mask は 2 つの役割を果たします:
これにより、ドットの色がそのすぐ下のグラデーションの色になります:
上で説明したすべての CSS は次のとおりです:
.background-mask { --mask-size: 24px; /* Position Styles */ position: fixed; width: 100%; height: 100%; z-index: -1; /* Mask Styles */ mask-image: radial-gradient(black 2px, transparent 2px); mask-size: var(--mask-size) var(--mask-size); mask-position: 0px 0px; animation: mask-move 3s infinite linear; } .background-gradient { background: var(--red); background-image: var(--gradient); width: 100%; height: 100%; } @keyframes mask-move { 0% { mask-position: 0px 0px; } 100% { mask-position: var(--mask-size) var(--mask-size); } } @media (prefers-reduced-motion: reduce) { .hero-background-mask { animation: none; } }
CSS のマスクについて詳しく知りたい場合は、Ahmad Shadeed によるこの包括的な投稿をお勧めします
すべての CSS プロパティが同じようにアニメーションするわけではありません。ブラウザーがどのように HTML をページにレンダリングするかについては詳しく説明しませんが (概要はここで説明しましたが)、ブラウザーが通過する段階はいくつかあります。私たちが興味がある 3 つの段階は次のとおりです:
パイプラインの順序は次のようになります:
レイアウト → ペイント → コンポジット
レイアウトとペイントのプロセスは CPU に負荷をかける可能性があるため、CSS がパイプラインのステージをトリガーする回数を減らすように努めることが重要です*。ブラウザは、特定のプロパティのパフォーマンスを最適化することで部分的に役立ちます。レンダリング パイプラインのステージ全体をスキップしたり、ハードウェア アクセラレーションを利用して計算を CPU から GPU に移動したりできます。
translate や opacity などの特定のプロパティをアニメーション化すると、レイアウトのトリガーが回避され、ハードウェア アクセラレーションが使用されます。
残念ながら、マスク位置をアニメーション化する場合は当てはまりません。 Chrome を見てみると、背景 div のペイント数がフレームごとに増加していることがわかりました。数秒後、すでに 1,000 回以上ペイントがトリガーされていました。
これだけペイント数が多くても、Chrome 上のアニメーションはスムーズに感じられます。ただし、Firefox では非常に動作が不安定に感じます。腹立たしいことに、Firefox でペイント数を測定する方法が見つからなかったので、Firefox のパフォーマンスの低さについての私の推測はまったくの推測です。
私が気づいたのは、アニメーションは小さなデバイスでは問題ありませんが、画面のサイズが大きくなるにつれて悪化するということです。私の実際の理論は、Firefox は 24x24 マスクごとにレイアウト トリガーをバッチ処理しないため、24x24 マスクがさらに多く存在すると FPS が低下するというものです。繰り返しますが、ここで私は完全に間違っている可能性があります。
マスク位置のような不適切に最適化された CSS プロパティをアニメーション化する代わりに、translate のようなよりパフォーマンスの高いプロパティに頼る必要がありました。
解決策は、マスクを 24 ピクセル移動することではなく、translate プロパティを使用して背景要素全体を移動することでした。
抽象的な観点から見ると、アニメーションは次のようになります:
CSS の 2 行の変更は次のとおりです:
/* --mask-size = 24px */ @keyframes mask-move { 0% { transform: translate(calc(var(--mask-size) * -1), calc(var(--mask-size) * -1)); } 100% { transform: translate(0px, 0px); } }
ブラウザは、各フレームでレイアウトをトリガーするマスク位置をアニメーション化しなくなりました。背景はフレームごとに移動しますが、移動によってレイアウトやペイントはトリガーされません。ペイントが 2 回のみで、毎分 1,000 回から減少していることがわかります。
鋭い観察力を持つ視聴者は問題を発見するでしょう。覚えていると思いますが、背景の高さと幅がビューポート全体に表示されます。背景を左と上に 24 ピクセル移動すると、ビューポート内にこの空きスペースが残ります。
これを解決するには、コンテナの幅と高さにマスク サイズを追加するのと同じくらい簡単です:
.background-mask { --mask-size: 24px; width: calc(100% var(--mask-size)); height: calc(100% var(--mask-size)); }
Firefox でもう一度見てみましょう:
完璧な解決策ではないかもしれませんが、楽しい スモーク アンド ミラー CSS トリックを実行すると、常に少し満足のいくものになります。
免責事項: 提供されるすべてのリソースの一部はインターネットからのものです。お客様の著作権またはその他の権利および利益の侵害がある場合は、詳細な理由を説明し、著作権または権利および利益の証拠を提出して、電子メール [email protected] に送信してください。 できるだけ早く対応させていただきます。
Copyright© 2022 湘ICP备2022001581号-3