캐스케이드 레이어 (@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
레이어 3개를 추가합니다.
@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
보다 선택기 수준의 특정성이 더 높지만, a
에 더 높은 우선순위인 @layer
의 색상 스타일이 있기 때문입니다. 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
의 3가지 레이어가 있습니다. base
의 정규화, 테마, 서체 파일(layouts
의 post
파일 및 components
의 cards
및 footer
) 파일을 가져오면 레이어 함수를 사용하여 레이어가 인스턴스화됩니다. 또 다른 접근 방식은 파일 맨 위에 레이어를 구성하여 가져오기 전에 레이어를 선언하는 것입니다.
@layer base,
theme,
layouts,
components,
utilities;
이제 스타일을 @import
하는 순서는 레이어 이름의 첫 번째 인스턴스에서 이미 설정되었으므로 레이어 순서는 중요하지 않습니다. 걱정하지 않아도 됩니다. 가져온 파일을 특정 레이어로 설정할 수는 있지만 순서는 이미 설정되어 있습니다.
레이어 및 캐스케이드
한 걸음 물러서서 더 넓은 캐스케이드와 관련하여 레이어가 사용되는 위치를 살펴보겠습니다.
우선순위는 다음과 같습니다.
- 사용자 에이전트 일반 (가장 낮은 우선순위)
- 로컬 사용자 @layer
- 로컬 사용자 일반
- 작성자 @layers
- 저자 일반
- 작성자 !important
- 작성자 @layer !important
- 로컬 사용자 !important
- 사용자 에이전트 !important** (가장 높은 우선순위)
여기서 @layer !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
가 있는 CSS 파일(예: card.css
)이 있고 카드 내의 모든 링크의 스타일을 지정하려면 다음과 같은 스타일을 작성하면 안 됩니다.
a {
…
}
이렇게 하면 파일의 모든 a
태그가 이 재정의를 받게 됩니다. 여전히 스타일의 범위를 적절하게 지정하는 것이 중요합니다.
.card a {
…
}
규칙 2: 캐스케이드 레이어는 레이어가 없는 CSS 뒤에 순서가 지정된다
레이어로 구성된 CSS 파일은 레이어가 아닌 CSS보다 우선 적용되지 않습니다. 이는 기존 코드베이스를 보다 합리적인 방식으로 사용하기 위해 레이어를 더 쉽게 도입할 수 있도록 의도된 결정이었습니다. 예를 들어 reset.css
파일을 사용하는 것이 캐스케이드 레이어의 좋은 시작점이자 사용 사례입니다.
규칙 3: !important
는 캐스케이드 특이성을 반전합니다.
레이어 스타일은 일반적으로 레이어가 없는 스타일보다 덜 구체적이지만 !important
를 사용하면 반대로 됩니다. 레이어에서 !important
규칙을 사용하는 선언은 레이어가 없는 스타일보다 더 구체적입니다.
이 경우 !important
스타일은 특이성을 반전합니다. 위의 다이어그램은 참고용으로 이를 보여줍니다. author @layers는 author @layer !important보다 우선순위가 낮은 author !important보다 우선순위가 낮고 author @layers보다 우선순위가 낮습니다.
레이어가 여러 개 있는 경우 !important
가 있는 첫 번째 레이어가 !important
우선순위를 가지며 가장 구체적인 스타일이 됩니다.
규칙 4: 삽입 지점의 이해
레이어 순서는 코드에 각 레이어 이름이 처음 표시될 때 설정되므로 layer()
를 가져와서 설정한 후 또는 다른 @layer
문 뒤에 @layer
선언을 배치하면 무시될 수 있습니다. 페이지 가장 아래쪽에 있는 스타일 규칙이 캐스케이드 레이어에 적용되는 CSS와 달리, 순서는 첫 번째 인스턴스부터 설정됩니다.
이는 목록, 레이어 블록 또는 가져오기에 있을 수 있습니다. layer()
를 사용하여 가져오기 목록 뒤에 @layer
를 배치하면 아무 작업도 하지 않습니다. 파일 상단에 배치하면 레이어 순서가 설정되므로 아키텍처 내에서 레이어를 명확하게 볼 수 있습니다.
규칙 #5: 자신의 특수성을 조심하라
캐스케이드 레이어를 사용하면 덜 구체적인 선택기 (예: a
)가 보다 구체적인 선택기 (예: .link
)를 재정의합니다. 이 선택기가 더 구체적인 레이어에 있는 경우 이 선택기가 재정의됩니다. 다음 사항에 유의하세요.
@layer utilities, components
가 지정된 경우 layer(components)
의 a
가 layer(utilities)
의 .pink
를 재정의합니다. 이 API는 의도된 부분이지만 예상하지 못한다면 혼란과 불편을 초래할 수 있습니다.
따라서 유틸리티 클래스를 작성하는 경우 항상 재정의하려는 구성요소보다 상위 레이어로 이를 포함해야 합니다. '색상을 변경하기 위해 이 .pink
클래스를 추가했는데 적용되지 않습니다'라고 생각할 수 있습니다.
캐스케이드 레이어 자세히 알아보기
캐스케이드 레이어에 대해 자세히 알아보려면 다음 리소스를 확인하세요.