Published on

display block 을 했을때 transition 이 왜 안될까

Authors
  • avatar
    Name
    piano cat
    Twitter

display block을 할때 왜 transition이 작동하지 않았을까

결론부터 말하면, display 속성은 레이아웃을 결정하는 속성으로 이는 변화의 중간 단계를 가질수 없기 때문이다. 즉, display 속성은 none 에서 block으로 또는 그 반대로 바로 전환되기 때문에 중간단계를 보여주는 transition의 효과를 적용할수 없다.

위 내용을 좀 더 자세히 설명해보면,

렌더링 트리를 생성하기 위해 브라우저의 작업 순서는

  1. DOM 트리의 루트부터 시작하여 표시된 각 노드를 트래버스한다.
  2. 표시되는 각 노드에 대해 적절하게 일치하는 CSSOM 규칙을 찾아 적용한다.
  3. 콘텐츠 및 계산된 스타일과 함께 표시되는 노드를 내보낸다.

첫번째 순서에서 Dom 이 생성되었지만 이후 CSSOM 규칙에서 display none을 확인하고, display none 요소를 완전히 숨기게 되어 요소가 보이지 않고 레이아웃에 포함되지 않도록 렌더링 트리에서 요소를 완전히 제거하게 된다.

그렇기 때문에 transition 과 같은 애니메이션 효과는 display 속성에 적용할수가 없다.

transition을 가능하게 하는 어떤 방법을 사용해야할까

opacity

opacity나 visibility 속성을 사용하여 transition 효과를 적용할 수 있다. opacity: 0 -> 1 로 변경하여 적용할 수 있다. 하지만 이와같은 방법은 완전한 해결책은 아니다. opacity를 0으로 설정하면 요소는 보이지않지만 페이지 레이아웃에 공간을 차지하게 된다. 그렇기때문에 만약 버튼을 opacity로 가렸다면 그부분에 버튼 요소가 클릭이 가능하다.

visibility

visibility를 사용하면, 요소도 보이지않고 가려진 버튼도 클릭이 안되게 할수 있다. visibility: hidden -> visible 으로 변경하여 적용한다. CSS만으로 처리하는 방법으로는 이 방법이 가장 효과적일 수 있다. 이 방법은 layout 요소에 남아있지만 빈 박스요소로 존재한다는 단점이 있지만, 화면에 안보이고, 클릭할수도 없는 방법을 찾는 다면 이 방법을 사용하면 된다.

javascript 를 활용한 방법

또한 javascript를 사용한 방법도 있는데,

function fadeIn(element) {
  element.style.display = 'block'
  let op = 0.1 // 초기 투명도
  let timer = setInterval(function () {
    if (op >= 1) {
      clearInterval(timer)
    }
    element.style.opacity = op
    element.style.filter = 'alpha(opacity=' + op * 100 + ')'
    op += op * 0.1
  }, 10)
}

function fadeOut(element) {
  let op = 1 // 초기 투명도
  let timer = setInterval(function () {
    if (op <= 0.1) {
      clearInterval(timer)
      element.style.display = 'none'
    }
    element.style.opacity = op
    element.style.filter = 'alpha(opacity=' + op * 100 + ')'
    op -= op * 0.1
  }, 10)
}

위처럼 Dom에 접근하여 opacity를 통해 점진적으로 투명도를 높여서 보이게 만드거나 사라지게 할 수 있다. 이 방법은 자바스크립트를 작성해야하는 단점이 있지만 layout요소에 남기지 않고 사라지게 만드는 방법으로는 적합한 방법이다.

참고