높이에 애니메이션 적용: auto; CSS에 (및 기타 고유한 크기 조정 키워드 포함)

interpolate-size 속성 또는 calc-size() 함수를 사용하여 길이에서 고유 크기 조정 키워드로의 원활한 전환 및 애니메이션을 사용 설정하고 그 반대로 전환할 수 있습니다.

게시일: 2024년 9월 17일

소개

자주 요청되는 CSS 기능height: auto로 애니메이션을 적용하는 기능입니다. 이 요청의 약간 다른 변형은 height 대신 width 속성을 전환하거나 min-content, max-content, fit-content와 같은 키워드로 표현되는 다른 기본 크기로 전환하는 것입니다.

예를 들어 다음 데모에서는 아이콘 위로 마우스를 가져갈 때 라벨이 자연스러운 너비로 부드럽게 애니메이션되도록 하는 것이 좋습니다.

사용된 CSS는 다음과 같습니다.

nav a {
    width: 80px;
    overflow-x: clip;
    transition: width 0.35s ease; /* 👈 Transition the width */

    &:hover,
    &:focus-visible {
        width: max-content; /* 👈 Doesn't work with transitions */
    }
}

transitionwidth 속성을 전환하도록 선언되고 width: auto:hover에 선언되었지만 원활한 전환이 발생하지 않습니다. 대신 변경사항이 갑작스럽습니다.

interpolate-size를 사용하여 크기 조절 키워드 간에 애니메이션 처리

브라우저 지원

  • Chrome: 129
  • Edge: 지원되지 않음
  • Firefox: 지원되지 않음
  • Safari: 지원되지 않음

소스

CSS interpolate-size 속성을 사용하면 CSS 고유 크기 조정 키워드의 애니메이션과 전환을 허용할지 여부를 제어할 수 있습니다.

기본값은 numeric-only이며 보간을 사용 설정하지 않습니다. 속성을 allow-keywords로 설정하면 브라우저에서 이러한 키워드에 애니메이션을 적용할 수 있는 경우 길이에서 CSS 고유 크기 조정 키워드로의 보간을 선택합니다.

사양에 따라:

  • numeric-only: <intrinsic-size-keyword>은 보간할 수 없습니다.
  • allow-keywords: 두 값 중 하나가 <intrinsic-size-keyword>이고 다른 하나가 <length-percentage>인 경우 두 값을 보간할 수 있습니다. […]

interpolate-size 속성은 상속되는 속성이므로 :root에서 선언하여 전체 문서의 고유 크기 조정 키워드 간에 전환할 수 있습니다. 권장되는 방법입니다.

/* Opt-in the whole page to interpolate sizes to/from keywords */
:root {
    interpolate-size: allow-keywords; /* 👈 */
}

다음 데모에서는 이 규칙이 코드에 추가됩니다. 따라서 width: autowidth: auto 사이의 애니메이션이 지원되는 브라우저에서 제대로 작동합니다.

선택기를 좁혀 수신 동의 도달범위 제한

allow-keywords 선택을 문서의 하위 트리로만 제한하려면 선택기를 :root에서 타겟팅하려는 요소로만 조정합니다. 예를 들어 페이지의 <header>가 이러한 유형의 전환과 호환되지 않는 경우 다음과 같이 <main> 요소와 그 하위 요소로만 선택을 제한할 수 있습니다.

main { /* 👈 Scope the opt-in to only <main> and its descendants */
    interpolate-size: allow-keywords;
}

크기 조절 키워드 간에 애니메이션을 기본적으로 허용하지 않는 이유는 무엇인가요?

이 선택 메커니즘에 대한 일반적인 의견은 브라우저가 기본적으로 크기 조절 키워드에서 길이로의 전환과 애니메이션을 허용해야 한다는 것입니다. 기본적으로

이 동작을 사용 설정하는 옵션은 기능 개발 중에 연구되었습니다. 작업 그룹은 많은 스타일 시트에서 고유 크기 키워드 (예: auto 또는 min-content)를 애니메이션할 수 없다고 가정하기 때문에 기본적으로 이를 사용 설정하면 이전 버전과 호환되지 않는다는 사실을 발견했습니다. 자세한 내용은 관련 CSS 작업 그룹 문제에 관한 이 설명을 참고하세요.

따라서 이 속성은 선택사항입니다. 상속 트레잇 덕분에 전체 문서를 선택하는 것은 앞서 설명한 대로 :root에 대한 interpolate-size: allow-sizes 선언에 불과합니다.

calc-size()를 사용하여 고유 크기 키워드 간에 애니메이션 처리

브라우저 지원

  • Chrome: 129
  • Edge: 129
  • Firefox: 지원되지 않음
  • Safari: 지원되지 않음

소스

내장 크기 조정 키워드 간의 보간을 사용 설정하는 또 다른 방법은 calc-size() 함수를 사용하는 것입니다. 이를 통해 잘 정의된 안전한 방식으로 고유 크기에 수학을 실행할 수 있습니다.

이 함수는 다음 두 인수를 순서대로 허용합니다.

  • calc-size basis: <intrinsic-size-keyword>일 수도 있고 중첩된 calc-size()일 수도 있습니다.
  • calc-size 기준을 사용하여 계산을 실행할 수 있는 calc-size 계산 calc-size 기준을 참조하려면 size 키워드를 사용하세요.

예를 들면 다음과 같습니다.

width: calc-size(auto, size);        // = the auto width, unaltered
width: calc-size(min-content, size); // = the min-content width, unaltered

원래 데모에 calc-size()를 추가하면 코드는 다음과 같습니다.

