← 목록으로 돌아가기

CSS @scope와 Anchor Positioning: 2026년 레이아웃의 두 가지 혁신 실전 가이드

CSS

CSS @scope Anchor Positioning layout innovation

CSS가 스스로 경계를 그을 수 있다면

2026년 프론트엔드 생태계에서 두 가지 CSS 기능이 조용하지만 확실하게 실무의 판도를 바꾸고 있습니다. @scope와 Anchor Positioning입니다. 두 기능은 서로 다른 문제를 풀지만, 공통적으로 "자바스크립트가 처리하던 일을 CSS가 직접 처리한다"는 흐름 위에 있습니다.

@scope는 스타일 격리 문제를 해결합니다. Anchor Positioning은 팝오버, 툴팁, 드롭다운의 위치 계산 문제를 해결합니다. 두 기능 모두 2026년 기준 Chromium 기반 브라우저에서 안정적으로 동작하며, 점진적 적용 전략도 충분히 실현 가능합니다.


1. @scope의 탄생 배경: CSS 격리의 새 접근

방법격리 수준빌드 도구 의존JS 런타임 비용단점
CSS Modules높음필요없음빌드 설정 필요
Shadow DOM완전 격리불필요있음외부 스타일 차단
BEM 네이밍규약 의존불필요없음사람 실수 의존
styled-components높음필요있음SSR hydration 비용
@scope명시적 범위불필요없음브라우저 지원 제한

CSS Cascade 6 스펙에서 정의된 @scope는 스타일을 "어디에 적용할지"가 아니라 "어디서부터 어디까지 영향을 미칠지"를 CSS 선언 안에서 명시합니다.

@scope는 "Proximity(근접성)"라는 새로운 카스케이드 기준을 도입합니다. 같은 명시도의 규칙이 충돌할 때, 타겟 요소와 더 가까운 스코프에 속한 규칙이 이깁니다. 이 개념이 기존의 명시도·출처 순서와 어떻게 상호작용하는지는 CSS @layer 실전 가이드에서 다룬 카스케이드 순서와 함께 이해하면 더 명확합니다.


2. :scope 가상 클래스와의 차이

:scope는 CSS 선택자 안에서 현재 스타일 컨텍스트의 루트 요소를 가리키는 가상 클래스입니다. 반면 @scope는 At-rule입니다.

:scope {
  --color-brand: #0070f3;
}

@scope (.card) {
  img {
    border-radius: 0.5rem;
    object-fit: cover;
  }

  p {
    color: var(--color-neutral-700);
    line-height: 1.6;
  }
}

MDN @scope 문서는 이 차이를 명확히 설명합니다. :scope는 선택자 레벨의 가상 클래스이고, @scope는 카스케이드 알고리즘에 근접성 축을 추가하는 At-rule입니다.

@scope 안의 선택자는 스코프 선택자의 명시도를 추가로 가지지 않습니다. 스코프는 명시도가 아니라 근접성으로 우선순위를 결정합니다.


3. 범위 제한과 Donut Scope (from/to 구문)

@scope의 가장 독특한 기능 중 하나는 "구멍이 뚫린 스코프(Donut Scope)"입니다.

@scope (.card) {
  h2 {
    font-size: 1.25rem;
    font-weight: 700;
  }
}

/* Donut Scope: .card 안이지만 .card__footer 안은 제외 */
@scope (.card) to (.card__footer) {
  p {
    color: var(--color-text-primary);
    font-size: 0.9375rem;
  }

  a {
    color: var(--color-brand);
    text-decoration: underline;
  }
}

@scope (.card__footer) {
  a {
    color: var(--color-text-secondary);
    text-decoration: none;
    font-size: 0.875rem;
  }
}

to 구문에 사용하는 선택자는 스코프 안에 포함되어야 합니다. CSS Container Query@scope를 조합하면 컴포넌트가 자신의 공간과 스타일 경계를 모두 자율적으로 관리하는 구조가 완성됩니다.


