계층 캐스캐이딩 (@layer
CSS 규칙)이 Chromium 99, Firefox 97, Safari 15.4 베타에 도입됩니다. 이를 통해 CSS 파일을 더 명시적으로 제어하여 스타일 고유성 충돌을 방지할 수 있습니다. 이는 대규모 코드베이스, 디자인 시스템, 애플리케이션에서 서드 파티 스타일을 관리할 때 특히 유용합니다.
CSS를 명확하게 레이어링하면 예상치 못한 스타일 재정의를 방지하고 CSS 아키텍처를 개선할 수 있습니다.
CSS 특수성 및 계층 구조
CSS 특수성은 CSS가 어떤 요소에 어떤 스타일을 적용할지 결정하는 방법입니다. 사용할 수 있는 다양한 선택자는 스타일 규칙의 특이성을 결정합니다. 예를 들어 요소는 클래스나 속성보다 구체적이지 않으며 클래스나 속성은 ID보다 구체적이지 않습니다. 이는 CSS를 학습하는 데 있어 기본적인 부분입니다.
사람들은 의도치 않게 특이성을 재정의하는 것을 방지하기 위해 BEM과 같은 CSS 명명 규칙을 사용합니다. 모든 요소에 단일 클래스 이름을 지정하면 모든 요소가 동일한 특정성 평면에 배치됩니다. 하지만 특히 서드 파티 코드 및 디자인 시스템을 사용할 때는 이러한 체계적인 스타일을 유지하는 것이 항상 가능한 것은 아닙니다.
계단식 레이어는 이 문제를 해결하는 것을 목표로 합니다. CSS 캐스케이드에 새로운 레이어를 도입합니다. 계층화된 스타일의 경우 레이어의 우선순위가 항상 선택기의 특정성보다 높습니다.
예를 들어 선택기 .post a.link
는 .card a
보다 특이성이 높습니다. 게시물 내 카드 내에서 링크의 스타일을 지정하려고 하면 더 구체적인 선택기가 적용됩니다.
@layer
를 사용하면 각 스타일의 특수성을 더 명시적으로 지정할 수 있으며, 모든 CSS가 동일한 평면에 있는 경우 수치적으로 특수성이 더 낮더라도 카드 링크의 스타일이 게시물 링크의 스타일을 재정의하도록 할 수 있습니다. 이는 계단식 우선순위 때문입니다. 레이어 스타일을 사용하면 새로운 계단식 '평면'이 생성됩니다.
@layer
작업 중
이 예에서는 @layer
를 사용하여 계단식 레이어의 기능을 보여줍니다. 몇 개의 링크가 표시됩니다. 추가 클래스 이름이 적용되지 않은 링크, .link
클래스가 적용된 링크, .pink
클래스가 적용된 링크가 각각 하나씩 있습니다. 그런 다음 CSS는 다음과 같이 base
, typography
, utilities
라는 세 개의 레이어를 추가합니다.
@layer base {
a {
font-weight: 800;
color: red; /* ignored */
}
.link {
color: blue; /* ignored */
}
}
@layer typography {
a {
color: green; /* styles *all* links */
}
}
@layer utilities {
.pink {
color: hotpink; /* styles *all* .pink's */
}
}
결국 모든 링크가 녹색 또는 분홍색입니다. 이는 .link
가 a
보다 선택자 수준의 구체성이 높지만 우선순위가 더 높은 @layer
에 a
의 색상 스타일이 있기 때문입니다. 녹색 규칙이 파란색 규칙 뒤의 레이어에 있으면 a { color: green }
가 .link { color: blue }
를 재정의합니다.
레이어 우선순위가 요소 구체성보다 우선합니다.
레이어 정리
위와 같이 페이지에서 직접 레이어를 정렬하거나 파일 상단에서 정렬할 수 있습니다.
레이어 순서는 각 레이어 이름이 코드에 처음 표시될 때 설정됩니다.
즉, 파일 상단에 다음을 추가하면 링크가 모두 빨간색으로 표시되고 클래스가 .link
인 링크는 파란색으로 표시됩니다.
@layer utilities, typography, base;
이는 이제 레이어 순서가 바뀌어 유틸리티가 먼저, 기본이 나중에 표시되기 때문입니다. 따라서 base
레이어의 스타일 규칙은 서체 레이어의 스타일 규칙보다 항상 더 높은 특정성을 갖습니다. 더 이상 녹색 링크가 아닌 빨간색 또는 파란색 링크로 표시됩니다.
가져오기 정리
@layer
를 사용하는 또 다른 방법은 가져오기 파일을 사용하는 것입니다. 다음 예와 같이 스타일을 가져올 때 layer()
함수를 사용하여 직접 할 수 있습니다.
/* Base */
@import '../styles/base/normalize.css' layer(base); /* normalize or rest file */
@import '../styles/base/base.css' layer(base); /* body and base styles */
@import '../styles/base/theme.css' layer(theme); /* theme variables */
@import '../styles/base/typography.css' layer(theme); /* theme typography */
@import '../styles/base/utilities.css' layer(utilities); /* base utilities */
/* Layouts */
@import '../styles/components/post.css' layer(layouts); /* post layout */
/* Components */
@import '../styles/components/cards.css' layer(components); /* imports card */
@import '../styles/components/footer.css' layer(components); /* footer component */
위의 코드 스니펫에는 base
,layouts
, components
라는 세 개의 레이어가 있습니다. base
의 정규화, 테마, 서체 파일, layouts
의 post
파일, components
의 cards
및 footer
. 파일을 가져올 때 레이어 함수를 사용하여 레이어가 인스턴스화됩니다. 가져오기 전에 레이어를 선언하여 파일 상단에 레이어를 구성하는 것도 방법입니다.
@layer base,
theme,
layouts,
components,
utilities;
이제 스타일을 @import
하는 순서는 레이어 순서에 영향을 미치지 않습니다. 레이어 이름의 첫 번째 인스턴스에서 이미 설정되었기 때문입니다. 이제 걱정할 일이 하나 줄었네요. 가져온 파일을 특정 레이어로 설정할 수는 있지만 순서는 이미 정해져 있습니다.
레이어 및 계단식
한 걸음 물러서서 더 큰 폭의 계단식 구조와 관련하여 레이어가 사용되는 위치를 살펴보겠습니다.
우선순위는 다음과 같습니다.
- 사용자 에이전트 일반 (최저 우선순위)
- 로컬 사용자 @layer
- 로컬 사용자 일반
- 저자 @layers
- 저자 일반
- 저자 !important
- Author @layer !important
- 로컬 사용자 !important
- 사용자 에이전트 !important** (가장 높은 우선순위)
여기에서 @layer !important
스타일이 반전된 것을 볼 수 있습니다. 레이어링되지 않은 (일반) 스타일보다 덜 구체적이기는 하지만 우선순위가 더 높습니다. 이는 !important
가 계단식 구조에서 작동하는 방식 때문입니다. !important
는 스타일시트에서 일반적인 계단식 구조를 중단하고 일반적인 레이어 수준 특정성 (우선순위)을 반전시킵니다.
중첩된 레이어
레이어는 다른 레이어 내에 중첩될 수도 있습니다. 다음 예는 미리엄 스즈키의 카스케이드 레이어 설명에서 가져온 것입니다.
@layer default {
p { max-width: 70ch; }
}
@layer framework {
@layer default {
p { margin-block: 0.75em; }
}
p { margin-bottom: 1em; }
}
위의 코드 스니펫에서는 .
를 framework
내에 중첩된 default
레이어의 지표로 사용하여 framework.default
에 액세스할 수 있습니다. 더 간단한 형식으로 작성할 수도 있습니다.
@layer framework.default {
p { margin-block: 0.75em }
}
결과 레이어 및 레이어 순서는 다음과 같습니다.
- 기본값
framework.default
framework
레이어 해제됨- 레이어 없음
주의사항
계단식 레이어는 올바르게 사용하면 유용하지만 혼란을 야기하고 예기치 않은 결과를 초래할 수도 있습니다. 계단식 레이어를 사용할 때는 다음 사항에 유의하세요.
규칙 1: 범위 지정에 @layer
를 사용하지 않음
계층 구조 레이어는 범위를 해결하지 않습니다. @layer
(예: card.css
)가 있는 CSS 파일이 있고 카드 내의 모든 링크에 스타일을 지정하려는 경우 다음과 같은 스타일을 작성하지 마세요.
a {
…
}
이렇게 하면 파일의 모든 a
태그에 이 재정의가 적용됩니다. 스타일의 범위를 지정하는 것이 여전히 중요합니다.
.card a {
…
}
규칙 2: 계층화된 레이어는 계층화되지 않은 CSS 뒤에 정렬됩니다.
레이어된 CSS 파일은 레이어되지 않은 CSS를 재정의하지 않습니다. 이는 기존 코드베이스와 더 적절한 방식으로 레이어를 더 쉽게 도입할 수 있도록 의도적으로 결정한 사항입니다. 예를 들어 reset.css
파일을 사용하는 것은 계단식 레이어의 시작점과 사용 사례로 적합합니다.
규칙 3: !important
는 계층식 특이성을 반전합니다.
일반적으로 레이어된 스타일은 레이어되지 않은 스타일보다 구체적이지 않지만 !important
를 사용하면 이 점이 반전됩니다. 레이어에서 !important
규칙이 있는 선언은 레이어되지 않은 스타일보다 더 구체적입니다.
이 경우 !important
스타일은 특이성을 반전시킵니다. 위의 다이어그램은 참고용으로 이를 보여줍니다. author @layers는 author normal보다 우선순위가 낮고, author normal은 author !important보다 우선순위가 낮으며, author !important는 author @layer !important보다 우선순위가 낮습니다.
레이어가 여러 개인 경우 !important
가 있는 첫 번째 레이어가 !important
우선순위를 따르며 가장 구체적인 스타일이 됩니다.
규칙 4: 삽입 지점 이해
레이어 순서는 각 레이어 이름이 코드에 처음 표시될 때 설정되므로 layer()
를 가져오고 설정한 후 또는 다른 @layer
문에 @layer
선언을 배치하면 무시될 수 있습니다. CSS와 달리 페이지에서 가장 아래에 있는 스타일 규칙이 계단식 레이어에 적용되는 것과 달리 순서는 첫 번째 인스턴스에서 설정됩니다.
목록, 레이어 블록 또는 가져오기에 있을 수 있습니다. layer()
가 있는 가져오기 목록 뒤에 @layer
를 배치하면 아무 일도 일어나지 않습니다. 파일 상단에 배치하면 레이어 순서가 설정되고 아키텍처 내의 레이어를 명확하게 볼 수 있습니다.
규칙 5: 구체적인 내용을 사용하세요.
계단식 레이어를 사용하면 덜 구체적인 선택기(예: a
)가 더 구체적인 레이어에 있는 경우 덜 구체적인 선택기(예: .link
)가 더 구체적인 선택기(예: .link
)를 재정의합니다. 다음을 고려하세요.
@layer utilities, components
이 지정된 경우 layer(components)
의 a
이 layer(utilities)
의 .pink
를 재정의합니다. 이는 API의 의도적인 부분이지만 예상치 못한 경우 혼란스럽고 불편할 수 있습니다.
따라서 유틸리티 클래스를 작성하는 경우 항상 재정의하려는 구성요소보다 상위 레이어로 포함하세요. '색상을 변경하기 위해 이 .pink
클래스를 추가했는데 적용되지 않는 것 같습니다.'라고 생각할 수 있습니다.
계단식 영역에 대해 자세히 알아보기
다음 리소스에서 계단식 레이어에 대해 자세히 알아볼 수도 있습니다.