CSS 네스팅에서 &를 빼먹었더니 전혀 다른 요소가 선택된 이유
문제 발생
Sass를 걷어내고 네이티브 CSS 네스팅으로 옮기면서 아래처럼 썼는데, .card가 아니라 카드 안의 a 요소들에 스타일이 붙었습니다.
.card {
padding: 16px;
a { /* 의도: .card가 링크일 때 */
text-decoration: none;
}
}그리고 Sass에서 즐겨 쓰던 이 패턴은 아무리 고쳐도 동작하지 않았습니다.
.card {
&--wide { ... } /* Sass에서는 .card--wide로 합쳐졌다 */
}원인 분석
네이티브 네스팅에서 &를 생략하면 후손 결합자가 됩니다. .card { a { ... } }는 .card a { ... }입니다. 의도가 ".card이면서 동시에 a"였다면 &를 붙여야 합니다.
두 번째는 더 근본적입니다. 네이티브 네스팅은 선택자 문자열을 이어 붙이지 않습니다. Sass는 전처리기라 &--wide를 텍스트로 합쳐 .card--wide를 만들 수 있었지만, CSS 네스팅은 실제 선택자 구조를 다룹니다. &--wide는 문법적으로 성립하지 않습니다.
관련해서 알아둘 규칙이 하나 더 있습니다. 복합 선택자에서 타입 선택자는 맨 앞에 와야 합니다. 그래서 &a처럼 쓸 수 없고, 순서를 뒤집어 a&로 써야 a.card로 해석됩니다.
해결 방안
- "이 요소 자신"이면
&를 명시합니다.
.card {
padding: 16px;
a& { text-decoration: none; } /* a.card */
&:hover { background: #f5f5f5; }
&.is-active { border-color: blue; }
}- BEM 변형 클래스는 이어 붙이지 말고 펼쳐 씁니다. 이름을 검색할 수 있게 되는 부수 효과도 있습니다 — Sass 시절
.card--wide는 코드베이스에서 grep으로 찾히지 않았습니다.
.card { padding: 16px; }
.card--wide { padding: 24px; }- 의심스러우면
&를 붙여 둡니다.& .child는.child와 완전히 동일하게 해석되므로, 항상 붙이는 규칙을 팀에서 정하면 이 실수 자체가 사라집니다. - 중첩 깊이를 제한합니다. 전처리기 시절부터 이어진 문제로, 세 단계를 넘어가면 최종 선택자가 무엇인지 읽어서 알 수 없게 되고 특이도도 함께 올라갑니다.
@media도 중첩할 수 있습니다. 컴포넌트 규칙과 그 반응형 규칙을 한자리에 둘 수 있다는 것이 네스팅의 실질적인 이득입니다.
.card {
grid-template-columns: 1fr;
@media (width > 700px) {
grid-template-columns: 200px 1fr;
}
}
댓글0
댓글을 남기려면 로그인이 필요해요. 로그인
아직 댓글이 없어요. 첫 의견을 편하게 남겨 보세요.