4. 컴포넌트 스타일 격리 실전 사례

@scope (.feed-card) {
  :scope {
    display: grid;
    grid-template-rows: auto 1fr auto;
    gap: 0.75rem;
    padding: 1rem;
    border: 1px solid var(--color-border);
    border-radius: 0.5rem;
  }

  img {
    width: 100%;
    aspect-ratio: 16 / 9;
    object-fit: cover;
  }

  h3 {
    font-size: 1rem;
    font-weight: 600;
    -webkit-line-clamp: 2;
    overflow: hidden;
  }
}

@scope (.featured-card) {
  :scope {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 1.5rem;
    padding: 1.5rem;
    background: var(--color-surface-elevated);
    border-radius: 1rem;
  }

  img {
    width: 100%;
    aspect-ratio: 4 / 3;
  }

  h3 {
    font-size: 1.5rem;
    font-weight: 700;
  }
}

이 패턴의 핵심은 .feed-card img.featured-card img가 충돌하지 않는다는 점입니다. @scope를 사용하면 근접성이 우선하므로, 어떤 순서로 선언되든 타겟 요소와 더 가까운 스코프의 규칙이 이깁니다.


5. Anchor Positioning 개념: position-anchor와 anchor()

Anchor Positioning은 한 요소의 위치를 다른 요소(앵커)의 위치에 상대적으로 묶는 CSS 기능입니다. MDN CSS Anchor Positioning 문서는 이를 "하나의 요소가 다른 요소를 위치 기준점으로 삼을 수 있는 메커니즘"이라고 정의합니다.

/* 버튼이 앵커 역할: 이름 부여 */
.dropdown-trigger {
  anchor-name: --dropdown-btn;
}

/* 드롭다운 패널: 버튼 아래에 붙도록 위치 */
.dropdown-panel {
  position: absolute;
  position-anchor: --dropdown-btn;

  top: anchor(bottom);
  left: anchor(left);

  min-width: anchor-size(width);
  max-width: 320px;
}

Chrome Developers 블로그의 Anchor Positioning API 소개에 따르면, 이 기능은 position: absolute 또는 position: fixed를 사용하는 요소에서만 동작합니다.


6. 툴팁·드롭다운·팝오버 구현 패턴

.tooltip-btn {
  anchor-name: --tooltip-anchor;
  position: relative;
}

.tooltip {
  position: absolute;
  position-anchor: --tooltip-anchor;

  bottom: calc(anchor(top) + 8px);
  left: anchor(center);
  transform: translateX(-50%);

  background: var(--color-neutral-900);
  color: white;
  padding: 0.375rem 0.625rem;
  border-radius: 0.375rem;
  font-size: 0.8125rem;
  white-space: nowrap;
  pointer-events: none;

  opacity: 0;
  visibility: hidden;
  transition: opacity 150ms ease, visibility 150ms ease;
}

.tooltip-btn:hover + .tooltip,
.tooltip-btn:focus-visible + .tooltip {
  opacity: 1;
  visibility: visible;
}
<button popovertarget="user-menu" class="user-btn">계정 메뉴</button>

<div id="user-menu" popover class="user-popover">
  <ul>
    <li><a href="/profile">프로필 설정</a></li>
    <li><a href="/billing">결제 관리</a></li>
    <li><button>로그아웃</button></li>
  </ul>
</div>
.user-btn {
  anchor-name: --user-menu-anchor;
}

.user-popover {
  position: absolute;
  position-anchor: --user-menu-anchor;
  top: anchor(bottom);
  right: anchor(right);

  margin-top: 0.5rem;
  min-width: 200px;
  background: var(--color-surface);
  border-radius: 0.5rem;
  box-shadow: var(--shadow-md);
}

popover API와 함께 사용하면 키보드 트랩, Escape 키로 닫기, ARIA 속성을 브라우저에서 자동으로 처리합니다.


7. @position-try fallback 전략

