작업을 하면서 시각적으로 요소가 변화해야 하는 상황이 생기게 되는데 초반에는 기능적인 부분만 중점으로 생각하여 transition
이라는 것을 잘 사용하지 않았었다. 하지만 시각적으로도 부드럽게 변화하는 모습을 구현하기 위해 해당 속성을 사용하게 되었고, display
를 block
, none
으로 적용했을 경우 transition
이 정상적으로 작동하지 않는다는 것을 발견하였다. 이 글에서는 그 경우에 대체할 수 있는 방안에 대하여 작성해보고자 한다.
transition
은 속성이 변화하는 과정을 시각적으로 확인할 수 있도록 하는 속성이다. transition-property
, transition-duration
, transition-timing-function
, transition-delay
를 포함하는 단축속성으로, 사용법은 다음과 같다.
/* Apply to 1 property */
/* property name | duration */
transition: margin-left 4s;
/* property name | duration | delay */
transition: margin-left 4s 1s;
/* property name | duration | timing function | delay */
transition: margin-left 4s ease-in-out 1s;
/* Apply to 2 properties */
transition: margin-left 4s, color 1s;
/* Apply to all changed properties */
transition: all 0.5s ease-out;
/* Global values */
transition: inherit;
transition: initial;
transition: unset;
위의 방법대로 display
none
, block
을 적용하여 작성한 코드는 이런식이다.
메뉴 버튼을 클릭하면 화면 왼쪽에서 서랍 메뉴가 부드럽게 나타나는 것을 구현하고 싶었다. 하지만 예상과는 다르게 그런 모션이 하나도 나타나고 있지 않은 것을 확인할 수 있다.
이유가 무엇일까 찾아보니 브라우저가 render tree를 생성하는 과정에서 발생하는 문제였다. render tree는 DOM과 CSSOM을 합하여 화면에 출력될 요소들을 결정하며, 보이지 않아도 되는 내용(meta
, script
등)은 출력에 반영되지 않는다. 그 과정에서 일부 노드는 CSS를 통해 숨겨지는데, display: none
속성이 여기에 해당한다.
display: none
은 요소가 보이지 않게 하는 것 뿐만 아니라 레이아웃에도 포함되지 않도록 하기 때문에 render tree에서 완전히 사라진다. 그 상태에서 display: block
으로 변경되면 render tree에 없던 것이 추가되는 것이므로 요소가 변화하는 과정을 보여줄 수 없는 것이다.
즉 transition
은 render tree에 존재하는 요소의 변화 과정을 보여주는 것인데, display: none
은 render tree에서도 사라지도록 하는 속성이므로 transition
이 제대로 동작할 수 없게 된다.
그렇다면 시각적으로 요소를 보였다 안보였다 할 수 있는 다른 방법은 무엇이 있을까?
그 방법은 visibility
속성을 사용하는 것이다. visibility
는 요소를 보이지 않게 만들지만 레이아웃에서 공간은 그대로 차지하고 있기에 render tree에 비어있는 상자로 렌더링 되게 된다.
이제 transition
이 정상적으로 작동하는 것이 보인다.
📕 참조