display: "none"에서 왜 transition이 먹히지 않을까?

정수현·2022년 12월 26일
4
post-thumbnail

⚠️ 문제: 부드러운 효과를 위해 transition을 주고 싶은데 적용되지 않는다.

display: nonedisplay: block을 사용해서 토스트 메시지를 띄우고 없애는 코딩을 하고 있었다. 나타났다가 사라지는 효과를 부드럽게 주기 위해 transition을 사용하고자 했다. 하지만 transition이 적용되지 않고 부드럽지 못하게 뚝뚝 끊기는 현상이 발생했다.

이 이슈를 포스팅으로 다루기 위해 코드를 좀 더 단순화하여 나타내보았다.
상자에 마우스가 호버되면 display: none으로 바뀌어 상자가 보이지 않는다. 마우스가 올라가고, 내려갈 때 애니메이션이 부드럽게 적용되지 않는 모습이다.

왜 transition이 적용되지 않을까?

transition이란?

CSS 속성값이 변할 때, 값의 변화가 일정시간에 거쳐 일어나도록 하는 것이다. 엘리먼트의 두 가지 상태 사이에 변화를 줄 수 있다.이전 프로퍼티의 상태와 이후 프로퍼티의 상태를 비교해서 그 차이를 부드럽게 만들어줄 수 있다.

왜 transition이 적용되지 않을까?

이 이유를 알아내기 위해서는 브라우저의 렌더링 과정을 다시 한번 알아볼 필요가 있다.
>>브라우저 렌더링 과정 보러가기<<
html과 css가 파싱되어 DOM, CSSOM이 생성되고 이들이 합쳐져 렌더링 트리가 형성된다. 렌더링 트리가 그려질 때는 화면에 그려지지 않는 요소들은 포함하지 않는다. 예) <head> 태그, <script> 태그, display:none이 적용된 엘리먼트 등

transition이 적용되지 않는 이유는 display: none 속성을 주면 렌더링 트리에 해당 요소가 포함되지 않기 때문이다. 따라서 해당 요소는 렌더링 트리가 그려진 후의 레이아웃, 페인트 단계를 거치지 않는다.

display: none에서 display: block으로 변경이 될 때, 요소는 그제서야 렌더링 트리에 추가된다. transition은 두 상태에서 속성의 변화가 일정 기간에 걸쳐 일어나도록 하지만 display: none 상태에서는 렌더링 트리에 존재하지 않았기 때문에 transition의 시작점이 없는것이고, 비교할만한 두 상태가 없기 때문에 transition이 일어나지 않는 것처럼 보인다.

해결 방법

scale 값을 변경하자!

transform : scale(1)에서 transform: scale(0)로 변경해주었다.
scale(0)이 되면 작아져 보이지 않기 때문이다.

opacity를 주자!

요소를 투명하게 만들어서 없는 것처럼 보이게 하는 것이다.
스르륵 잘 사라지고 있다.

하지만 scale, opacity 모두 요소가 보이지 않는 상태에서도 스크린 리더가 읽어버린다.

요소를 시각적으로 숨길 때 스크린리더 또한 읽히면 안되는 경우가 많다. 이를 위해서는 visibility 속성을 사용하면 된다. display:none과 달리 visibility:hidden은 화면에서는 보이지 않아도 자신의 공간을 계속 차지하고 있다. visibility 속성을 가진 요소는 렌더링 트리 형성 이후 레이아웃 계산을 끝마쳤다는 것이다. 따라서 visibility:hidden 상태와 visibility:visible 상태를 서로 비교가 가능하고, transition 애니메이션을 사용할 수 있다!

  • visibility: hidden -> 스크린리더가 읽지 않는다.

opacity와 visibility속성을 같이 주어 요소가 보이지 않을 때는 스크린리더가 읽지 못하게 하고, transition을 사용하여 부드러운 효과도 주었다.

결과

프로젝트 토스트 메시지에는 scale을 조정하는 방법을 사용하여 좀 더 역동적인 효과를 줘봤다.

0개의 댓글