프로그래밍/HTML, Javascript, CSS

CSS @starting-style 기준

포도알77 2026. 8. 16. 16:03

본문 중간의 쿠팡 추천 상품 구매시 쿠팡 파트너스에서 일정액의 수수료를 제공받습니다.

CSS @starting-style은 요소가 처음 화면에 나타날 때 CSS transition의 시작값을 지정하는 at-rule입니다. DOM에 새로 추가된 요소, display: none에서 보이는 상태로 바뀐 요소, popover나 <dialog>처럼 top layer에 올라오는 요소는 이전 렌더링 상태가 없을 수 있습니다. 이때 시작값을 따로 주지 않으면 기대한 진입 전환이 생기지 않을 수 있습니다.

결론부터 말하면 @starting-style은 "처음 보이는 순간도 transition으로 처리하고 싶을 때" 쓰는 기능입니다. 반복 애니메이션이나 키프레임 효과를 만들려는 목적이라면 CSS animation을 쓰는 편이 더 직접적입니다.

@starting-style은 무엇을 해결할까

CSS transition은 보통 이전 스타일과 새 스타일 사이의 변화를 보간합니다. 문제는 요소가 이전 style change event에서 렌더링되지 않았거나 DOM에 없었다면 비교할 이전 스타일이 없다는 점입니다. CSS Transitions Level 2는 이런 상황에서 전환의 before-change style을 만들기 위해 @starting-style을 정의합니다.

MDN도 같은 맥락에서 @starting-style을 처음 표시되는 요소, display: none에서 표시 상태로 바뀌는 요소, DOM에 추가되거나 제거되는 요소의 진입·종료 전환에 유용한 기능으로 설명합니다.

.toast {
  opacity: 1;
  transform: translateY(0);
  transition:
    opacity 160ms ease,
    transform 160ms ease;

  @starting-style {
    opacity: 0;
    transform: translateY(8px);
  }
}

위 예시는 .toast가 처음 표시될 때 opacity: 0과 아래쪽 위치에서 시작해 최종 스타일로 전환되도록 만든 것입니다. 이미 화면에 렌더링된 뒤 상태가 바뀌는 일반 transition과 달리, 처음 등장하는 순간의 출발점을 CSS 안에 명시한다는 점이 핵심입니다.

작성 방식은 두 가지다

@starting-style은 독립된 at-rule 블록으로 쓸 수도 있고, 기존 rule 안에 중첩해서 쓸 수도 있습니다. 두 방식 모두 시작 스타일을 제공한다는 목적은 같습니다.

.popover:popover-open {
  opacity: 1;
  transform: scale(1);
}

@starting-style {
  .popover:popover-open {
    opacity: 0;
    transform: scale(.96);
  }
}

독립 블록 방식에서는 기존 rule과 @starting-style 내부 rule의 선택자 우선순위가 같을 수 있습니다. MDN은 이 경우 시작 스타일이 적용되도록 원래 rule 뒤에 @starting-style을 두는 방식을 설명합니다. 중첩 방식은 같은 선택자 안에서 시작 선언을 같이 보게 해 주므로 컴포넌트 단위 CSS에서는 읽기 쉬울 수 있습니다.

방식 장점 주의할 점
독립 블록 여러 선택자의 시작 스타일을 한곳에 모을 수 있음 cascade 순서와 선택자 우선순위를 확인해야 함
중첩 블록 최종 스타일과 시작 스타일을 가까이 둘 수 있음 팀의 CSS nesting 지원 범위와 빌드 환경을 확인해야 함

display 전환과 같이 볼 점

displaynone에서 보이는 값으로 바뀌는 전환은 일반적인 숫자 보간과 다릅니다. MDN의 예시는 displayoverlay처럼 discrete transition을 다룰 때 transition-behavior: allow-discrete 또는 transition shorthand의 allow-discrete를 함께 쓰는 형태를 보여줍니다.

.panel {
  display: block;
  opacity: 1;
  transition:
    opacity 180ms ease,
    display 180ms allow-discrete;

  @starting-style {
    opacity: 0;
  }
}

.panel.is-hidden {
  display: none;
  opacity: 0;
}

여기서 @starting-style은 처음 보이는 순간의 시작 opacity를 정하고, allow-discrete는 discrete 속성을 transition 목록에서 다룰 수 있게 합니다. 둘은 같은 기능이 아니라 서로 다른 문제를 보완합니다.

 

 

transition과 animation 중 무엇을 고를까

