https://www.codeit.kr/topics/css-core-concepts/lessons/5609
https://www.codeit.kr/topics/css-core-concepts/lessons/5610
https://developer.mozilla.org/en-US/docs/Learn/CSS/Building_blocks/Cascade_and_inheritance
https://developer.mozilla.org/en-US/docs/Web/CSS/Cascade
코드잇 강의 중 CSS 핵심개념 > 캐스케이드, CSS 핵심개념 > 캐스케이드 순서 수강을 마치고는 깊은 호기심은 느끼지 않았다.
단순히, 아~ 내가 원하는대로 스타일링 하려면, 식별자를 잘 써야할 뿐만 아니라,
CSS 동작 원리에서, 요소가 어떻게 식별되고 지정되느냐에 따라
누가 누구를 덮어 쓰고, 특정 스타일링이 원하는 대로 나오지 않을 수 있기 때문에
해당 우선순위를 잘 인지하고 있어야 겠구나~
수준에 머무르고 그냥 다음 강의로 넘어갔다.
오히려 CSS 작성할 때, 애초에 중복되는 식별자가 안나오게,
개별 요소 단위로 스타일링 하면 되는 문제가 아닌가 ? 하는 생각도 들었다.
그러던 중, 마침 코드잇에서 위클리 페이퍼 주제로 CSS Casacade 에 대한 주제로 글을 써보는 과제가 주어졌고,
이 참에 더 깊은 공부 하고자 한다.
캐스케이드
는 사용자 에이전트가 다양한 소스에서 유래한 속성 값을 어떻게 결합하는지를 정의하는 알고리즘으로, 스타일 규칙이 어떻게 적용되는지를 결정하는 CSS의 핵심 개념 중 하나이다. CSS의 이름이 이를 보여준다.
Cascading Style Sheets
이를 한국말로 풀면 폭포식 스타일링 시트 정도 될 것이다. 이름대로 폭포가 떨어지듯, 특정 우선순위는 절대적으로 바뀌지 않으며, 언제나 스타일링 규칙은 우선순위가 높은 스타일에서 그 아래로 넘겨져 간다.
CSS 캐스케이드 알고리즘의 역할은 CSS 속성에 대한 올바른 값을 결정하기 위해 CSS 선언을 선택하는 것다. CSS 선언은 다양한 Origin types
에서 나올 수 있으며, 이 에는 user agent style sheet
, author style sheet
및 user style sheet
가 포함된다.
각 Origin types
에서 발생하는 스타일시트는 서로 다른 레이어에 있을 수 있지만, 기본 범위는 서로 겹치는데,,, 이를 위해 캐스케이드 알고리즘은 그들이 상호 작용하는 방식을 정의한다.
user agent style sheet
는 브라우저가 모든 문서에 기본 스타일을 제공하는 기본 스타일 시트이다. 몇 브라우저에서는 사용자가 user agent style sheets
를 수정할 수 있지만, 이는 권장되지는 않는다고 한다.속성 옆에 !importance
가 붙어있지 않는 이상, 언제나 author style sheets
에 비해 우선순위가 밀린다.
author style sheet
는 웹 개발자가 작성하는 스타일로, 가장 일반적인 스타일 시트 유형에 해당된다. 이 스타일은 user agent sheets
를 리셋하고, 특정 웹 페이지 또는 응용 프로그램의 디자인을 정의할 수 있다.작성자는 <link>
태그로 연결된 스타일 시트나, <style>
블록이나 style
속성으로 정의된 인라인 스타일을 사용하여 문서의 스타일을 정의할 수 있다.
이때 링크로 연결된 스타일 시트와 스타일 블록 내의 스타일의 우선순위는 동등한 것으로, <head>
태그 안의 위치가 이들의 우선순위를 결정해주는 것으로 확인되었다.
(코드 상으로 더 아래 있으면 우선순위가 높다.)
다만, 인라인 스타일은 언제나 다른 둘 보다 우선순위가 높다.
user style sheet
는 웹 사이트의 사용자가 사용자 지정 스타일 시트를 통해 스타일을 재정의할 수 있는 기능을 제공하며, 이는 사용자 에이전트나 브라우저 확장 프로그램을 통해 추가될 수 있다.요약) 스타일 시트의 근원이 어디느냐에 따라 스타일이 적용되는 우선순위가 갈린다.
우선순위 : user style sheet
> author style sheet
> user agent style sheet
캐스케이딩 알고리즘은 각 문서 요소에 대해 각 속성에 대한 적용 값을 찾는 방법을 결정한다. 이 알고리즘은 다음 단계를 따른다 :
Order (low to high) | Origin | Importance |
---|---|---|
1 | user-agent (browser) | normal |
2 | user | normal |
3 | author (developer) | normal |
4 | CSS @keyframe | animations |
5 | author (developer) | !important |
6 | user | !important |
7 | user-agent (browser) | !important |
8 | CSS transitions |
명시성 : 원본이 동일한 경우(동일한 스타일시트), 규칙의 명시도를 고려하여 다른 값을 선택한다. 선택자의 명시성을 비교하고 가장 높은 명시성을 가진 선언이 이는데, 그 순서는 다음과 같다. id 선택자 > class 선택자 > 요소 선택자 (h2, div)
더불어, 선택자의 개수가 많을 수록 명시도가 상승한다.
스코핑 근접성: 우선순위가 있는 원본 레이어에서 명시도가 동일한 두 선택자가 있는 경우, 범위가 제일 루트까지 DOM 계층구조를 거슬러 올라가는 규칙 내 속성 값이 이길 것이다.
출현 순서: 우선 순위가있는 원본에서 속성에 대해 경쟁하는 값이 동일한 명시도와 스코핑 근접성을 가진 스타일 블록과 일치하는 경우, 스타일 순서의 마지막 선언이 적용된다.
CSS 애니메이션은 @keyframes
at-rules
을 사용하여 상태 간의 애니메이션을 정의한다. 키프레임은 카스케이드되지 않으므로 특정 시점에서 CSS는 하나의@keyframes
만 사용하고 여러 개를 섞어 사용하지 않는다.
동일한 애니메이션 이름으로 여러 키프레임 애니메이션이 정의된 경우, 가장 높은 우선순위의 원산지 및 레이어에서 마지막으로 정의된 @keyframes
가 사용됩니다. 애니메이션 이름이 동일한 경우에도 여러 @keyframes
정의가 결합되지 않는다.
컨텐츠가 스타일을 변경하는 작업을 마치면, 애니메이션, 테마 변경 등의 상황에서 스타일을 알려진 상태로 복원해야 할 때가 있다. CSS 속성 all
을 사용하면 CSS의 (거의) 모든 것을 빠르게 알려진 상태로 다시 설정할 수 있다.
all
을 사용하면 모든 속성을 즉시 초기(기본) 상태로 복원하거나, 이전 카스케이드 수준에서 상속된 상태, 특정 원산지(사용자 에이전트 스타일시트, 작성자 스타일시트 또는 사용자 스타일시트) 또는 속성의 값을 완전히 지우는 등 다양한 옵션을 선택할 수 있다.
어느 순간 프로젝트를 진행하다 보면 특정 요소에 적용되어야 할 것으로 생각했던 CSS가 작동하지 않는 경우가 발생할텐데, 종종, 동일한 요소에 동일한 속성의 서로 다른 값을 적용하는 두 규칙을 생성하는 문제가 있었을 것이다.
카스케이드와 밀접한 관련이 있는 specificity(명시도)는 이러한 충돌이 발생할 때 어떤 규칙이 적용되는지를 제어하는 메커니즘이다. 요소에 스타일을 적용하는 규칙이 예상한 것과 다를 수 있으므로 이러한 메커니즘들이 어떻게 작동하는지를 이해해야 한다.
또한 inheritance(상속)의 개념도 중요한데, 이는 현재 요소의 부모 요소에서 설정된 값을 상속받는 CSS 속성이 있고 그렇지 않은 속성이 있음을 의미한다. 이는 예상하지 못한 동작을 일으킬 수도 있다.
명시도는 브라우저가 요소에 적용할 속성 값을 결정하는 알고리즘이다. 여러 스타일 블록이 동일한 요소를 대상으로 다른 값으로 동일한 속성을 구성하는 서로 다른 선택자를 가지고 있을 때, 명시도는 요소에 적용되는 속성 값을 결정한다. 명시도는 기본적으로 선택자의 선택이 얼마나 구체적인지를 측정하는 것이다:
요소 선택자는 덜 구체적이다. 페이지에 나타나는 해당 유형의 모든 요소를 선택하므로 가중치가 적다.
ex) h2{}
클래스 선택자는 더 구체적이다. 페이지에 있는 특정 클래스 속성 값을 가진 요소만을 선택하므로 가중치가 높다. 속성 선택자와 가상 클래스는 클래스와 동일한 가중치를 가진다.
ex) .main-heading{}
아이디 선택자가 클래스보다 더 구체적이다. 동일한 클래스 속성 값을 가질 수 있는 요소는 여럿일 수 있지만, 동일한 아이디 속성 값은 단일 요소에만 부여되는 것이 권장되기에, 아이디 선택자의 가중치가 더 높다.
ex) #main-heading-input
그리고 동일한 요소를 지정하는 선택자의 타입마저 겹칠 때는, 얼마나 많은 선택자가 사용되었느냐가 중요해진다. 동시에 많은 선택자로 요소를 지정하는 행위는 더 높은 명시도를 보장한다.
부모 요소에 설정된 일부 CSS 속성 값은 자식 요소에 상속되지만, 일부는 그렇게 작동하지 않는다.
body {
color: blue;
}
h2 {
}
span {
color: black;
}
이 경우 바디 요소의 자식인 h2는 color 속성값을 상속받아, 파란색 글자색을 가지게 된다. 반면에, span 의 경우 직접 속성값을 지정했기 때문에 검은색 글자색을 보인다.
body {
width: 50%;
}
div {
}
반면에 width
속성 값의 경우 상속이 이루어지지 않는다. div 요소가 body 안에 소속되어 있지만, 부모의 너비값을 물려받지는 않는데, 만약 이를 물려받을 경우 css에서 너비 스타일링은 매우 복잡해질 것이다.
상속되지 않는 속성으로는 width
, margin
, padding
, border
등이 있다.
CSS는 상속을 제어하기 위한 다섯 가지 특별한 범용 속성 값을 제공하는데, 모든 CSS 속성이 이러한 값을 수용한다.
inherit
선택한 요소에 적용된 속성 값을 해당 부모 요소와 동일하게 설정한다. 이 값은 효과적으로 상속을 적용한다.
initial
선택한 요소에 적용된 속성 값을 해당 속성의 초기 값으로 설정한다.
revert
선택한 요소에 적용된 속성 값을 속성에 적용된 기본값이 아닌 브라우저의 기본 스타일링으로 재설정한다. 이 값은 많은 경우에 unset
처럼 작동한다.
revert-layer
선택한 요소에 적용된 속성 값을 이전 캐스케이드 레이어에서 설정된 값으로 재설정한다.
unset
속성을 해당 속성이 자연스럽게 상속되는 경우 inherit
처럼 작동하고, 그렇지 않은 경우 initial
처럼 작동한다.
CSS의 세 가지 개념(캐스케이드, 특수성 및 상속)은 함께 어떤 요소에 어떤 CSS가 적용되는지를 제어한다. 이러한 개념이 어떻게 작동하는지는 조금 복잡해 보일 수 있지만 CSS에 대한 경험이 쌓이면 기억하기 시작하고, 세부 정보를 잊어버린 경우에는 언제든지 찾아볼 수 있다..!
심지어 경험 많은 개발자도 모든 세부 사항을 기억하지는 않는다고 한다...
위 영상에서 더 많은 정보를 찾아 볼 수 있다.