ホームページ  >  記事  >  ウェブフロントエンド  >  パフォーマンスを低下させる 2 行の CSS (fps から ps)

パフォーマンスを低下させる 2 行の CSS (fps から ps)

WBOY
WBOYオリジナル
2024-09-03 11:09:21923ブラウズ

私は最近「Learn WCs」をリリースしました。これをご覧になった方は、色付きの円が画面上で斜めに動く背景のアニメーションに気づいたでしょう。次のようになります:

Chrome と Safari では問題なく動作しますが、Firefox ではパフォーマンスが大幅に低下することに気付きました。

パフォーマンスが非常に悪かったので、Firefox でこのアニメーションをすぐに無効にしました。

アニメーションはどのように機能しますか?

アニメーションは 2 つのネストされた div を使用して構築されます。外側の div は、サイトの body タグの最初の子です。

<body>
    <div class="background-mask">
        <div class="background-gradient"></div>
    </div>

    <!-- Rest of content -->
</body>

.background-gradient 要素は、親コンテナの幅と高さ全体にわたるグラデーションを作成します。同様に:

The Two Lines of CSS That Tanked Performance (fps to ps)

外側の .background-mask は 2 つの役割を果たします:

  1. 位置を固定に設定し、コンテナがビューポートの寸法全体を埋めるようにします。
  2. グラデーション上に点線のマスクを作成します

これにより、ドットの色がその直下のグラデーションの色になることが保証されます。

The Two Lines of CSS That Tanked Performance (fps to ps)

上で説明したすべての 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 回以上ペイントがトリガーされていました。

The Two Lines of CSS That Tanked Performance (fps to ps)

これだけペイント数が多くても、Chrome 上のアニメーションはスムーズに感じられます。ただし、Firefox では非常に動作が不安定に感じます。厄介なことに、Firefox のペイント数を測定する方法が見つからなかったので、Firefox のパフォーマンスの低さについての私の推測は完全に推測です。

私が気づいたのは、アニメーションは小さなデバイスでは問題ありませんが、画面のサイズが大きくなるにつれて悪化するということです。私の実際の理論は、Firefox は 24x24 マスクごとにレイアウト トリガーをバッチ処理しないため、24x24 マスクがさらに多く存在すると FPS が低下するというものです。繰り返しますが、ここで私は完全に間違っている可能性があります。

これをどうやって修正しましたか?

mask-position のような不適切に最適化された CSS プロパティをアニメーション化する代わりに、translate などのよりパフォーマンスの高いプロパティに頼る必要がありました。

解決策はマスクを 24 ピクセル移動することではなく、translate プロパティを使用して背景要素全体を移動することでした。

From an abstract standpoint, this is how the animation looks:

Here’s the two line change in the CSS:

/* --mask-size = 24px */

@keyframes mask-move {
    0% {
        transform: translate(calc(var(--mask-size) * -1), calc(var(--mask-size) * -1));
    }

    100% {
        transform: translate(0px, 0px);
    }
}

The browser no longer animates the mask-position, which triggered a layout on each frame. Even though the background moves on each frame, through translate it doesn’t trigger a layout or a paint. You can see that the only paints twice, down from 1,000+ every minute.

The Two Lines of CSS That Tanked Performance (fps to ps)

Eagle-eyed viewers will have spotted a problem. If you remember, the height and width of the background fills the viewport. Shifting the background left and up by 24px leaves us with this empty space in the viewport.

The Two Lines of CSS That Tanked Performance (fps to ps)

Solving it is as simple as adding the mask size to the width and height of the container:

.background-mask {
    --mask-size: 24px;

    width: calc(100% + var(--mask-size));
    height: calc(100% + var(--mask-size));
}

Let’s take a look again in Firefox:

It may not be a perfect solution, but it’s always a little satisfying pulling off a fun smoke and mirrors CSS trick.

以上がパフォーマンスを低下させる 2 行の CSS (fps から ps)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。