개요

CSS Nesting과 @scope는 Sass나 Less 같은 전처리기 없이도 네이티브 CSS에서 중첩 규칙과 스코프 제한을 사용할 수 있게 해주는 기능입니다. CSS Nesting은 2024년에 모든 주요 브라우저에서 지원이 완료되었고, @scope는 Chrome과 Edge에서 지원되며 다른 브라우저도 구현 중입니다.

이 두 기능은 CSS 코드의 구조화와 유지보수를 크게 개선합니다. 중첩으로 관련 스타일을 그룹화하고, @scope로 스타일의 영향 범위를 제한하면 대규모 프로젝트에서도 CSS 충돌 걱정 없이 안전하게 스타일을 작성할 수 있습니다.

핵심 개념

CSS Nesting과 @scope 각각의 핵심을 살펴봅니다.

  • CSS Nesting: 선택자를 중첩하여 부모-자식 관계를 명확히 표현합니다. & 기호로 부모를 참조합니다.
  • 중첩 가능 대상: 선택자, 미디어 쿼리, 컨테이너 쿼리, 레이어 등 모든 at-rule을 중첩할 수 있습니다.
  • @scope: 스타일의 시작점(scoping root)과 끝점(scoping limit)을 정의하여 영향 범위를 제한합니다.
  • Proximity 우선순위: @scope는 specificity 외에 DOM 근접성에 따른 우선순위를 도입합니다.
  • 하한 경계(lower boundary): @scope (.card) to (.card__nested)처럼 스타일이 침투하지 않는 경계를 설정할 수 있습니다.

실전 예제

CSS Nesting으로 컴포넌트 스타일을 구조화하는 예제입니다.

/* CSS Nesting 실전 예제 */
.card {
  background: white;
  border-radius: 12px;
  overflow: hidden;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);

  /* 자식 요소 중첩 */
  .card__header {
    padding: 1.5rem;
    border-bottom: 1px solid #f1f5f9;

    h2 {
      margin: 0;
      font-size: 1.25rem;
      color: #0f172a;
    }
  }

  .card__body {
    padding: 1.5rem;
    color: #475569;
    line-height: 1.7;
  }

  .card__footer {
    padding: 1rem 1.5rem;
    background: #f8fafc;
    display: flex;
    justify-content: flex-end;
    gap: 0.5rem;
  }

  /* & 사용: 부모 선택자 참조 */
  &:hover {
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
    transform: translateY(-2px);
    transition: all 0.2s ease;
  }

  &.card--featured {
    border: 2px solid #3b82f6;
  }

  /* 미디어 쿼리 중첩 */
  @media (max-width: 768px) {
    .card__footer {
      flex-direction: column;
    }
  }

  /* 컨테이너 쿼리 중첩 */
  @container (min-width: 400px) {
    .card__body {
      font-size: 1.1rem;
    }
  }
}

@scope로 컴포넌트의 스타일 영향 범위를 제한하는 예제입니다.

/* @scope 실전 예제 */

/* .sidebar 내부에서만 적용, .sidebar 안의 .widget에는 침투하지 않음 */
@scope (.sidebar) to (.widget) {
  p {
    font-size: 0.9rem;
    line-height: 1.5;
    color: #64748b;
  }

  a {
    color: #2563eb;
    text-decoration: none;

    &:hover {
      text-decoration: underline;
    }
  }

  h3 {
    font-size: 1rem;
    margin-bottom: 0.5rem;
  }
}

/* 각 위젯은 독자적 스코프를 가짐 */
@scope (.widget) {
  :scope {
    border: 1px solid #e2e8f0;
    border-radius: 8px;
    padding: 1rem;
    margin-bottom: 1rem;
  }

  h3 {
    font-size: 0.875rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: #94a3b8;
  }

  p {
    font-size: 0.8rem;
  }
}

활용 팁

  • 3단계 이상 깊은 중첩은 피하세요. Sass에서도 마찬가지지만, 과도한 중첩은 specificity를 높이고 가독성을 저하시킵니다.
  • @scope는 CSS Modules의 대안이 될 수 있습니다. 빌드 도구 없이도 스타일 격리를 달성할 수 있습니다.
  • Nesting + @scope 조합: @scope 블록 내에서 CSS Nesting을 사용하면 가장 깔끔한 컴포넌트 스타일을 만들 수 있습니다.
  • Sass에서 마이그레이션할 때는 &의 동작 차이에 주의하세요. 네이티브 CSS Nesting에서는 &가 항상 부모 선택자 전체를 나타냅니다.
  • @scope의 하한 경계(to 절)는 디자인 시스템에서 컴포넌트 간 스타일 침투를 방지하는 데 매우 유용합니다.

마무리

CSS Nesting과 @scope는 네이티브 CSS를 전처리기 수준으로 끌어올리는 핵심 기능들입니다. 중첩으로 코드 구조를 개선하고, @scope로 스타일 격리를 달성하면, 빌드 도구 의존성을 줄이면서도 유지보수성 높은 CSS를 작성할 수 있습니다. CSS의 진화를 적극적으로 프로젝트에 반영해 보시기 바랍니다.