.tooltip {
  position: absolute;
  position-anchor: --my-anchor;

  top: calc(anchor(bottom) + 8px);
  left: anchor(center);
  transform: translateX(-50%);

  position-try-fallbacks:
    --tooltip-above,
    --tooltip-left,
    --tooltip-right;
}

@position-try --tooltip-above {
  top: auto;
  bottom: calc(anchor(top) + 8px);
}

@position-try --tooltip-left {
  top: anchor(center);
  transform: translateY(-50%);
  left: auto;
  right: calc(anchor(left) + 8px);
}

@position-try --tooltip-right {
  top: anchor(center);
  transform: translateY(-50%);
  left: calc(anchor(right) + 8px);
}

브라우저는 기본 위치를 먼저 시도합니다. 해당 위치로 렌더링했을 때 팝오버가 viewport를 벗어나면, position-try-fallbacks 목록을 순서대로 시도합니다.


8. 브라우저 지원 현황과 polyfill 옵션

@scope 지원 현황: Chrome 118+, Edge 118+, Firefox 128+, Safari 17.4+. 모든 주요 브라우저에서 지원하는 Baseline Newly Available 기능입니다.

Anchor Positioning 지원 현황: Chrome 125+, Edge 125+, Firefox 133+ (일부 플래그). Safari는 미지원(개발 중).

.tooltip {
  position: fixed;
  top: var(--tooltip-top, 0);
  left: var(--tooltip-left, 0);
}

@supports (anchor-name: --test) {
  .tooltip {
    position: absolute;
    position-anchor: --tooltip-anchor;
    top: calc(anchor(bottom) + 8px);
    left: anchor(center);
    transform: translateX(-50%);
  }
}

9. 기존 JavaScript 포지셔닝(Floating UI) 대체 가능성

기능Floating UICSS Anchor Positioning
기본 위치 지정지원지원
Viewport 감지 fallback지원@position-try로 지원
화살표(꼬리) 위치 계산지원수동 계산 필요
가상 요소 앵커지원미지원
Safari 지원지원미지원
번들 크기~10KB0KB
스크롤 추적 자동화JS 이벤트브라우저 내장

현재 권장하는 전략은 @supports 기반 점진적 적용입니다. Chromium 기반 브라우저에서는 CSS 방식으로, Safari 등 미지원 브라우저에서는 Floating UI로 처리합니다.


10. 디자인 시스템 적용 체크리스트

@scope 도입 체크리스트

  • 컴포넌트 경계를 어떤 선택자를 스코프 루트로 사용할지 결정했는가
  • @layer와 함께 사용할 때 레이어 안에 @scope를 중첩하는 방식으로 우선순위를 관리하고 있는가
  • Donut Scope(to 구문)가 필요한 중첩 컴포넌트를 식별했는가

Anchor Positioning 도입 체크리스트

  • 대상 컴포넌트(툴팁, 드롭다운, 팝오버, 컨텍스트 메뉴)를 목록화했는가
  • @supports (anchor-name: --test) 감지로 미지원 브라우저에 Floating UI fallback을 준비했는가
  • @position-try fallback 전략이 4방향(상, 하, 좌, 우)을 모두 커버하는가
  • popover API와 조합해 접근성을 브라우저에 위임했는가

결론

@scope와 Anchor Positioning은 CSS가 "스타일 언어"에서 "UI 레이아웃 로직 언어"로 진화하는 흐름의 두 축입니다.

  1. 팀의 브라우저 지원 매트릭스를 실제 분석 데이터로 확인하고, @scope와 Anchor Positioning 각각의 도입 시점을 별도로 결정한다.
  2. @scope@layer 구조와 함께 설계한다.
  3. Anchor Positioning 도입 초기에는 popover API와 함께 사용해 접근성 부담을 브라우저에 위임한다.
  4. @position-try fallback을 반드시 작성한다.
  5. Floating UI 같은 기존 JS 포지셔닝 라이브러리를 즉시 제거하지 말고, @supports 감지를 통한 점진적 대체 경로를 설계한다.