이번 주 CSS 커버리지는 하나의 테마로 수렴합니다. 브라우저가 과거 JavaScript를 요구했던 동작을 점점 더 자체적으로 처리하고 있다는 것입니다. 주요 아이템인 Brecht De Ruyte의 CSS @container scroll-state() 쿼리 심층 분석이 가장 명확한… 개발자가 바로 활용할 수 있도록 정리했습니다.
calendar_todaysummarize2026년 4주차
article
태그: CSS읽기_시간: 5분
CSS @container scroll-state() 쿼리: JavaScript 없이 스크롤 위치 감지
CSS scroll-state 쿼리는 컨테이너가 자신의 스크롤 상태를 자식 요소에 선언적으로 노출하여 JavaScript의 Intersection Observer와 scroll 이벤트 리스너를 대체합니다. Chrome 133에서 stuck, snapped, scrollable세 가지 상태가 출시되었으며, Chrome 144에서는 사용자의 가장 최근 스크롤 방향을 추적하는 scrolled 상태가 추가되었습니다. 이를 통해 스크롤 다운 시 헤더 숨기기, 스크롤 업 시 표시하기 같은 패턴을 @container scroll-state(scrolled: bottom) 규칙만으로 구현할 수 있습니다. 사용하려면 스크롤 조상 요소에 container-type: scroll-state를 설정해야 하며, 현재 Chrome에서만 지원되므로 progressive enhancement 전략이 권장됩니다.
리셋 스타일시트의 규칙을 익명 @layer {} 블록으로 감싸는 것은 모든 선택자를 :where()로 래핑하는 것보다 가독성이 높은 specificity 낮추기 방법입니다. cascade에서 layered 규칙은 unlayered 규칙보다 항상 낮은 우선순위를 가지므로, 소스 순서에 관계없이 사용자 스타일시트 규칙이 익명 레이어의 선언을 덮어씁니다. 이미 named @layer 블록을 사용 중이라면 나중에 정의된 레이어가 우선하므로 익명 레이어는 반드시 먼저 선언해야 합니다. 익명(이름 없는) 레이어를 사용하면 서드파티가 포함한 named layer가 기존의 @layer first, reset, base, components 선언 순서를 바꾸는 충돌을 방지합니다.
OddBird의 팟캐스트 에피소드로, Chris Coyier와 함께 두 가지 수렴하는 CSS 기능을 다룹니다. 첫 번째로 2025년 말 Firefox가 지원을 출시하여 모든 주요 브라우저에서 사용 가능해진 @scope의 실용적 활용 사례를 살펴봅니다. 두 번째로 Miriam Suzanne이 개발 중인 CSS mixins 명세를 논의하며, @content 블록이 Sass의 mixin처럼 동작하는 방식을 탐구합니다. 또한 @content 대 @contents 명칭 문제와 CSS가 프로그래밍 가능하고 컴포넌트 친화적인 언어로 나아가는 방향도 다룹니다.
CSS 레이아웃은 모든 알고리즘이 확장하는 소수의 핵심 모델 위에 구축됩니다: normal flow (block은 수직으로 쌓이고, inline은 수평으로 흐름), box model (content-box 대 border-box), whitespace로 인한 anonymous box 생성, 형제와 부모/자식 간의 margin collapse (display: flow-root나 overflow: auto로 방지), inline 요소의 baseline 정렬, position: absolute의 offset parent 체인, 그리고 stacking context가 있습니다. Flexbox는 요소를 bottom-up으로 배포하고, Grid는 미리 정의된 영역에 top-down으로 배치합니다. place-content: center를 높이가 지정된 block 요소에 적용하는 것이 현대적 수직 중앙 정렬의 가장 간단한 해법입니다.
CSS anchor positioning의 fallback 시스템은 툴팁, 드롭다운, 팝오버가 뷰포트를 넘칠 때 JavaScript 없이 자동으로 위치를 재지정합니다. position-try-fallbacks 속성은 flip-block, flip-inline 등의 flip 키워드 또는 @position-try at-rule을 콤마로 나열하여 차례로 시도하며, 모두 맞지 않으면 원래 위치로 되돌아갑니다. @position-try at-rule은 다른 position-anchor 타겟이나 max-block-size 같은 커스텀 크기 조정을 허용하지만 positioning 관련 속성만 사용할 수 있습니다. position-try-order: most-block-size는 여러 fallback이 맞을 때 가장 많은 수직 공간을 제공하는 위치를 선택하며, 이는 오버플로 발생 시뿐만 아니라 초기 표시 시점에도 평가됩니다.
네이티브 HTML <dialog> 요소는 focus trapping, Escape 키 닫기, 닫힌 상태에서의 display: none 처리를 기본 제공하여 커스텀 오버레이 구현을 대체합니다. .showModal()은 요소를 브라우저의 top layer로 승격시켜 z-index 충돌을 완전히 제거하며, .show()는 chat 위젯처럼 배경 상호작용이 필요한 비모달 용도로 사용합니다. CSS reset에서 margin: 0을 사용하면 기본 margin: auto 중앙 정렬이 깨지고, <dialog> 요소에 직접 display: grid를 적용하면 open/close가 동작하지 않으므로 반드시 dialog[open] 선택자에 적용해야 합니다. ::backdrop pseudo-element로 배경 dimming을 커스터마이즈할 수 있으며, scrollbar-gutter: stable로 스크롤바 토글 시 레이아웃 이동을 방지할 수 있습니다.
CSS @container scroll-state() 쿼리: JavaScript 없이 스크롤 위치 감지
CSS scroll-state 쿼리는 컨테이너가 자신의 스크롤 상태를 자식 요소에 선언적으로 노출하여 JavaScript의 Intersection Observer와 scroll 이벤트 리스너를 대체합니다. Chrome 133에서 stuck, snapped, scrollable세 가지 상태가 출시되었으며, Chrome 144에서는 사용자의 가장 최근 스크롤 방향을 추적하는 scrolled 상태가 추가되었습니다. 이를 통해 스크롤 다운 시 헤더 숨기기, 스크롤 업 시 표시하기 같은 패턴을 @container scroll-state(scrolled: bottom) 규칙만으로 구현할 수 있습니다. 사용하려면 스크롤 조상 요소에 container-type: scroll-state를 설정해야 하며, 현재 Chrome에서만 지원되므로 progressive enhancement 전략이 권장됩니다.
네이티브 HTML <dialog> 요소는 focus trapping, Escape 키 닫기, 닫힌 상태에서의 display: none 처리를 기본 제공하여 커스텀 오버레이 구현을 대체합니다. .showModal()은 요소를 브라우저의 top layer로 승격시켜 z-index 충돌을 완전히 제거하며, .show()는 chat 위젯처럼 배경 상호작용이 필요한 비모달 용도로 사용합니다. CSS reset에서 margin: 0을 사용하면 기본 margin: auto 중앙 정렬이 깨지고, <dialog> 요소에 직접 display: grid를 적용하면 open/close가 동작하지 않으므로 반드시 dialog[open] 선택자에 적용해야 합니다. ::backdrop pseudo-element로 배경 dimming을 커스터마이즈할 수 있으며, scrollbar-gutter: stable로 스크롤바 토글 시 레이아웃 이동을 방지할 수 있습니다.
리셋 스타일시트의 규칙을 익명 @layer {} 블록으로 감싸는 것은 모든 선택자를 :where()로 래핑하는 것보다 가독성이 높은 specificity 낮추기 방법입니다. cascade에서 layered 규칙은 unlayered 규칙보다 항상 낮은 우선순위를 가지므로, 소스 순서에 관계없이 사용자 스타일시트 규칙이 익명 레이어의 선언을 덮어씁니다. 이미 named @layer 블록을 사용 중이라면 나중에 정의된 레이어가 우선하므로 익명 레이어는 반드시 먼저 선언해야 합니다. 익명(이름 없는) 레이어를 사용하면 서드파티가 포함한 named layer가 기존의 @layer first, reset, base, components 선언 순서를 바꾸는 충돌을 방지합니다.
OddBird의 팟캐스트 에피소드로, Chris Coyier와 함께 두 가지 수렴하는 CSS 기능을 다룹니다. 첫 번째로 2025년 말 Firefox가 지원을 출시하여 모든 주요 브라우저에서 사용 가능해진 @scope의 실용적 활용 사례를 살펴봅니다. 두 번째로 Miriam Suzanne이 개발 중인 CSS mixins 명세를 논의하며, @content 블록이 Sass의 mixin처럼 동작하는 방식을 탐구합니다. 또한 @content 대 @contents 명칭 문제와 CSS가 프로그래밍 가능하고 컴포넌트 친화적인 언어로 나아가는 방향도 다룹니다.
CSS 레이아웃은 모든 알고리즘이 확장하는 소수의 핵심 모델 위에 구축됩니다: normal flow (block은 수직으로 쌓이고, inline은 수평으로 흐름), box model (content-box 대 border-box), whitespace로 인한 anonymous box 생성, 형제와 부모/자식 간의 margin collapse (display: flow-root나 overflow: auto로 방지), inline 요소의 baseline 정렬, position: absolute의 offset parent 체인, 그리고 stacking context가 있습니다. Flexbox는 요소를 bottom-up으로 배포하고, Grid는 미리 정의된 영역에 top-down으로 배치합니다. place-content: center를 높이가 지정된 block 요소에 적용하는 것이 현대적 수직 중앙 정렬의 가장 간단한 해법입니다.
CSS anchor positioning의 fallback 시스템은 툴팁, 드롭다운, 팝오버가 뷰포트를 넘칠 때 JavaScript 없이 자동으로 위치를 재지정합니다. position-try-fallbacks 속성은 flip-block, flip-inline 등의 flip 키워드 또는 @position-try at-rule을 콤마로 나열하여 차례로 시도하며, 모두 맞지 않으면 원래 위치로 되돌아갑니다. @position-try at-rule은 다른 position-anchor 타겟이나 max-block-size 같은 커스텀 크기 조정을 허용하지만 positioning 관련 속성만 사용할 수 있습니다. position-try-order: most-block-size는 여러 fallback이 맞을 때 가장 많은 수직 공간을 제공하는 위치를 선택하며, 이는 오버플로 발생 시뿐만 아니라 초기 표시 시점에도 평가됩니다.
이번 주 CSS 커버리지는 하나의 테마로 수렴합니다. 브라우저가 과거 JavaScript를 요구했던 동작을 점점 더 자체적으로 처리하고 있다는 것입니다. 주요 아이템인 Brecht De Ruyte의 CSS @container scroll-state() 쿼리 심층 분석이 가장 명확한 사례입니다. Chrome 144의 새로운 scrolled 상태를 이용하면 @container scroll-state(scrolled: bottom) 규칙 하나만으로, JavaScript 없이 스크롤 다운 시 헤더 숨기기 패턴을 구현할 수 있습니다. Chrome 133에서 도입된 stuck, snapped, scrollable 상태를 기반으로 합니다. 현재는 Chrome 전용이므로 progressive enhancement 전략이 권장됩니다. Kevin Powell의 네이티브 <dialog> 요소 영상도 같은 맥락입니다. .showModal()이 요소를 브라우저의 top layer로 승격시켜 z-index 충돌을 완전히 제거하고, 내장 focus trap과 Escape 키 닫기가 수백 줄의 커스텀 오버레이 코드를 대체합니다.
정밀한 포지셔닝도 깊게 다뤄집니다. Schalk Neethling의 CSS anchor positioning fallback 시스템 가이드 — position-try-fallbacks, named @position-try at-rule, position-try-order: most-block-size — 는 툴팁과 팝오버가 JavaScript 측정 없이 자동으로 위치를 재조정하는 방법을 보여줍니다. Manuel Matuzović는 리셋 스타일시트를 익명 @layer {} 블록으로 감싸는 깔끔한 cascade 기법을 소개합니다. 이 방법은 모든 unlayered 규칙보다 specificity를 낮춰, 선택자마다 :where()를 감싸는 장황한 패턴을 깔끔하게 대체합니다.
CSS 언어의 미래를 내다보면, OddBird 팟캐스트에서 Miriam Suzanne과 Chris Coyier가 2025년 말 Firefox 지원으로 크로스브라우저가 된 @scope와, @content 블록을 활용한 네이티브 CSS mixins 명세를 탐구합니다. Polypane의 CSS 레이아웃 기본 원리 심층 글은 normal flow, box model, margin collapse, stacking context 등 모든 레이아웃 알고리즘의 바탕이 되는 mental model을 재정립하며, 높이가 지정된 block 요소에 place-content: center를 적용하는 것이 현대적 수직 중앙 정렬의 가장 간단한 해법임을 결론으로 제시합니다.
핵심 요점
CSS scroll-state 쿼리(scrolled, stuck, snapped, scrollable)를 통해 Chrome에서 JavaScript scroll 리스너를 선언적 container 쿼리로 대체할 수 있으며, 브라우저 지원이 확대될 때까지 progressive enhancement가 필수입니다.
네이티브 <dialog> 요소의 top layer 승격과 anchor positioning fallback 시스템은 레이아웃을 위해 JavaScript를 사용하던 두 가지 가장 흔한 패턴을 제거합니다.
익명 @layer 블록은 리셋 스타일시트의 specificity를 낮추기 위한 :where() 방식보다 더 깔끔하고 충돌 안전한 대안을 제공합니다.