css를 통해 animation을 사용하거나 마우스오버 혹은 특정 버튼을 클릭했을 때 클래스 추가하여 transform을 조정하게 될 경우 영역이 깜빡이거나 잠시 흐려지는 현상을 경험한 적이 있을 것이다.
1. CSS핵 (translateZ or translate3d) 사용
위와 같은 부자연스러운 transform, animation 현상이 발생하는 것을 해결하기 위해 '*하드웨어 가속'을 활성화해 대상이 되는 엘리먼트를 빠르게 렌더링 처리하는 방법을 사용했다.
*하드웨어 가속
- 하드웨어 가속은 중앙처리장치(CPU)가 하는 일을 그래픽 처리 장치(GPU)가 분담하여 처리해서 컴퓨터의 성능을 최대한으로 끌어올리고 브라우저 렌더링을 보다 빠르게 할 수 있게 만든다.
일반적인 css animation, transform, transition 속성에는 하드웨어 가속이 적용되지 않기 때문에 브라우저를 속여서 강제로 3D 처리를 하도록 브라우저에 지시해 하드웨어를 가속화 하는 방법을 사용했다.
그 방법이 translateZ 혹은 translate3d이다.
transform: translate3d(0,0,0);
transform: translateZ(0)
하지만 이러한 방법은 RAM이나 그래픽 처리 장치(GPU)의 사용량을 커지게하여 페이지에 병목 현상을 줘서 오히려 악영향을 끼치게 한다.
2. will-change
위 css핵을 대체할 수 있는 새로운 css 속성이 생겼다. 그 속성이 will-change 이다.
속성명 그대로 어떤 속성이 변경이 될 것인지 미리 엘리먼트에 적용하여 브라우저가 해당 css를 읽을 때 변경 될 속성을 알게하여 미리 그 변경에 대비할 수 있게 하는 것이다.
will-change: auto; /* 기본 값 */
will-change: scroll-position; /* 스크롤 위치가 변경 될 예정 */
will-change: contents; /* 요소의 컨텐츠 내용이 변경 될 예정 */
/* 특정 css 속성 적용 */
will-change: transform; /* transform 속성이 변경 될 예정 */
will-change: opacity; /* opacity 속성이 변경 될 예정 */
will-change: left, top; /* left, top 값이 변경 될 예정 */
will-change: transform, opacity
적용예시)
<style>
.thmb {width:100px; height:100px; border-radius:50%; overflow:hidden;}
.thmb img {transition:0.3s transform; will-change:transform;}
.thmb:hover img {transform:scale(1.2);}
</style>
<!-- .thmb 마우스오버시 img 확대 -->
<div class="item">
<div class="thmb">
<img src="picture.jpg">
</div>
</div>
위와 같은 소스상 .thmb에 마우스 오버시 img가 확대되는 효과를 구현하고자 할 때
transform을 통해 scale을 변경할 img태그에 미리 will-change 속성을 적용해줄 수 있다.
3. will-change 사용상의 주의사항
브라우저 성능을 최적화 하겠다고 will-change를 과다하게 사용하면 안된다.
브라우저는 기본적으로 브라우저가 사용할 수 있는 최적화를 최대한으로 적용한다.
그리고 브라우저가 적용한 최적화를 삭제하고 가능한한 빨리 브라우저가 처리해야할 다른 작업들을 실행한다.
그런데 will-change를 선언하게 되면 이러한 브라우저의 특성을 무시하고 브라우저가 최적화에 더 많은 시간을 쏟게 한다.
즉, 오히려 브라우저 최적화에 악영향을 끼친다.
그렇기 때문에 will-change는 정말 필요한 경우에만 적절하게 사용해야한다.
4. 자바스크립트를 이용한 will-change 적용
3번과 같은 브라우저 최적화 이슈가 있기 때문에 가능하면 will-change를 사용할 때는 자바스크립트를 사용해서 필요한 순간에만 적용하고 다시 will-change를 초기화 시키는 방법을 적용할 수 있다.
<!-- .thmb 마우스오버시 img 확대 -->
<div class="item">
<div class="thmb">
<img src="picture.jpg">
</div>
</div>
<script>
// 클릭할 때 애니메이션을 재생할 엘리먼트를 선택합니다.
var item = document.querySelector('.item');
// 엘리먼트의 조상 요소에 마우스 커서가 올라가면 will-change를 설정한다.
item.addEventListener('mouseenter', hintBrowser);
// 엘리먼트의 조상 요소에 마우스 커서가 내려가면 will-change를 초기화한다.
item.addEventListener('mouseleave', removeHint);
function hintBrowser() {
this.querySelector('img').style.willChange = 'transform, opacity';
}
function removeHint() {
this.querySelector('img').style.willChange = 'auto';
}
</script>
참조
https://dev.opera.com/articles/ko/css-will-change-property/
'Frontend > CSS' 카테고리의 다른 글
[css 이슈] ios 버튼 연속 클릭시 확대되는 이슈 해결 (touch-action) (0) | 2023.10.10 |
---|---|
[css 단위] dvh, svh, lvh (모바일 주소 표시줄 영역 대응) (0) | 2023.07.14 |
[css 이슈] 크롬에서 이미지가 흐리게 보일 때 처리 방법(image-rendering) (0) | 2022.05.17 |
[css 응용] 스크립트 없이 드롭다운 메뉴 만들기 (drop down menu) (0) | 2022.01.11 |
[css 속성] env() (아이폰 노치 영역 대응) (0) | 2021.08.24 |