본문으로 건너뛰기
개발 머꼬
개발 노트CSS
hohyeon.dev16

라이브러리 스타일을 덮으려고 !important를 쓰다가 @layer로 정리한 과정

  • #CSS
  • #Engineering Note

문제 발생

UI 라이브러리의 .btn 스타일을 덮으려는데 상대 특이도가 더 높아서 계속 밀렸습니다. 선택자를 길게 늘이다가 결국 !important를 붙였고, 그러자 이번엔 우리 쪽의 상태 스타일이 그걸 덮지 못했습니다.

/* 라이브러리 */
.theme .btn.btn-primary { background: blue; }

/* 우리 코드 — 계속 지는 중 */
.btn-primary { background: green; }
.page .content .btn-primary { background: green; }   /* 특이도 경쟁 */
.btn-primary { background: green !important; }       /* 결국 이렇게 */

원인 분석

특이도는 누가 더 구체적으로 썼는가를 재는 규칙이지 누가 더 중요한가를 재는 규칙이 아닙니다. 그래서 "라이브러리보다 우리 코드가 우선"이라는 의도를 특이도로 표현하려면 선택자를 계속 길게 만들어야 하고, 그 경쟁의 끝이 !important입니다.

캐스케이드 레이어(@layer)는 이 의도를 직접 표현합니다. 레이어를 선언한 순서가 우선순위이고, 특이도는 같은 레이어 안에서만 비교됩니다. 늦게 선언한 레이어의 낮은 특이도 규칙이 먼저 선언한 레이어의 높은 특이도 규칙을 이깁니다.

두 가지를 더 알아야 합니다.

  • 레이어에 속하지 않은 스타일이 가장 강합니다. 어떤 레이어에도 넣지 않은 규칙은 모든 레이어를 이깁니다.
  • !important는 레이어 순서를 뒤집습니다. 일반 선언은 나중 레이어가 이기지만, !important끼리는 먼저 선언한 레이어가 이깁니다.

해결 방안

  1. 순서를 파일 맨 위에서 한 번에 선언합니다. 규칙이 없어도 순서만 먼저 정할 수 있고, 이후 어디서 레이어에 내용을 추가하든 이 순서가 유지됩니다.
@layer reset, vendor, base, components, utilities;
  1. 라이브러리는 import하면서 레이어에 넣습니다. 라이브러리 CSS를 한 줄도 고치지 않고 우선순위를 낮출 수 있습니다.
@import url("ui-library.css") layer(vendor);

이제 components 레이어의 .btn-primary { background: green; }vendor 레이어의 .theme .btn.btn-primary를 이깁니다. 특이도를 올릴 필요도, !important도 필요 없습니다.

  1. 유틸리티는 마지막 레이어에 둡니다. "이건 무조건 이겨야 한다"는 성격의 클래스가 사는 자리입니다.
@layer utilities {
  .hidden { display: none; }
}
  1. 레이어 밖에는 아무것도 두지 않는 편이 낫습니다. 레이어 밖 스타일이 전부를 이기므로, 하나라도 새어 나가면 레이어 설계가 무의미해집니다. 정말 마지막 수단으로만 남겨 둡니다.
  2. !important가 남아 있다면 순서가 뒤집힌다는 점을 기억합니다. 레이어를 도입하면서 기존 !important를 그대로 두면 의도와 반대로 동작할 수 있습니다. 레이어로 옮기는 김에 걷어내는 것이 목적에 맞습니다.

공식 문서

마지막 수정

좋아요북마크

댓글0

아직 댓글이 없어요. 첫 의견을 편하게 남겨 보세요.