|
| 1 | +--- |
| 2 | +title: CSS Cascade Algorithm 이란? (Feat. Cascade Layer) |
| 3 | +createdAt: 2025-04-13 |
| 4 | +category: WEB |
| 5 | +pinned: true |
| 6 | +description: CSS Cascade Algorithm 은 브라우저에서 스타일을 적용하는 방법을 정의합니다. CSS Cascade Algorithm 을 이해하면 CSS 스타일 우선순위를 이해할 수 있습니다. |
| 7 | +--- |
| 8 | + |
| 9 | +# 📖 스타일 충돌을 해결하는 방법, 무엇이 문제일까 ? |
| 10 | + |
| 11 | +CSS 를 사용할 때, 종종 스타일이 예기치 않게 덮어씌워지는 문제를 겪습니다. <br/> |
| 12 | +특히, 여러 개발자와 함께 협업하는 프로젝트에서는 스타일 충돌이 더욱 빈번하게 발생합니다. |
| 13 | + |
| 14 | +이러한 스타일 충돌 문제를 해결하기 위해 **BEM(Block-Element-Modifier)** 나 **CSS Modules**, **CSS-in-JS** 와 같은 다양한 접근 방식이 등장했습니다. |
| 15 | + |
| 16 | +하지만, **CSS 스타일의 적용방식 (우선순위)** 가 어떻게 결정되는지 이해하지 못하면, 근본적인 해결책을 찾기 어렵습니다 |
| 17 | + |
| 18 | +<br /> |
| 19 | + |
| 20 | +# 🎨 CSS Cascade Algorithm 이란? |
| 21 | + |
| 22 | +CSS 는 Cascading Style Sheets 의 약자로, **스타일 우선순위** 를 결정하는 방식을 정의합니다. |
| 23 | + |
| 24 | +> **Cascade** : 폭포 또는 위에서 아래로 떨어지는, 흐르는 |
| 25 | +
|
| 26 | +CSS는 요소에 여러 스타일이 적용되었을 때 다음과 같은 우선순위 규칙에 따라 최종 스타일을 결정합니다. <br/> |
| 27 | + |
| 28 | +우선순위는 다음과 같은 순서로 적용됩니다 |
| 29 | + |
| 30 | +> 1. 중요도 (`!important`) |
| 31 | +> 2. 스타일의 유래 (origin) |
| 32 | +> 3. Cascade Layer (sub-origin) |
| 33 | +> 4. Selector 의 구체성 (specificity) |
| 34 | +> 5. 선언 순서 (order) |
| 35 | +> 6. 상속 (inheritance) |
| 36 | +
|
| 37 | +## 1. 중요도 (`!important`) |
| 38 | + |
| 39 | +CSS 에서 `!important` 키워드를 사용하면 해당 스타일의 우선순위가 가장 높아집니다. |
| 40 | + |
| 41 | +```css |
| 42 | +div { |
| 43 | + color: red !important; |
| 44 | +} |
| 45 | +``` |
| 46 | + |
| 47 | +하지만, `!important` 를 남발하면 코드의 유지보수가 어려워지고, 스타일 충돌 문제가 더욱 복잡해집니다. 따라서, `!important` 를 사용하는 것은 지양해야 합니다. |
| 48 | + |
| 49 | +## 2. 스타일의 유래 (origin) |
| 50 | + |
| 51 | +CSS 는 다양한 origin 에서 선언될 수 있으며, 어떤 스타일이 우선적으로 적용되는지는 origin 에 따라 달라집니다. |
| 52 | + |
| 53 | +| Origin | 설명 | 우선순위 | |
| 54 | +| -------------------- | ------------------------------ | -------- | |
| 55 | +| User Agent | 브라우저의 기본 스타일 | 0 | |
| 56 | +| User | 사용자가 지정한 스타일 | 1 | |
| 57 | +| Author | 개발자가 작성한 스타일 | 2 | |
| 58 | +| CSS Animation | CSS 애니메이션 스타일 | 3 | |
| 59 | +| Inline | HTML 요소에 직접 작성한 스타일 | 4 | |
| 60 | +| User && !important | 사용자가 설정한 !important | 5 | |
| 61 | +| Author && !important | 개발자가 설정한 !important | 6 | |
| 62 | + |
| 63 | +> ‼️ **Author vs User** <br /> |
| 64 | +> Author : 개발자가 작성한 스타일 <br /> |
| 65 | +> User : 웹사이트를 보는 사용자가 설정한 스타일로 주로 접근성을 위한 사용자 정의 스타일 <br /> |
| 66 | +> 예) 웹페이지 폰트 크기 강제로 키우기, 고대비 모드 등.. |
| 67 | +
|
| 68 | +그렇다면 개발자는 origin 을 변경할 수도 없고, `!important` 를 남발할 수도 없으니, 어떻게 해야 할까요? <br/> |
| 69 | + |
| 70 | +## 3. Cascade Layer (sub-origin) ⭐️ |
| 71 | + |
| 72 | +개발자는 그럼 정말로 origin 을 변경할 수 없을까요? <br/> |
| 73 | + |
| 74 | +Cascade Layer는 CSS의 origin 내에서 스타일 우선순위를 세부적으로 제어하는 방법입니다. 같은 origin에서 동일한 specificity를 가진 스타일 간에 Layer 순서가 우선순위를 결정합니다. <br/> |
| 75 | +최근 브라우저(Chrome99+, Firefox97+, Safari TP 및 iOS Safari)는 @layer 키워드를 지원합니다.<br /> |
| 76 | + |
| 77 | +각 origin 레벨에 대해 여러개의 cascade layer 가 있을 수 있고, <br/> |
| 78 | +각 레벨의 cascade layer 는 만들어진 순서에 따라 서로 다른 우선순위를 가집니다. <br/> |
| 79 | + |
| 80 | +기본적으로 Layer 의 우선순위는 선언 순서로 결정됩니다. |
| 81 | + |
| 82 | +```css |
| 83 | +@layer a, b, c; |
| 84 | + |
| 85 | +@layer a { |
| 86 | +} |
| 87 | +@layer b { |
| 88 | +} |
| 89 | +@layer c { |
| 90 | +} |
| 91 | +``` |
| 92 | + |
| 93 | +Layer `c` 가 가장 나중에 선언되었으므로 `c` 에 있는 스타일이 우선적으로 적용됩니다. <br/> |
| 94 | + |
| 95 | +### 3.1 `@layer` 기본 사용법 |
| 96 | + |
| 97 | +캐스케이드 레이어는 다음과 같이 선언할 수 있습니다 |
| 98 | + |
| 99 | +```css |
| 100 | +@layer layer-name { |
| 101 | +} |
| 102 | +``` |
| 103 | + |
| 104 | +`@layer` 를 사용하여 레이어를 선언한 후, 해당 레이어에 스타일을 작성하면 됩니다. <br/> |
| 105 | + |
| 106 | +또, `@import` 를 사용하여 외부 CSS 파일을 가져올 때도 레이어를 지정할 수 있습니다. |
| 107 | + |
| 108 | +```css |
| 109 | +@import url("style.css") layer-name; |
| 110 | +``` |
| 111 | + |
| 112 | +이렇게 하면 `style.css` 파일 전체가 `layer-name` 레이어에 포함됩니다. <br/> |
| 113 | + |
| 114 | +### 3.2 중첩 레이어는 |
| 115 | + |
| 116 | +중첩 레이어를 사용하면 레이어의 이름 충돌을 방지하고 계층적으로 레이어를 구성할 수 있습니다. <br/> |
| 117 | + |
| 118 | +다음과 같이 `@layer` 를 중첩해서 구성하거나, |
| 119 | + |
| 120 | +```css |
| 121 | +@layer a { |
| 122 | + @layer b { |
| 123 | + @layer c { |
| 124 | + } |
| 125 | + } |
| 126 | +} |
| 127 | +``` |
| 128 | + |
| 129 | +`@import` 를 사용할 수 있습니다. |
| 130 | + |
| 131 | +```css |
| 132 | +@import url("style.css") layer(layerA.layerB); |
| 133 | +``` |
| 134 | + |
| 135 | +이렇게 하면 layerA 내부에 layerB 레이어가 생성되고, `style.css` 에 선언된 레이어는 `layerA.layerB` 레이어에 포함됩니다. <br/> |
| 136 | + |
| 137 | +### 3.3 Layer 는 origin 내부의 우선순위 서브 시스템이다 |
| 138 | + |
| 139 | +위에서 언급했던것 처럼, CSS의 origin은 다음과 같은 순서로 적용됩니다. |
| 140 | + |
| 141 | +> 1. User Agent |
| 142 | +> 2. User |
| 143 | +> 3. Author |
| 144 | +> 4. Inline Style |
| 145 | +> 5. Author !important |
| 146 | +> 6. User !important |
| 147 | +
|
| 148 | +여기서 Cascade Layer는 Author, Author !important 범위 내에서만 적용됩니다. |
| 149 | + |
| 150 | +```css |
| 151 | +@layer base { |
| 152 | + .btn { |
| 153 | + color: red; |
| 154 | + } |
| 155 | +} |
| 156 | +@layer theme { |
| 157 | + .btn { |
| 158 | + color: blue; |
| 159 | + } |
| 160 | +} |
| 161 | +``` |
| 162 | + |
| 163 | +여기서, |
| 164 | + |
| 165 | +두 스타일 모두 Author origin에 속하므로, <br/> |
| 166 | + |
| 167 | +이 경우 우선순위는 **Cascade Layer 순서(base → theme)**를 따르게 됩니다.<br/> |
| 168 | + |
| 169 | +따라서 theme가 나중에 선언되었기 때문에 `.btn { color: blue }`가 최종 적용됩니다.<br/> |
| 170 | + |
| 171 | +즉, 같은 origin에서 동일한 specificity를 가진 스타일 간에, layer 순서가 우선순위를 결정합니다. |
| 172 | + |
| 173 | +## 4. Selector 의 구체성 |
| 174 | + |
| 175 | +셀렉터는 더 구체적일수록 더 우선적으로 고려되어 스타일이 적용되기 때문에, <br/> |
| 176 | +셀렉터를 구체적으로 작성하여 스타일의 우선순위를 높일 수 있습니다. |
| 177 | + |
| 178 | +<br /> |
| 179 | + |
| 180 | +CSS 는 다음과 같은 우선순위를 따릅니다 |
| 181 | + |
| 182 | +> 인라인 스타일 (inline style) > id 셀렉터 > class 및 가상 셀렉터 > 태그 셀렉터 > 전체 셀렉터 > 상위 요소에 의해 상속된 속성 |
| 183 | +
|
| 184 | +이때, 동일한 우선순위의 셀렉터가 있다면, `셀렉터의 숫자가 더 많은 선언이 우선순위가 높아집니다` |
| 185 | + |
| 186 | +## 5. 선언 순서 |
| 187 | + |
| 188 | +CSS 에서 동일한 우선순위의 스타일이 여러 개 선언된 경우, **선언된 순서**에 따라 마지막에 선언된 스타일이 우선적으로 적용됩니다. |
| 189 | + |
| 190 | +```css |
| 191 | +div { |
| 192 | + color: red; |
| 193 | +} |
| 194 | +div { |
| 195 | + color: blue; |
| 196 | +} |
| 197 | +``` |
| 198 | + |
| 199 | +위의 예시에서 `div` 요소는 `blue` 색상이 적용됩니다. <br/> |
| 200 | + |
| 201 | +또, link 태그를 통해 css 파일을 로드할 때도 나중에 쓰인 link 태그의 스타일이 우선적으로 적용됩니다. |
| 202 | + |
| 203 | +```html |
| 204 | +<link rel="stylesheet" href="style1.css" /> |
| 205 | +<link rel="stylesheet" href="style2.css" /> |
| 206 | +<link rel="stylesheet" href="style3.css" /> |
| 207 | +``` |
| 208 | + |
| 209 | +위의 예시에서 `style3.css` 의 스타일이 `style1.css`, `style2.css` 의 스타일보다 우선적으로 적용됩니다. |
| 210 | + |
| 211 | +<br /> |
| 212 | + |
| 213 | +## 6. 상속 |
| 214 | + |
| 215 | +CSS 에서는 부모 요소의 스타일이 자식 요소에 상속되는 경우가 있습니다. <br/> |
| 216 | +`color` `font-*` `text-*` `visibility` `white-space` `list-style` `border` 등과 같은 속성은 상속되는 반면에, |
| 217 | +`margin` `padding` `background` `width` `height` `position` 등과 같은 속성은 상속되지 않습니다. |
| 218 | + |
| 219 | +상속은 CSS 의 기본적인 동작 방식이므로, 상속을 활용하여 스타일을 일관되게 적용할 수 있습니다. <br/> |
| 220 | +또한, `inherit` 키워드를 사용하여 부모 요소의 스타일을 자식 요소에 강제로 상속시킬 수 있습니다. |
| 221 | + |
| 222 | +| inherit | initial | unset | |
| 223 | +| ------------------------- | ----------------- | --------------------------- | |
| 224 | +| 부모 요소의 스타일을 상속 | 기본값으로 초기화 | 상속 또는 기본값으로 초기화 | |
| 225 | + |
| 226 | +# 🔗 참고자료 |
| 227 | + |
| 228 | +- [MDX Cascade Layer](https://developer.mozilla.org/ko/docs/Learn_web_development/Core/Styling_basics/Cascade_layers) |
0 commit comments