CSS 최적화가 필요한 이유
CSS는 렌더링을 막는다.
CSS의 존재만으로도, CSS가 파싱되기 전까지 브라우저는 렌더링이 지연된다. 만약 브라우저가 CSS가 없는 페이지를 그대로 노출하면, 스타일적용이 되지않은 페이지가 나타나기 때문이다. 이를 FOUC
라고 불린다.
CSS는 HTML 파싱도 막을 수 있다
브라우저가 CSS가 파싱되기 전까지 콘텐츠를 보여주지 않더라고, HTML의 로딩된 부분만을 일단 보여줄 수 있다. 그러나 스크립트의 경우 async
defer
가 없다면 파싱을 막게 된다. 스크립트는 잠재적으로 페이지를 조작할 여자기 있기때문에 브라우저는 스크립트 실행에 매우 주의를 기울이기 때문이다.
스크립트가 페이지의 스타일에 영향을 줄 수 있기 때문에, 만약 브라우저가 CSS 관련 작업을 진행중이라면, 이 작업이 완료될 때까지 기다렸다가 스크립트를 실행할 것이다. 스크립트가 실행되기 전까지 문서 파싱을 할 수 없기 때문에, CSS는 더이상 렌더링을 차단하는 요소로 작용하지 않는다. 문서의 외부 스타일시트 및 스크립트 순서에 따라서 때로는 HTML 파싱도 중지할 수 있다.
따라서 파싱이 차단되는 상황을 피하기 위해서는 CSS를 최대한 빨리 불러와야하고, 리소스를 최적의 순서로 불러와야한다.
CSS 최적화
CSS 사이즈 최소화
CSS minify
사용하지 않는 CSS 제거
CSS 우선순위 정하기
- critical css 를 인라인으로 처리하여, CSS 로딩하는 시간을 아끼기
- CriticalCSS와 같은 자동화 툴이 있음
non-critical CSS는 비동기로 불러오기
1 2 3 4 5 6
<link rel="stylesheet" href="non-critical.css" media="print" onload="this.media='all'" />
media="print"
는 사용자가 페이지를 프린트하려고 하는 경우에만 불러오는 스타일시트로, 렌더링에는 영향을 미치지 않는다.onload="this.media='all'"
는 스타일시트 로드가 완료되면 미디어 속성을 다시all
로 바꾸면서 스타일시트가 적용되도록 하는 것이다.
효과적인 CSS 애니메이션
페이지에 애니메이션이 있는 요소가 있는 경우, 브라우저는 종종 문서 내 요소의 위치와 크기를 재계산한다. 예를 들어 어떤 요소의 너비를 바꾸게 되면, 그 자식 요소들까지 영향을 미치면서 페이지 내부에서 큰 레이아웃 변경이 발생할 수 있다. 이 레이아웃의 크기가 커질 수록 성능에 안좋은 영향을 미칠 것이다.
height
width
대신transform: scale()
사용하기top
right
bottom
left
대신transform :translate()
를 사용한다.- 배경에 blur를 먹이고 싶다면, opacity 대신 blur된 이미지를 불러오는 게 낫다.
좀더 자세한 설명
CSS가 적용되는 4가지 순서
Styles
브라우저가 객체에 적용할 스타일의 값을 계산, 재계산한다.
Layout
position display overflow width height min-width min-height padding margin border top bottom left right font white-space line-height vertical-align float clear Paint
color background visibility text-decoration border-radius border-style box-shadow Composite
transform, opacity
위 순서에 따르면, width나 height 등 Layout
속성을 바꾸면, Paint
, Composite
순서를 거치기 때문에 성능 저하가 이루어진다. 이것을 Reflow
라고 한다. 또한 Paint
속성을 바꾸면 Composite
를 거치기에 성능저하가 이루어지고, 이것을 Repaint
라고 한다.
따라서 성능을 최대로 올리려면 Composite
속성만 바꾸는 것이 최고의 방법이다.
GPU 가속
GPU 가속을 이용하여 애니메이션 프레임을 최대로 끌어올릴 수 있다. will-change 옵션을 사용하여 GPU 가속을 사용할 수 있다. 브라우저에게 예상되는 변화에 대한 힌트를 미리 제공하여 실제 요소가 변화되기 전에 브라우저가 적절하게 최적화할 수 있도록 하는 방법이다. 하지만 과도하게 사용할 경우 많은 기기 자원을 소모한다. 따라서 적절히 사용한다.
1
2
3
4
5
6
.app-menu {
-webkit-transform: translateX(-100%);
transform: translateX(-100%);
transition: transform 300ms linear;
will-change: transform;
}
HTML 최적화하기
이벤트가 끝나면, 해당 이벤트를 위한 html class는 제거해줘야한다. 클래스를 추가하는 것은 자식요소의 DOM Tree를 변경하는 성능저하를 유발하기 때문이다.
contain 속성
contain은 브라우저에 요소와 하위 요소가 그 문서 트리와 무관한 것으로 간주된다는 것을 알려주는 속성이다. 페이지의 하위트리와 나머지 페이를 분리한다. 그런다음, 브라우저는 페이지에서 독립된 부분의 렌더링을 최적화하여 성능을 향상 시킬 수 있다.
contain
은 페이지 내부에서 독립적으로 작동하는 위젝 등에서 효과적이다. 위젯 내부의 변경사항이 바깥으로 전파되는 것을 막을 수 있다.
variable font로 폰트파일 크기 줄이기
Variable Font는 모든 너비, weight, style에 대해서 별도의 폰트파일이 아니라 하나의 파일에 여러가지 다양한 폰트를 통합해줄 수 있도록 한다. CSS와 단일 @font-face
참조로 지정된 글꼴의 다양한 변형에 액세스할 수 있다.
이는 글꼴의 여러 변형이 필요한 파일 크기를 획기적으로 줄일 수 있다. 일반, 볼드, 기울임꼴 폰트 버전을 각각 로딩하는 대신 모든 정보가 포함된 하나의 단일 파일을 로딩할 수 있다.
CSS 선택자 속도는 걱정안해도 된다.
브라우저는 셀렉터는 오른쪽에서 왼쪽으로 읽기에 자식에서부터 부모로 거쳐서 올라가게 된다. 예를들어 nav a {}
는 먼저 a를 찾고, 그 중 부모가 nav 인것을 찾는다. 따라서 선택자는 짧은게 더 빠르다.
하지만, 브라우저가 선택자를 매칭시키는 속도는 매우 빠르기에 걱정할 필요가 없다.
출처
https://yceffort.kr/2021/03/improve-css-performance