nav a {
    width: 80px;
    overflow-x: clip;
    transition: width 0.35s ease;

    &:hover,
    &:focus-visible {
        width: calc-size(max-content, size); /* 👈 */
    }
}

시각적으로는 interpolate-size를 사용할 때와 결과가 정확히 동일합니다. 따라서 이 경우에는 interpolate-size를 사용해야 합니다.

calc-size()의 장점은 계산을 할 수 있다는 점입니다. 이는 interpolate-size로는 할 수 없는 작업입니다.

width: calc-size(auto, size - 10px); // = The auto width minus 10 pixels
width: calc-size(min-content, size + 1rem); // = The min-content width plus 1rem
width: calc-size(max-content, size * .5);   // = Half the max-content width

예를 들어 페이지의 모든 단락 크기를 50px의 가장 가까운 배수로 설정하려면 다음을 사용하면 됩니다.

p {
    width: calc-size(fit-content, round(up, size, 50px));
    height: calc-size(auto, round(up, size, 50px));
}

calc-size()를 사용하면 두 개의 계산 크기 기반이 모두 동일한 경우 두 calc-size() 간에 보간할 수도 있습니다. 이 역시 interpolate-size로는 불가능합니다.

#element {
    width: min-content; /* 👈 */
    transition: width 0.35s ease;

    &:hover {
        width: calc-size(min-content, size + 10px); /* 👈 */
    }
}

calc()에서 <intrinsic-size-keyword>를 허용하지 않는 이유는 무엇인가요?

calc-size()와 관련하여 자주 제기되는 질문은 CSS 작업 그룹에서 고유 크기 키워드를 지원하도록 calc() 함수를 조정하지 않은 이유입니다.

그 이유 중 하나는 계산 시 고유 크기 키워드를 혼합하여 사용할 수 없기 때문입니다. 예를 들어 유효해 보이지만 실제로는 유효하지 않은 calc(max-content - min-content)를 작성하고 싶을 수 있습니다. calc-size()calc()와 달리 첫 번째 인수로 하나의 <intrinsic-size-keyword>만 허용하므로 정확성을 적용합니다.

또 다른 이유는 컨텍스트 인식입니다. 일부 레이아웃 알고리즘은 특정 고유 크기 키워드에 대한 특별한 동작을 보입니다. calc-size()<length>가 아닌 고유 크기를 나타내도록 명시적으로 정의됩니다. 이를 통해 이러한 알고리즘은 calc-size(<intrinsic-size-keyword>, …)<intrinsic-size-keyword>로 취급하여 해당 키워드의 특수 동작을 유지할 수 있습니다.

어떤 접근 방식을 사용해야 하나요?

대부분의 경우 :root에서 interpolate-size: allow-keywords를 선언합니다. 기본 크기 조정 키워드 간에 애니메이션을 사용 설정하는 가장 쉬운 방법으로, 기본적으로 한 줄로 작성할 수 있습니다.

/* Opt-in the whole page to animating to/from intrinsic sizing keywords */
:root {
    interpolate-size: allow-keywords; /* 👈 */
}

이 코드는 점진적 개선의 좋은 예입니다. 이를 지원하지 않는 브라우저는 전환을 사용하지 않는 것으로 대체되기 때문입니다.

계산과 같이 더 세부적으로 제어해야 하거나 calc-size()만 실행할 수 있는 동작을 사용하려는 경우 calc-size()를 사용하면 됩니다.

#specific-element {
    width: 50px;

    &:hover {
        width: calc-size(fit-content, size + 1em); /* 👈 Only calc-size() can do this */
    }
}

하지만 코드에서 calc-size()를 사용하려면 calc-size()를 지원하지 않는 브라우저를 위한 대체 항목을 포함해야 합니다. 예를 들어 추가 크기 선언을 추가하거나 @supports를 사용하여 기능 감지로 대체합니다.

width: fit-content;
width: calc-size(fit-content, size + 1em);
       /* 👆 Browsers with no calc-size() support will ignore this second declaration,
             and therefore fall back to the one on the line before it. */

더 많은 데모

다음은 interpolate-size: allow-keywords를 활용하는 데모입니다.

알림

다음 데모는 @starting-style 데모의 포크입니다. 높이가 다른 항목을 추가할 수 있도록 코드가 조정되었습니다.

이를 위해 전체 페이지에서 크기 키워드 보간을 선택하고 각 .item 요소의 heightauto로 설정됩니다. 그렇지 않으면 코드는 포크 전과 정확히 동일합니다.

:root {
    interpolate-size: allow-keywords; /* 👈 */
}

.item {
    height: auto; /* 👈 */

    @starting-style {
        height: 0px;
    }
}

<details> 요소 애니메이션

이러한 유형의 보간을 사용하려는 일반적인 사용 사례는 공개 위젯이나 전용 아코디언이 열릴 때 애니메이션을 적용하는 것입니다. HTML에서는 <details> 요소를 사용합니다.

interpolate-size: allow-keywords를 사용하면 다음과 같은 작업을 할 수 있습니다.

@supports (interpolate-size: allow-keywords) {
    :root {
        interpolate-size: allow-keywords;
    }
    
    details {
        transition: height 0.5s ease;
        height: 2.5rem;
        
        &[open] {
            height: auto;
            overflow: clip; /* Clip off contents while animating */
        }
    }
}

하지만 공개 위젯이 열릴 때만 애니메이션이 실행됩니다. 이를 위해 Chrome에서는 올해 말 Chrome에 제공될 ::details-content 가명을 개발하고 있으며, 이는 향후 게시물에서 다루게 됩니다. interpolate-size: allow-keywords::details-content를 결합하면 양방향으로 애니메이션을 얻을 수 있습니다.