@starting-style은 CSS transition에 관련된 기능입니다. MDN은 CSS animation으로 효과를 구현한다면 @starting-style이 필요하지 않다고 설명합니다. animation은 @keyframes 안에서 시작 상태와 끝 상태를 직접 정의하기 때문입니다.

상황 우선 검토 이유
새 요소가 나타날 때 한 번 부드럽게 보여야 함 transition + @starting-style 최종 스타일은 그대로 두고 첫 시작값만 보강하면 됨
반복되거나 단계가 많은 움직임이 필요함 @keyframes animation 여러 중간 상태를 명시하기 쉬움
popover, dialog 진입 전환을 CSS로 정리하고 싶음 @starting-style top layer에 올라오는 첫 표시 상태를 다루기 좋음

실무 적용 기준

첫째, 기본 상태와 표시 상태를 먼저 나눕니다. @starting-style은 기본 상태를 대체하는 문법이 아닙니다. 요소가 닫히거나 숨겨질 때 돌아갈 기본 스타일은 별도로 있어야 합니다.

둘째, 시작 스타일은 짧고 명확하게 둡니다. 보통 opacity, transform처럼 레이아웃 흔들림이 적은 속성이 다루기 쉽습니다. 크기, 위치, 표시 상태가 복잡하게 얽힌 전환은 브라우저별 동작과 접근성 흐름을 더 꼼꼼히 확인해야 합니다.

셋째, prefers-reduced-motion을 고려합니다. 진입 전환 자체가 필수 정보는 아니므로 움직임 감소 설정을 사용하는 환경에서는 transition duration을 줄이거나 제거하는 CSS를 함께 두는 편이 안전합니다.

@media (prefers-reduced-motion: reduce) {
  .toast,
  .panel {
    transition-duration: 1ms;
  }
}

브라우저 지원은 어떻게 볼까

MDN은 @starting-style을 Baseline 2024 기능으로 표시하고, 2024년 8월 이후 최신 주요 브라우저에서 사용할 수 있는 기능으로 설명합니다. 다만 Baseline은 최신 기기와 브라우저를 기준으로 하므로 오래된 WebView, 사내 브라우저, 구형 모바일 환경까지 포함한다면 실제 지원 범위를 별도로 확인해야 합니다.

호환성이 중요한 서비스에서는 @starting-style이 없어도 콘텐츠가 보이고 동작하도록 기본 스타일을 먼저 작성한 뒤, 지원되는 환경에서 진입 전환만 보강하는 progressive enhancement로 다루는 편이 무난합니다.

자주 묻는 질문

@starting-style은 hover 전환에도 필요할까

보통 필요하지 않습니다. hover 전환은 이미 렌더링된 요소의 상태 변화이므로 이전 스타일이 있습니다. @starting-style은 처음 렌더링되거나 이전에 보이지 않던 요소가 표시될 때 주로 필요합니다.

닫힐 때도 @starting-style이 쓰일까

처음 표시된 뒤에는 요소에 이전 스타일이 생깁니다. 닫힐 때는 시작 스타일이 아니라 기본 상태 또는 닫힘 상태로 transition됩니다. 그래서 표시 상태, 닫힘 상태, 시작 상태를 섞지 않고 분리해서 작성하는 것이 중요합니다.

모든 등장 효과를 @starting-style로 바꾸면 될까

그렇지 않습니다. 간단한 첫 등장 transition에는 잘 맞지만, 반복 애니메이션이나 여러 단계의 시각 효과는 @keyframes가 더 적합합니다. 선택 기준은 "상태 변화 보간"인지 "정해진 애니메이션 시퀀스"인지입니다.

정리

@starting-style은 CSS transition이 처음 표시되는 요소에도 출발점을 가질 수 있게 해 주는 at-rule입니다. DOM에 새로 들어온 요소, display: none에서 보이는 상태가 된 요소, popover와 dialog의 진입 전환처럼 이전 렌더링 상태가 애매한 경우에 특히 유용합니다.

실무 기준은 세 가지입니다. 첫째, 기본 상태와 표시 상태를 먼저 정리합니다. 둘째, 시작 스타일은 opacitytransform처럼 예측하기 쉬운 속성부터 적용합니다. 셋째, animation이 더 적합한 반복 효과까지 억지로 transition으로 만들지 않습니다. 이 글은 2026년 8월 16일 기준 MDN과 CSS Transitions Level 2 문서를 바탕으로 정리했습니다.

반응형
페이스북으로 공유카카오톡으로 공유카카오스토리로 공유트위터로 공유URL 복사