가장 유용한 CSS 전처리기 기능 중 하나인 스타일 규칙 중첩이 이제 언어에 기본 제공됩니다.
중첩하기 전에는 모든 선택자를 서로 별도로 명시적으로 선언해야 했습니다. 이로 인해 반복, 스타일시트 대량, 분산된 작성 환경이 발생합니다.
.nesting { color: hotpink; } .nesting > .is { color: rebeccapurple; } .nesting > .is > .awesome { color: deeppink; }
중첩 후에는 선택자를 계속 사용할 수 있으며 관련 스타일 규칙을 그룹화할 수 있습니다.
.nesting { color: hotpink; > .is { color: rebeccapurple; > .awesome { color: deeppink; } } }
중첩은 관련 요소의 스타일 규칙을 함께 배치하면서 선택자를 반복할 필요성을 줄여 개발자에게 도움이 됩니다. 또한 스타일이 타겟팅하는 HTML과 일치하도록 도울 수 있습니다. 이전 예의 .nesting 구성요소가 프로젝트에서 삭제된 경우 관련 선택기 인스턴스를 검색하는 대신 전체 그룹을 삭제할 수 있습니다.
중첩은 다음과 같은 작업에 도움이 될 수 있습니다. - 구성 - 파일 크기 줄이기 - 리팩터링
중첩은 Chrome 112부터 사용할 수 있으며 Safari 기술 미리보기 162에서도 사용해 볼 수 있습니다.
CSS 중첩 시작하기
이 게시물의 나머지 부분에서는 다음 데모 샌드박스를 사용하여 선택 항목을 시각화합니다. 이 기본 상태에서는 아무것도 선택되지 않고 모든 항목이 표시됩니다. 다양한 도형과 크기를 선택하여 구문을 연습하고 실제로 작동하는지 확인할 수 있습니다.

