ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 패딩이 적용된 블록 엘리먼트에 높이로 트랜지션하기
    짧은경험기 2023. 8. 1. 19:36

    개요

    패딩이 적용된 블록 엘리먼트에 높이를 기준으로 트랜지션을 하려고 시도하면 두 가지 문제가 발생한다.

    1. 시작 상태에 height 속성을 0으로 지정하더라도, 패딩에 의하여 공간이 확보되어 해당 엘리먼트 안의 내용물 보인다.
    2. 트랜지션 롤백 과정의 마지막에  엘리먼트 안의 내용물이 감춰지지 않는다.

    예시

    <style>
        .container {
            background: darkcyan;
            color: white;
            padding: 1em;
            width: 150px;
            height: 0px;
        }
    </style>
    
    <div class="container">
    	Hello World
    </div>

    블록 엘리먼트에 패딩을 1em만큼 주고 height을 0으로 하면 어떤 결과가 나올까? 다음 이미지를 보자.

    패딩 1em, height 0

    왜 이런 결과가 나온 걸까? 패딩에 의하여 블록 엘리먼트의 공간이 확보되고 height: 0 속성이 무시된다. 엘리먼트는 최소 padding의 top, bottom 크기만큼의 높이를 갖게 되는 것이다. 그 결과, 가리기를 원했던 글이 보인 것이다. 이 상태에서 height을 변경하는 트랜지션을 적용시켜도 결과가 달라지지 않는다.

    시작 지점에서 글자가 보이니, 롤백에서도 글자가 보이는 것으로 마무리

    해결 - 엘리먼트를 래핑해서 사용

    해결 방법은 다음과 같다. 블록 엘리먼트를 둘러싼 엘리먼트를 만들고, container 클래스를 부모 엘리먼트에 적용한다. padding은 제외하고 position absoulte를 적용한다. 자식 엘리먼트에 padding 수치만큼 margin을 넣는다.

    <style>
        .container {
        	position: absolute;
            background: darkcyan;
            color: white;
            width: 150px;
            height: 0px;
    
            transition: all 1s;
        }
    
        .inner {
            margin: 1em;
        }
    
        .show {
            height: 150px;
        }
    </style>
        
    <body>
        <button type="button" onclick="startTransition()">트랜지션시작</button>
        <div class="container">
            <div class="inner">
                Hello World
            </div>
        </div>
        <script>
            function startTransition() {
                const el = document.querySelector('.container');
                el.classList.toggle('show');
    
                setTimeout(() => {
                    el.classList.toggle('show');
                }, 1000);
            }
        </script>
    </body>

    그 결과는 다음과 같다.

    컨텐츠에 마진으로 여백이 생겼다. 그러나 height를 고정했기에 마지막 문장이 짤렸다.

    결과를 보면, 패딩으로 의도했던 여백이 마진으로도 잘 동작하는 것을 알 수 있다. 만약 부모 컨테이너를 position absoulte로 설정하는 것이 아니라 기본 position인 static이었다면, 생각한것처럼 제대로 안될 수도 있다. 자식 컨테이너의 margin에 의하여 부모 컨테이너가 밑으로 내려오는 상황이 발생한다.

     

    그리고, 트랜지션 종료 시점의 height를 150px로 고정했기에, 마지막 문장이 짤리는 문제를 볼 수 있다.

    개선 - 콘텐츠 높이에 따라 유동적으로

    위 코드에서, 트랜지션 종료에 height: 150px로 고정하고 있다. 컨텐츠 높이에 따라 height를 일일이 지정할 순 없을 것이다.

    컨텐츠에 따라 높이가 유동적으로 변하는 상황을 가정하고 접근해 보자. 어떻게 해야 할까? 완벽한 해결 방법은 아니지만, 어찌 되었든 콘텐츠 높이에 상한선이 있다고 가정하고 height 대신 max-height 속성을 사용할 수 있다. height: 0을 max-height: 0으로, height: 150px를 max-height: 500px(최고치)로 변경해 보자.

    예상했던 그대로 나온다.

    문제점은 최대 높이를 기준으로 트랜지션이 진행되기에 펼쳐지는 속도가 빠르다. 경험상 max-height를 기준으로 시간을 재조정하는 방향에서 자연스럽다는 느낌을 받았다.

     

    댓글

Designed by Tistory.