컨테이너 쿼리와 비슷하지만 중단된 쿼리, 스냅된 쿼리, 오버플로 쿼리에 적용됩니다.
게시일: 2025년 1월 15일
Chrome 133에서는 스크롤 상태 컨테이너 쿼리를 도입하여 컨테이너 쿼리를 기반으로 합니다. 이제 고정된 위치 지정, 스크롤 스냅 지점, 스크롤 가능한 요소에 대한 브라우저 관리 상태를 CSS에서 쿼리하고 조정할 수 있습니다.
개요
스크롤 상태 쿼리를 실행하기 전에 JavaScript를 사용하여 요소가 고정되었는지, 고정되었는지 또는 스크롤 가능한지 확인해야 합니다. 이제 표준 트랙에서 이 정보를 파악하고 적절하게 조정하는 더 성능이 우수한 메서드가 있습니다. CSS에서 스크롤 트리거 애니메이션을 잠금 해제하여 애니메이션을 트리거하는 새로운 방법도 있습니다.
다음은 Chrome 133부터 사용할 수 있는 상태 쿼리에 대한 개요입니다.
- 중단된 상태:
- 요소가 가장자리에 고정될 때 스타일 변경을 트리거합니다.
- Snapped 상태:
- 요소가 축에 스냅될 때 스타일 변경을 트리거합니다.
- 스크롤 가능한 상태:
- 요소가 오버플로되면 스타일 변경을 트리거합니다.
좋은 소식은 컨테이너 쿼리에서 배운 모든 내용이 스크롤 상태 쿼리를 사용하는 데 도움이 된다는 것입니다.
스크롤 기반 애니메이션과 스크롤 상태 컨테이너 쿼리 사이에는 알려지지 않은 영역도 있습니다. 스크롤 기반 애니메이션과 스크롤 트리거 스크롤 상태 애니메이션 중 어느 것이 가장 좋은지 알아보려면 타이밍과 컨텍스트를 실험해야 합니다. 다음 동영상과 데모에서는 고정 트리거 애니메이션과 스크롤 구동 애니메이션을 비교하여 이 문제를 보여줍니다.
첫 번째 스크롤 상태 쿼리
첫 번째 단계는 container-type
속성의 새 값을 사용하여 컨테이너를 정의하는 것입니다. 컨테이너 쿼리와 마찬가지로 쿼리할 요소는 container-type
및 선택적으로 container-name
를 제공하는 요소입니다. 스크롤 상태 쿼리를 사용하면 스크롤 시 고정되거나 스크롤 시 오버플로가 발생하는 요소에 container-type: scroll-state
를 제공합니다.
.stuck-top {
container-type: scroll-state;
position: sticky;
top: 0px;
}
두 번째 단계는 상태에 응답할 해당 컨테이너의 하위 요소를 선택하는 것입니다. 컨테이너 쿼리와 마찬가지로 container-type
가 있는 요소와 동일한 요소일 수는 없습니다.
.stuck-top {
container-type: scroll-state;
position: sticky;
top: 0px;
> nav {
@container scroll-state(stuck: top) {
background: Highlight;
color: HighlightText;
}
}
}
세 번째 단계는 사용해 보는 것입니다. 다음 CSS 예에서는 .stuck-top
요소가 0
의 상단에 고정될 때 배경을 빨간색으로 설정합니다. 이미 작성한 CSS에 몇 줄을 추가하고 브라우저 상태를 프록시하는 추가 포함 요소를 사용하면 구성요소가 주변 환경에 대해 훨씬 더 스마트해집니다.
점진적 개선
@supports
at-rule 및 중첩을 사용하면 코드 몇 줄만 추가하여 점진적 개선 또는 조건부 기능 사용을 추가할 수 있습니다.
.stuck-top {
container-type: scroll-state;
position: sticky;
top: 0px;
@supports (container-type: scroll-state) {
> nav {
@container scroll-state(stuck: top) {
background: Highlight;
color: HighlightText;
}
}
}
}
또한 스크롤 상태 쿼리로 페이지 주변의 요소에 애니메이션을 적용하는 경우 모션 주위에 @media (prefers-reduced-motion: no-preference) {}
를 사용해야 합니다.
사용 사례
중단
이 섹션의 이름을 '해결하기 어려운 상황'으로 지정해야 할까요? 여기에는 스티키 상태 사용 사례 모음과 구현해야 할 아이디어에 관한 보너스 섹션이 포함되어 있습니다.
@container scroll-state(stuck: top) {}
@container scroll-state(stuck: bottom) {}
멈춘 경우 그림자 추가
중단된 쿼리의 가장 일반적인 사용 사례 중 하나는 중단된 경우 box-shadow
를 추가하여 오버레이하는 콘텐츠 위에 표시되도록 하는 탐색 메뉴입니다.
.stuck-top {
container-type: scroll-state;
position: sticky;
top: 0px;
> nav {
transition: box-shadow .3s ease;
@container scroll-state(stuck: top) {
box-shadow: var(--shadow-5);
}
}
}
현재 멈춘 헤더 활성화
또 다른 일반적인 고정 UI 피드백 시나리오는 현재 고정된 요소를 강조 표시하는 것입니다. 알파벳순으로 정렬된 밴드 목록에서 이 기능은 사용자 환경에 매우 유용하고 도움이 될 수 있습니다.
.sticky-slide {
dt {
container-type: scroll-state;
position: sticky;
inset-block-start: 0;
inset-inline: 0;
> header {
transition:
background .3s ease,
box-shadow .5s ease;
@container scroll-state(stuck: top) {
background: hsl(265 100% 27%);
box-shadow: 0 5px 5px #0003;
}
}
}
}
다음은 헤더가 목록 항목 옆에 있는 또 다른 변형입니다. 가능성은 무궁무진합니다.
아이디어 넘침
다음은 스크롤 상태 쿼리를 사용하여 데모에 약간의 재미를 더하거나 JavaScript를 삭제하는 데 도움이 될 수 있는 고정 데모 목록입니다. 마음에 드는 것을 만들어 보세요. 문법과 아이디어를 기억하는 데 도움이 됩니다 😏.
- https://codepen.io/BlogFire/pen/PoGMjaX - 스티커 메모 변형
- https://codepen.io/mikegolus/pen/jOZzRzw - 테이블이 붙을 때 테이블에 그림자를 추가합니다.
- https://codepen.io/MarcRay/pen/PomBeP - 트리거에 헤더 탐색 메뉴가 표시됨
- https://codepen.io/kevinpowell/pen/OqKJjK - 바닥글 탐색 메뉴 표시
- https://codepen.io/abhisekz-the-decoder/pen/eKaLRd - 고정 카드 헤더
- https://codepen.io/tutsplus/pen/abojPjP - 가격 헤더 섀도우가 트리거에 적용됨
- https://codepen.io/kevinpowell/pen/KEjMEv - 고정 섹션 사이드바 제목
맞춰짐
고정된 상태 쿼리를 사용하면 JavaScript 및 Snap 이벤트에서 일부 책임을 삭제하고 처리를 CSS로 이동할 수 있습니다.
@container scroll-state(snapped: x) {}
@container scroll-state(snapped: y) {}
@container scroll-state(snapped: inline) {}
@container scroll-state(snapped: block) {}
첫 번째 스크롤 상태 쿼리 섹션을 건너뛴 경우 참고로 스냅 쿼리의 컨테이너는 scroll-snap-align
가 있는 요소이며 적응할 수 있는 요소는 해당 요소의 하위 요소여야 합니다. 즉, 이를 설정하려면 다음 세 가지 요소가 필요합니다.
a scroll container with `scroll-snap-type`
⤷ a snap target with both `scroll-snap-align` and `container-type: scroll-state`
⤷ a child of the snap target that can query the container for snap state
스냅된 항목을 시각적으로 향상
중앙에 고정된 스크롤러에서는 중앙에 고정된 항목을 강조 표시하거나 표시하는 경우가 많습니다. 이 추천 문구 예에서는 not
키워드가 사용되므로 스냅되지 않은 모든 추천 문구는 불투명도가 낮고 스냅된 추천 문구는 자연스러운 프레젠테이션 상태를 유지합니다.
.demo {
overflow: auto hidden;
scroll-snap-type: x mandatory;
> article {
container-type: scroll-state;
scroll-snap-align: center;
@supports (container-type: scroll-state) {
> * {
transition: opacity .5s ease;
@container not scroll-state(snapped: x) {
opacity: .25;
}
}
}
}
}
캡처된 항목의 자막 표시
스크롤 상태 쿼리를 통해 스크롤 트리거 애니메이션을 사용 설정하는 방법을 보여주는 좋은 예입니다. 또한 CSS에서 모션 감소를 고려하는 것이 중요한 경우를 보여주는 좋은 예입니다.
.demo {
overflow-x: auto;
scroll-behavior-x: contain;
scroll-snap-type: x mandatory;
> .card {
container-type: scroll-state;
scroll-snap-align: center;
@supports (container-type: scroll-state) {
@media (prefers-reduced-motion: no-preference) {
figcaption {
transform: translateY(100%);
@container scroll-state(snapped: x) {
transform: translateY(0);
}
}
}
}
}
}
슬라이드 요소에 애니메이션 적용
강연을 할 때 슬라이드 쇼나 프레젠테이션의 요소에 애니메이션을 적용하는 것은 매우 일반적입니다. 이를 위해 교차 관찰자를 작성하는 것은 매우 불편했습니다. 교차 관찰자는 슬라이드에 클래스를 설정하는 역할만 했습니다. 이제 JavaScript가 필요하지 않습니다.
html {
scroll-snap-type: y mandatory;
}
section {
container-type: scroll-state;
scroll-snap-align: start;
scroll-snap-stop: always;
@supports (container-type: scroll-state) {
@media (prefers-reduced-motion: no-preference) {
> h1 {
transition: opacity .5s ease, transform .5s var(--ease-spring-3);
transition-delay: .5s;
opacity: 0;
transform: scale(1.25);
@container scroll-state(snapped: block) {
opacity: 1;
transform: scale(1);
}
}
}
}
}
모든 스냅된 CSS 상태 쿼리는 scrollsnapchange
가 아닌 scrollsnapchanging
처럼 동작하는 것을 볼 수 있습니다. 이렇게 하면 스냅된 요소의 시각적 피드백을 제공할 수 있는 가장 빠른 후크를 사용할 수 있습니다. 너무 성급한 경우 JavaScript 이벤트를 고려해 보세요.
스크롤 가능
스크롤 가능한 상태 쿼리는 스크롤 영역을 실제로 스크롤할 수 있는 시점에 시각적 어포던스를 표시하는 데 매우 유용합니다. 스크롤 상태 쿼리 전에는 이 정보를 알기 어려웠습니다.
@container scroll-state(scrollable: top) {}
@container scroll-state(scrollable: right) {}
@container scroll-state(scrollable: bottom) {}
@container scroll-state(scrollable: left) {}
그림자로 스크롤 표시
background-attachment: local
를 사용하여 이와 유사한 효과를 얻는 유명한 Lea Verou의 CSS 트릭과 스크롤 기반 애니메이션으로 이를 실행하는 방법이 있습니다. 각 기법에는 장단점이 있으므로 이러한 각 기법이 가장 적합한 시점과 위치를 살펴보는 것이 좋습니다.
다음 예에서는 스크롤 포트에 걸쳐 있는 고정된 단일 요소를 사용합니다. 컨텍스트 스크롤 상태 쿼리 @container scroll-state(scrollable: top)
가 적용되면 상단의 그라데이션과 하단의 그라데이션의 불투명도가 @property
로 애니메이션 처리됩니다.
또한 이 컨테이너는 size
컨테이너이자 scroll-state
컨테이너인 첫 번째 컨테이너입니다.
.scroll-container {
container-type: scroll-state size;
overflow: auto;
&::after {
content: " ";
background: var(--_shadow-top), var(--_shadow-bottom);
transition:
--_scroll-shadow-color-1-opacity .5s ease,
--_scroll-shadow-color-2-opacity .5s ease;
@container scroll-state(scrollable: top) {
--_scroll-shadow-color-1-opacity: var(--_shadow-color-opacity, 25%);
}
@container scroll-state(scrollable: bottom) {
--_scroll-shadow-color-2-opacity: var(--_shadow-color-opacity, 25%);
}
}
}
화살표 프롬프트
화살표를 표시하면 사용자가 스크롤 가능한 영역을 쉽게 찾을 수 있습니다. 이러한 화살표는 스크롤이 발생할 수 있는 방향을 가리키는 경향이 있으며 더 이상 필요하지 않으면 사라집니다. 다음 코드를 사용하면 됩니다.
@container scroll-state((scrollable: top) or (not (scrollable: bottom))) {
translate: 0 calc(100% + 10px);
}
@container scroll-state((scrollable: top) and (not (scrollable: bottom))) {
translate: 0 calc(100% + 10px);
rotate: .5turn;
}
맨 위로 돌아가기
또 다른 인기 있는 스크롤 상태 상호작용은 '맨 위로 스크롤' 편의 버튼입니다. 다음 코드를 사용하면 위로 스크롤할 곳이 없을 때 맨 위로 스크롤 버튼이 사라집니다.
이 솔루션은 약간 역설적이지만 CSS의 양을 줄일 수 있습니다. 버튼의 자연스러운 위치가 표시되므로 더 이상 위로 스크롤할 곳이 없을 때 버튼을 숨기도록 지시해야 합니다.
@container not scroll-state(scrollable: top) {
translate: 0 calc(100% + 10px);
}
연구 계속
자세한 내용은 사양 세부정보부터 이 주제를 다루는 다른 유용한 도움말에 이르기까지 다양한 리소스를 참고하세요.
- 컨테이너 쿼리할 수 있는 다른 항목이 있나요? https://github.com/w3c/csswg-drafts/issues/5989
- scroll-state() 설명 - https://drafts.csswg.org/css-conditional-5/scroll_state_explainer.md
- scroll-state() CSS 사양 - https://www.w3.org/TR/css-conditional-5/#scroll-state-container
- HTML 이벤트 루프에서 레이아웃 스냅샷
- 상태 쿼리에 관한 팟캐스트 에피소드 - https://nerdy.dev/the-css-podcast-on-state-queries
- 도움말 더보기
- https://utilitybend.com/blog/is-the-sticky-thing-stuck-is-the-snappy-item-snapped-a-look-at-state-queries-in-css/
- https://ishadeed.com/article/css-state-queries/
- https://csscade.com/can-you-detect-overflow-with-css/
- https://css-tip.com/overflow-detection/ - 하위 요소 외에도 알 수 있는 방식으로 스크롤 기반 애니메이션으로 감지 (속임수와의 절충)