샌드박스 안에는 원, 삼각형, 정사각형이 있습니다. 작은 것, 중간 크기, 큰 것이 있습니다. 파란색, 분홍색, 보라색도 있습니다. 모두 .demo 포함 요소 안에 있습니다. 다음은 타겟팅할 HTML 요소의 미리보기입니다.
<div class="demo">
<div class="sm triangle pink"></div>
<div class="sm triangle blue"></div>
<div class="square blue"></div>
<div class="sm square pink"></div>
<div class="sm square blue"></div>
<div class="circle pink"></div>
…
</div>
중첩 예시
CSS 중첩을 사용하면 다른 선택기의 컨텍스트 내에서 요소의 스타일을 정의할 수 있습니다.
.parent {
color: blue;
.child {
color: red;
}
}
이 예에서는 .child 클래스 선택자가
.parent 클래스 선택자 내에 중첩됩니다. 즉, 중첩된 .child 선택자는 .parent 클래스가 있는 요소의 하위 요소에만 적용됩니다.
이 예는 & 기호를 사용하여 상위 클래스를 배치할 위치를 명시적으로 나타낼 수도 있습니다.
.parent {
color: blue;
& .child {
color: red;
}
}
이 두 예는 기능적으로 동일하며 이 도움말에서 더 고급 예시를 살펴보면 옵션이 있는 이유가 더 명확해집니다.
원 선택
이 첫 번째 예에서는 데모 내의 원만 흐리게 하고 페이드하는 스타일을 추가하는 작업입니다.
중첩이 없는 현재 CSS:
.demo .circle {
opacity: .25;
filter: blur(25px);
}
중첩이 있는 두 가지 유효한 방법:
/* & is explicitly placed in front of .circle */
.demo {
& .circle {
opacity: .25;
filter: blur(25px);
}
}
또는
/* & + " " space is added for you */
.demo {
.circle {
opacity: .25;
filter: blur(25px);
}
}
결과, .demo 내의 모든 요소가 .circle 클래스와 함께
흐리게 표시되고 거의 보이지 않습니다.
삼각형 및 정사각형 선택
이 작업에는 그룹 선택기라고도 하는 여러 중첩된 요소를 선택해야 합니다.
중첩이 없는 현재 CSS에는 두 가지 방법이 있습니다.
.demo .triangle,
.demo .square {
opacity: .25;
filter: blur(25px);
}
또는 :is() 사용
/* grouped with :is() */
.demo :is(.triangle, .square) {
opacity: .25;
filter: blur(25px);
}
중첩이 있는 두 가지 유효한 방법:
.demo {
& .triangle,
& .square {
opacity: .25;
filter: blur(25px);
}
}
또는
.demo {
.triangle, .square {
opacity: .25;
filter: blur(25px);
}
}
결과, .circle 요소만 .demo 내에 남아 있습니다.
큰 삼각형과 원 선택
이 작업에는 요소를 선택하려면 두 클래스가 모두 있어야 하는 복합 선택기가 필요합니다.
중첩이 없는 현재 CSS:
.demo .lg.triangle,
.demo .lg.square {
opacity: .25;
filter: blur(25px);
}
또는
.demo .lg:is(.triangle, .circle) {
opacity: .25;
filter: blur(25px);
}
중첩이 있는 두 가지 유효한 방법:
.demo {
.lg.triangle,
.lg.circle {
opacity: .25;
filter: blur(25px);
}
}
또는
.demo {
.lg {
&.triangle,
&.circle {
opacity: .25;
filter: blur(25px);
}
}
}
결과, 모든 큰 삼각형과 원이 .demo 내에 숨겨져 있습니다.
복합 선택자 및 중첩 관련 고급 기능 사용 팁
& 기호는 중첩된 선택자를 결합하는 방법을 명시적으로 보여주므로 여기에서 유용합니다. 다음 예를 참고하세요.
.demo {
.lg {
.triangle,
.circle {
opacity: .25;
filter: blur(25px);
}
}
}
중첩하는 유효한 방법이지만 결과가 예상한 요소와 일치하지 않습니다.
그 이유는 &을 함께 결합한 원하는 결과를 지정하는 .lg.triangle,
.lg.circle가 없으면 실제 결과는 .lg .triangle, .lg
.circle 하위 선택자가 되기 때문입니다.
분홍색을 제외한 모든 도형 선택
이 작업에는 요소에 지정된 선택자가 없어야 하는 부정 기능 가상 클래스가 필요합니다.
중첩이 없는 현재 CSS:
.demo :not(.pink) {
opacity: .25;
filter: blur(25px);
}
중첩이 있는 두 가지 유효한 방법:
.demo {
:not(.pink) {
opacity: .25;
filter: blur(25px);
}
}
또는
.demo {
& :not(.pink) {
opacity: .25;
filter: blur(25px);
}
}
결과, 분홍색이 아닌 모든 도형이 .demo 내에 숨겨져 있습니다.
&를 사용한 정확성 및 유연성
:not() 선택자로 .demo를 타겟팅한다고 가정해 보겠습니다. 이를 위해서는 & 가 필요합니다.
.demo {
&:not() {
...
}
}
이전
예에서는 .demo :not()이 필요했지만 .demo와 :not()을 .demo:not()으로 결합합니다. 이 알림은 :hover 상호작용을 중첩하려는 경우 매우 중요합니다.
.demo {
&:hover {
/* .demo:hover */
}
:hover {
/* .demo :hover */
}
}
중첩 예시 더보기
중첩에 관한 CSS 사양에는 더 많은 예가 포함되어 있습니다. 예를 통해 구문을 자세히 알아보려면 다양한 유효한 예와 유효하지 않은 예가 포함되어 있습니다.
다음 몇 가지 예에서는 CSS 중첩 기능을 간략하게 소개하여 도입되는 기능의 범위를 이해하는 데 도움을 줍니다.
@media 중첩
스타일시트의 다른 영역으로 이동하여 선택자와 스타일을 수정하는 미디어 쿼리 조건을 찾는 것은 매우 주의를 산만하게 할 수 있습니다. 컨텍스트 내에 조건을 중첩할 수 있으므로 주의가 산만해지지 않습니다.
구문 편의를 위해 중첩된 미디어 쿼리가 현재 선택기 컨텍스트의 스타일만 수정하는 경우 최소 구문을 사용할 수 있습니다.
.card {
font-size: 1rem;
@media (width >= 1024px) {
font-size: 1.25rem;
}
}
&를 명시적으로 사용할 수도 있습니다.
.card {
font-size: 1rem;
@media (width >= 1024px) {
&.large {
font-size: 1.25rem;
}
}
}
이 예에서는 &를 사용하여 확장된 구문을 보여주면서 .large 카드를 타겟팅하여 추가 중첩 기능이 계속 작동하는지 보여줍니다.
@rules 중첩에 대해 자세히 알아보세요.
어디든 중첩
지금까지의 모든 예는 이전 컨텍스트를 계속하거나 추가했습니다. 필요한 경우 컨텍스트를 완전히 변경하거나 재정렬할 수 있습니다.
.card {
.featured & {
/* .featured .card */
}
}
& 기호는 문자열이 아닌 선택기 객체에 대한 참조를 나타내며 중첩된 선택자의 아무 곳에나 배치할 수 있습니다. 여러 번 배치할 수도 있습니다.
.card {
.featured & & & {
/* .featured .card .card .card */
}
}
이 예는 약간 쓸모없어 보이지만 선택기 컨텍스트를 반복할 수 있는 시나리오가 있습니다.
유효하지 않은 중첩 예시
유효하지 않은 중첩 구문 시나리오가 몇 가지 있으며 전처리기에서 중첩한 경우 놀랄 수 있습니다.
중첩 및 연결
많은 CSS 클래스 이름 지정 규칙은 중첩이 문자열인 것처럼 선택자를 연결하거나 추가할 수 있다고 가정합니다. 선택자는 문자열이 아니라 객체 참조이므로 CSS 중첩에서는 작동하지 않습니다.
.card {
&--header {
/* is not equal to ".card--header" */
}
}
자세한 설명은 사양을 참고하세요.
까다로운 중첩 예시
선택기 목록 및 :is() 내 중첩
다음 중첩 CSS 블록을 참고하세요.
.one, #two {
.three {
/* some styles */
}
}
선택기 목록으로 시작한 후 계속 중첩되는 첫 번째 예입니다. 이전 예는 선택기 목록으로만 끝났습니다. 이 중첩 예에는 유효하지 않은 것이 없지만 선택기 목록, 특히 ID 선택자를 포함하는 목록 내 중첩에 관한 까다로운 구현 세부정보가 있을 수 있습니다.
중첩의 의도가 작동하려면 가장 안쪽 중첩이 아닌 선택기 목록은 브라우저에서 :is()로 래핑됩니다. 이 래핑은 작성된 컨텍스트 내에서 선택기 목록의 그룹화를 유지합니다. 이 그룹화의 부작용인 :is(.one, #two)는 괄호 안의 선택기 내에서 가장 높은 점수의 구체성을 채택한다는 것입니다. 이는 :is()가 항상 작동하는 방식이지만 작성된 내용과 정확히 일치하지 않으므로 중첩 구문을 사용할 때 놀랄 수 있습니다. 요약된 트릭: ID 및 선택기 목록을 사용하여 중첩하면 구체성이 매우 높은 선택자가 될 수 있습니다.
까다로운 예를 명확하게 요약하기 위해 이전 중첩 블록이 문서에 다음과 같이 적용됩니다.
:is(.one, #two) .three {
/* some styles */
}
ID 선택자를 사용하는 선택기 목록 내에 중첩할 때 린터가 경고하도록 주의하거나 린터를 학습시키세요. 그러면 해당 선택기 목록 내의 모든 중첩의 구체성이 높아집니다.
중첩 및 선언 혼합
다음 중첩 CSS 블록을 참고하세요.
.card {
color: green;
& { color: blue; }
color: red;
}
.card 요소의 색상은 blue입니다.
중첩이 발생하기 전에 작성된 것처럼 혼합된 스타일 선언이 맨 위로 호이스트됩니다. 자세한 내용은 사양을 참고하세요.
해결 방법이 있습니다. 다음은 세 가지 색상 스타일을 &로 래핑하여 작성자가 의도한 대로 캐스케이드 순서를 유지합니다. .card 요소의 색상은 빨간색입니다.
.card {
color: green;
& { color: blue; }
& { color: red; }
}
실제로 중첩 다음에 오는 스타일을 &로 래핑하는 것이 좋습니다.
.card {
color: green;
@media (prefers-color-scheme: dark) {
color: lightgreen;
}
& {
aspect-ratio: 4/3;
}
}
기능 감지
CSS 중첩을 기능 감지하는 두 가지 좋은 방법이 있습니다. 중첩을 사용하거나 @supports를 사용하여 중첩 선택기 파싱 기능을 확인합니다.

중첩 사용:
html {
.has-nesting {
display: block;
}
.no-nesting {
display: none;
}
}
@supports 사용:
@supports (selector(&)) {
/* nesting parsing available */
}
동료인 Bramus는 이 전략을 보여주는 멋진 Codepen을 보유하고 있습니다.
Chrome DevTools로 디버깅
DevTools의 현재 중첩 지원은 최소한입니다. 현재 스타일은 예상대로 스타일 창에 표시되지만 중첩 및 전체 선택기 컨텍스트 추적은 아직 지원되지 않습니다. 이를 투명하고 명확하게 만들기 위한 설계 및 계획이 있습니다.

Chrome 113에서는 CSS 중첩을 추가로 지원할 계획입니다. 조금만 더 기다려 주시기 바랍니다.
미래
CSS 중첩은 버전 1에만 있습니다. 버전 2에서는 더 많은 구문 설탕과 기억해야 할 규칙이 줄어들 수 있습니다. 중첩 파싱이 제한되거나 까다로운 순간이 없도록 하는 것이 매우 중요합니다.
중첩은 CSS 언어의 큰 개선사항입니다. CSS의 거의 모든 아키텍처 측면에 작성 영향이 있습니다. 버전 2를 효과적으로 지정하기 전에 이 큰 영향을 깊이 탐구하고 이해해야 합니다.
마지막으로 다음은
@scope, 중첩, @layer을 모두 함께 사용하는 데모입니다. 모두 매우 흥미롭습니다.
