> 웹 프론트엔드 > CSS 튜토리얼 > 성능을 저하시키는 두 줄의 CSS(fps ~ ps)

성능을 저하시키는 두 줄의 CSS(fps ~ ps)

WBOY
풀어 주다: 2024-09-03 11:09:21
원래의
955명이 탐색했습니다.

최근에 Learn WCs를 출시했는데, 보신 분이라면 배경에서 색상이 지정된 원이 화면을 가로질러 대각선으로 움직이는 애니메이션을 보셨을 것입니다. 다음과 같습니다:

Chrome과 Safari에서는 잘 작동하지만 Firefox에서는 성능이 심하게 저하되는 것을 느꼈습니다.

성능이 너무 나빠서 Firefox에서 이 애니메이션을 바로 비활성화했습니다.

애니메이션은 어떻게 작동하나요?

애니메이션은 두 개의 중첩된 div를 사용하여 제작되었습니다. 외부 div는 사이트 본문 태그의 첫 번째 하위 항목입니다.

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

    <!-- Rest of content -->
</body>
로그인 후 복사

.ground-gradient 요소는 상위 컨테이너의 전체 너비와 높이에 걸쳐 있는 그라데이션을 생성하는 역할을 합니다. 다음과 같습니다:

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

외부 .Background-mask는 두 가지 역할을 담당합니다.

  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을 페이지에 렌더링하는 방법에 대해 너무 자세히 설명하지 않고도(여기서 간략하게 설명했지만) 몇 가지 단계를 거치게 됩니다. 우리가 관심을 갖는 세 가지 단계는 다음과 같습니다.

  • 레이아웃 - 브라우저가 페이지 요소의 크기와 위치를 계산하는 경우
  • 페인트 - 이미지, 색상, 그림자 등 페이지의 모든 시각적 측면을 그립니다.
  • 복합 - 올바른 순서로 요소를 서로 겹쳐서 배치

파이프라인의 순서는 다음과 같습니다.

레이아웃 → 페인트 → 합성

레이아웃 및 페인트 프로세스는 CPU 집약적일 수 있으므로 CSS가 파이프라인의 단계를 트리거하는 횟수를 줄이는 것이 중요합니다*.* 브라우저는 특정 속성에 대한 성능을 최적화하여 어느 정도 도움을 줍니다. 렌더링 파이프라인의 전체 단계를 건너뛰면 다른 사람들이 하드웨어 가속을 활용하여 계산을 CPU에서 GPU로 이동할 수 있습니다.

번역 및 불투명도와 같은 특정 속성에 애니메이션을 적용하면 레이아웃 트리거를 방지하고 하드웨어 가속을 사용합니다.

안타깝게도 마스크 위치에 애니메이션을 적용할 때는 그렇지 않습니다. 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 속성에 애니메이션을 적용하는 대신 번역과 같은 보다 성능이 뛰어난 속성에 의존해야 했습니다.

해결책은 마스크를 24픽셀씩 이동하는 것이 아니라 번역 속성을 사용하여 전체 배경 요소를 이동하는 것이었습니다.

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.

위 내용은 성능을 저하시키는 두 줄의 CSS(fps ~ ps)의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

원천:dev.to
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