시리즈1.CSS 기본 원리와 렌더링 이해-2편.CSS 기본 개념-선택자부터 단위까지 완벽 정리
by Jeongjin Kim
지난 글에서 브라우저가 CSS를 어떻게 렌더링하는지 알아봤습니다.
위와 같이 6단계 파이프라인을 통해 CSS가 화면에 그려진다는 것을 확인했습니다.
이제 CSS를 실제로 작성할 때 꼭 알아야 할 기본 개념들을 깊이 있게 살펴보겠습니다. 선택자는 어떻게 동작하고, 왜 어떤 스타일이 다른 스타일을 덮어쓰는지, 그리고 각각의 CSS 단위는 언제 사용해야 하는지 알아보겠습니다.
CSS 규칙의 구조
먼저 CSS 규칙(Rule Set)이 어떻게 구성되어 있는지 정확히 알아야 합니다:
.button {
color: blue;
font-size: 16px;
margin: 10px 0;
}
- 선택자(Selector):
.button
- 스타일을 적용할 요소를 선택 - 선언 블록(Declaration Block): 중괄호
{}
안의 전체 내용 - 선언(Declaration):
color: blue;
- 속성과 값의 조합 - 속성(Property):
color
,font-size
,margin
- 값(Value):
blue
,16px
,10px 0
브라우저는 이 규칙을 파싱해서 CSSOM에 저장하고, 나중에 DOM 요소와 매칭시킵니다. 이 매칭 과정에서 선택자의 역할이 매우 중요합니다.
CSS의 선택자-스타일링 할 요소를 선택하는 방법
기본 선택자들
/* 전체 선택자 - 모든 요소 선택 */
* {
box-sizing: border-box;
}
/* 타입 선택자 - 특정 태그 선택 */
h1 {
font-size: 2rem;
margin: 0 0 1rem 0;
}
/* 클래스 선택자 - 가장 많이 사용 */
.highlight {
background-color: yellow;
padding: 0.25rem;
}
/* ID 선택자 - 고유한 요소 */
#header {
position: sticky;
top: 0;
}
실무 팁: ID 선택자는 특정성(specificity)이 너무 높아서 나중에 덮어쓰기 어려워집니다. 가능한 한 클래스 선택자를 사용하는 것이 유지보수에 유리합니다.
결합자(Combinator): 요소 간의 관계 표현
결합자는 선택자 사이의 관계를 정의하는 중요한 도구입니다. 브라우저는 DOM 트리를 순회하면서 이 관계를 평가합니다.
후손 선택자 (공백(스페이스)
)
/* .article 안의 모든 p 태그 (깊이 무관) */
.article p {
line-height: 1.6;
margin-bottom: 1rem;
}
<div class="article">
<p>이것도 선택됨</p>
<section>
<p>이것도 선택됨 (깊은 곳에 있어도)</p>
</section>
</div>
브라우저는 .article
을 찾은 다음, 그 안의 모든 깊이에서 p
태그를 찾습니다. 이 과정은 재귀적으로 수행되기 때문에 깊게 중첩된 선택자는 성능에 영향을 줄 수 있습니다.
자식 선택자 (>
)
/* .nav의 직접적인 자식 li만 선택 */
.nav > li {
display: inline-block;
margin-right: 1rem;
}
<ul class="nav">
<li>Home</li> <!-- 선택됨 -->
<li>About
<ul>
<li>Team</li> <!-- 선택 안됨 (손자) -->
</ul>
</li>
</ul>
자식 선택자는 직계 자식만 선택하므로 후손 선택자보다 성능이 좋습니다. 명확한 구조적 관계를 표현할 때 사용합니다.
인접 형제 선택자 (+
)
/* h2 바로 다음에 오는 p만 선택 */
h2 + p {
font-weight: bold;
margin-top: 0;
}
<h2>제목</h2>
<p>이 문단만 선택됨 (바로 다음)</p>
<p>이건 선택 안됨</p>
인접 형제 선택자는 특정 요소 바로 다음의 형제 요소만 선택합니다. 제목 다음의 첫 문단에 특별한 스타일을 적용할 때 유용합니다.
일반 형제 선택자 (~
)
/* h2 이후에 오는 모든 p 선택 */
h2 ~ p {
color: #666;
}
<div>
<p>선택 안됨 (h2 이전)</p>
<h2>제목</h2>
<p>선택됨</p>
<div>중간에 다른 요소</div>
<p>이것도 선택됨</p>
</div>
속성 선택자: 세밀한 타겟팅
속성 선택자는 HTML 속성을 기반으로 요소를 선택합니다. 폼 요소나 링크를 다룰 때 특히 유용합니다.
/* type 속성이 "text"인 input */
input[type="text"] {
border: 1px solid #ddd;
padding: 0.5rem;
}
/* href 속성이 있는 a 태그 */
a[href] {
color: blue;
}
/* class 속성에 "btn"이 포함된 요소 */
[class*="btn"] {
cursor: pointer;
border: none;
}
/* href가 "https://"로 시작하는 링크 */
a[href^="https://"] {
color: green;
}
/* href가 ".pdf"로 끝나는 링크 */
a[href$=".pdf"]::after {
content: " (PDF)";
color: #666;
font-size: 0.875em;
}
/* data 속성 활용 */
[data-status="active"] {
background-color: #4CAF50;
}
[data-priority="high"] {
border-left: 4px solid red;
}
가상 클래스와 가상 요소
가상 클래스는 요소의 특정 상태를 선택하고, 가상 요소는 요소의 특정 부분을 선택합니다.
/* 상태 기반 가상 클래스 */
a:hover { color: red; }
input:focus { outline: 2px solid blue; }
button:disabled { opacity: 0.5; cursor: not-allowed; }
input:checked + label { font-weight: bold; }
/* 구조 기반 가상 클래스 */
tr:nth-child(even) { background-color: #f5f5f5; }
p:first-child { margin-top: 0; }
p:last-child { margin-bottom: 0; }
li:nth-of-type(3n) { color: red; } /* 3의 배수 번째 */
/* 부정 가상 클래스 */
input:not([type="submit"]) {
border: 1px solid #ccc;
}
/* 가상 요소로 콘텐츠 추가 */
.required::after {
content: " *";
color: red;
}
blockquote::before {
content: "";
font-size: 2em;
line-height: 0;
}
/* 첫 글자, 첫 줄 스타일링 */
p::first-letter {
font-size: 2em;
font-weight: bold;
}
p::first-line {
text-transform: uppercase;
}
상속(Inheritance)
CSS 상속은 DOM 트리를 따라 자동으로 이루어집니다. 이는 렌더링 성능 최적화의 핵심 개념입니다.
<div style="font-family: Arial, sans-serif; color: #333; line-height: 1.5;">
<h1>이 제목은 Arial 폰트와 #333 색상을 상속받습니다</h1>
<p>이 문단도 모든 스타일을 상속받습니다</p>
<ul>
<li>목록 아이템도 마찬가지입니다</li>
</ul>
</div>
상속되는 속성들 (대부분 텍스트 관련)
텍스트 관련 속성들이 상속되는 이유는 문서 전체의 일관성을 쉽게 유지하기 위함입니다.
.parent {
/* 이 속성들은 모두 자식에게 상속됨 */
font-family: "Helvetica Neue", sans-serif;
font-size: 16px;
font-weight: 400;
line-height: 1.5;
color: #333;
text-align: center;
letter-spacing: 0.5px;
word-spacing: 0.1em;
text-transform: uppercase;
/* 목록 관련도 상속됨 */
list-style: none;
list-style-position: inside;
/* 표 관련 */
border-collapse: collapse;
border-spacing: 0;
/* 커서 */
cursor: pointer;
}
상속되지 않는 속성들 (대부분 박스 모델과 배치)
박스 모델 관련 속성이 상속되지 않는 이유는 각 요소가 독립적인 레이아웃을 가져야 하기 때문입니다.
.parent {
/* 이 속성들은 상속되지 않음 */
width: 300px;
height: 200px;
margin: 20px;
padding: 10px;
border: 1px solid #ddd;
background-color: #f5f5f5;
position: relative;
display: flex;
z-index: 10;
overflow: hidden;
float: left;
}
상속 제어하기
때로는 상속을 명시적으로 제어해야 할 필요가 있습니다.
.parent {
color: red;
border: 2px solid blue;
}
.child {
/* 강제로 상속받기 */
border: inherit; /* 부모의 border를 강제 상속 */
/* 상속 차단하기 */
color: initial; /* 브라우저 기본값으로 리셋 */
/* 계산된 값 사용 */
width: unset; /* 상속되는 속성이면 상속, 아니면 initial */
/* 모든 상속 차단 */
all: unset; /* 모든 속성을 초기값으로 */
}
우선순위
여러 CSS 규칙이 같은 요소를 선택할 때 무엇이 적용될지 결정하는 시스템입니다. 브라우저는 이를 계산해서 CSSOM을 구성합니다.
우선순위 계산법 (점수제)
우선순위는 4개의 숫자로 표현됩니다: [inline, id, class, element]
/* 점수: 0,0,0,1 (태그 1개) */
p { color: black; }
/* 점수: 0,0,1,0 (클래스 1개) */
.text { color: blue; }
/* 점수: 0,0,1,1 (클래스 1개 + 태그 1개) */
.content p { color: green; }
/* 점수: 0,0,2,0 (클래스 2개) */
.article.featured { color: purple; }
/* 점수: 0,1,0,0 (ID 1개) */
#main { color: red; }
/* 점수: 0,1,1,0 (ID 1개 + 클래스 1개) */
#main .text { color: orange; }
/* 점수: 1,0,0,0 (인라인 스타일) */
<p style="color: yellow;">노란 텍스트</p>
실제 계산 예시
실제 개발에서 마주치는 복잡한 선택자의 우선순위를 계산해봅시다.
/* 점수: 0,1,2,2 (ID 1개 + 클래스 2개 + 태그 2개) */
#sidebar .widget-list li.active {
background-color: #e0e0e0;
}
/* 점수: 0,0,1,3 (클래스 1개 + 태그 3개) */
.content div ul li {
background-color: white; /* 위 규칙에 의해 덮어쓰임 */
}
/* 점수: 0,0,2,1 (속성 선택자 1개 + 클래스 1개 + 태그 1개) */
input[type="text"].error {
border-color: red;
}
/* 점수: 0,0,3,0 (가상 클래스도 클래스로 계산) */
.button:hover:focus {
outline: 2px solid blue;
}
캐스케이딩(Cascading) 규칙
CSS의 ‘C’가 바로 Cascading입니다. 같은 우선순위라면 나중에 작성된 규칙이 적용됩니다:
.button { background: red; }
.button { background: blue; } /* 이게 적용됨 */
/* 하지만 우선순위가 다르면 순서 무관 */
.button { background: red; } /* 점수: 0,0,1,0 */
#nav .button { background: blue; } /* 점수: 0,1,1,0, 이게 적용됨 */
/* 미디어 쿼리 내부의 규칙도 동일한 우선순위 */
.text { color: black; }
@media (max-width: 768px) {
.text { color: blue; } /* 768px 이하에서만 적용 */
}
!important: 최후의 수단
!important
는 일반적인 우선순위 규칙을 무시합니다. 하지만 코드의 유지보수성을 크게 해칩니다.
.button {
background: red !important; /* 다른 모든 규칙을 무시 */
}
#header .button {
background: blue; /* important에 의해 무시됨 */
}
/* important끼리는 다시 우선순위 규칙 적용 */
.button {
background: red !important;
}
#header .button {
background: blue !important; /* 더 높은 우선순위로 이게 적용 */
}
주의: !important
는 나중에 스타일을 덮어쓰기 매우 어렵게 만듭니다. 다음 경우에만 제한적으로 사용하세요:
- 서드파티 CSS를 덮어써야 할 때
- 유틸리티 클래스를 만들 때 (예:
.hidden { display: none !important; }
)
CSS 단위: 언제 무엇을 써야 할까?
CSS 단위는 레이아웃과 타이포그래피의 핵심입니다. 각 단위는 특정 용도에 최적화되어 있습니다.
절대 단위: px
픽셀은 가장 직관적이고 예측 가능한 단위입니다. 스크린의 물리적 픽셀과 1:1로 매핑되지는 않지만(디바이스 픽셀 비율 때문에), CSS에서는 일관된 단위로 동작합니다.
.card {
border: 1px solid #ddd; /* 얇은 선은 px가 최적 */
border-radius: 8px; /* 작은 곡률도 px */
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); /* 그림자도 px */
}
.icon {
width: 24px; /* 아이콘은 고정 크기가 보통 */
height: 24px;
}
/* 미디어 쿼리 브레이크포인트도 px */
@media (min-width: 768px) {
.container {
max-width: 1200px;
}
}
px를 사용해야 하는 경우:
- 보더, 그림자 등 세밀한 디자인 요소
- 아이콘, 로고 등 고정 크기 요소
- 1px, 2px 같은 매우 작은 값
- 미디어 쿼리 브레이크포인트
상대 단위: em
em은 현재 요소의 font-size
를 기준으로 계산됩니다. 컴포넌트 내부의 상대적 크기를 표현할 때 유용합니다.
.card {
font-size: 16px;
padding: 1em; /* 16px * 1 = 16px */
margin: 0.5em 0; /* 16px * 0.5 = 8px */
}
.card .title {
font-size: 1.25em; /* 16px * 1.25 = 20px */
margin-bottom: 0.5em; /* 20px * 0.5 = 10px (자신의 font-size 기준!) */
}
em의 함정: 중첩될 때 누적됩니다
.parent {
font-size: 1.2em; /* 기본 16px * 1.2 = 19.2px */
}
.parent .child {
font-size: 1.2em; /* 19.2px * 1.2 = 23.04px (누적!) */
}
.parent .child .grandchild {
font-size: 1.2em; /* 23.04px * 1.2 = 27.648px (또 누적!) */
}
이런 누적 문제 때문에 em보다는 rem을 선호하는 경우가 많습니다.
상대 단위: rem
rem은 루트 요소(html
)의 font-size
를 기준으로 계산됩니다. 일관성 있는 스케일링이 가능합니다.
html {
font-size: 16px; /* 기본값, 브라우저 설정에 따라 변경 가능 */
}
.section {
font-size: 1.125rem; /* 16px * 1.125 = 18px */
padding: 2rem; /* 16px * 2 = 32px */
margin: 1.5rem 0; /* 16px * 1.5 = 24px */
}
.section .title {
font-size: 1.5rem; /* 16px * 1.5 = 24px (항상 일정!) */
}
rem의 장점: 접근성과 일관성
/* 사용자가 브라우저에서 폰트 크기를 150%로 늘리면 */
html { font-size: 24px; } /* 16px * 1.5 */
/* 모든 rem 값이 자동으로 1.5배가 됨 */
.section {
padding: 2rem; /* 24px * 2 = 48px */
margin: 1.5rem 0; /* 24px * 1.5 = 36px */
}
퍼센트 단위: %
부모 요소의 해당 속성 값을 기준으로 계산됩니다. 반응형 레이아웃의 기초입니다. 아래는 container
안에 sidebar
와 main
이 있고, sidebar
는 25%
, main
은 75%
의 너비를 가지고 있습니다. sidebar
의 폭은 25%
이므로 부모 요소인 container
의 폭 1200px
의 25%
인 300px
이 됩니다.
.container {
width: 1200px;
height: 600px;
}
.sidebar {
width: 25%; /* 1200px * 0.25 = 300px */
height: 100%; /* 600px * 1 = 600px */
}
.main {
width: 75%; /* 1200px * 0.75 = 900px */
padding: 2%; /* 1200px * 0.02 = 24px (width 기준!) */
}
주의: padding
과 margin
의 %는 항상 부모의 width를 기준으로 합니다. 이는 수직/수평 여백의 일관성을 위한 설계입니다. 아래 box
가 container
안에 존재한다면 container
의 폭 1200px
의 10%
인 120px
이 됩니다.
.box {
width: 300px;
height: 200px;
padding: 10%; /* 120px (1200px의 10%, height와 무관!) */
}
녹색이 container, 핑크색이 box입니다.
개발자 도구로 실제 크기를 확인한 것입니다.
뷰포트 단위: vw, vh, vmin, vmax
뷰포트 단위는 브라우저 창 크기를 기준으로 합니다. 풀스크린 레이아웃이나 반응형 타이포그래피에 유용합니다.
/* 뷰포트 전체 활용 */
.hero {
width: 100vw; /* 뷰포트 너비의 100% */
height: 100vh; /* 뷰포트 높이의 100% */
}
/* 반응형 타이포그래피 */
.title {
font-size: 4vw; /* 화면이 커질수록 글자도 커짐 */
/* clamp()로 최소/최대 제한 */
font-size: clamp(1.5rem, 4vw, 3rem);
/* 최소 1.5rem, 기본 4vw, 최대 3rem */
}
/* 정사각형 만들기 */
.square {
width: 20vmin; /* 뷰포트의 짧은 쪽 기준 */
height: 20vmin; /* 항상 정사각형 유지 */
}
/* 뷰포트 방향에 따른 대응 */
.responsive-box {
width: 50vmax; /* 뷰포트의 긴 쪽의 50% */
height: 50vmin; /* 뷰포트의 짧은 쪽의 50% */
}
뷰포트 단위 활용 예시:
100vh
문제: 모바일에서 주소창 때문에 스크롤 발생- 해결책:
min-height: 100vh
또는 CSS 변수 활용
calc()로 단위 조합하기
calc()
는 다른 단위들을 수식으로 조합할 수 있게 해줍니다. 복잡한 레이아웃 계산을 CSS에서 직접 처리할 수 있습니다.
.header {
/* 100vh에서 푸터 높이만큼 빼기 */
height: calc(100vh - 80px);
/* 50%에서 고정 여백 빼기 */
width: calc(50% - 20px);
/* rem과 vw 조합 */
font-size: calc(1rem + 2vw);
}
.grid-item {
/* 3개 컬럼, 간격 고려 */
width: calc((100% - 40px) / 3); /* 전체에서 양옆 여백(40px) 빼고 3등분 */
}
/* 복잡한 계산 */
.complex-layout {
/* 가운데 정렬된 고정 너비 컨테이너 */
width: min(90%, 1200px);
margin-left: calc((100% - min(90%, 1200px)) / 2);
}
새로운 단위들: 논리적 속성
최근 CSS에서는 국제화를 고려한 논리적 단위들이 추가되었습니다. 가령 아랍어 같은 경우는 왼쪽이 아니라 오른쪽부터 쓰기 때문에 왼쪽, 오른쪽 대신 시작과 끝이라는 속성으로 일관되게 표현하기 위함입니다.
/* 물리적 속성 (left/right) */
.old-way {
margin-left: 1rem;
padding-right: 2rem;
}
/* 논리적 속성 (start/end) */
.new-way {
margin-inline-start: 1rem; /* LTR: left, RTL: right */
padding-inline-end: 2rem; /* LTR: right, RTL: left */
/* block은 세로 방향 */
margin-block-start: 1rem; /* 상단 */
margin-block-end: 1rem; /* 하단 */
}
/* 더 간단한 문법 */
.shorthand {
margin-inline: 1rem 2rem; /* start end */
margin-block: 1rem; /* start와 end 모두 */
}
실무에서의 단위 선택 가이드
타이포그래피 시스템
일관성 있는 타이포그래피를 위한 스케일 시스템을 구축합니다. 이런 시스템은 웹사이트의 전반적인 디자인 일관성을 유지하는 데 도움이 됩니다. tailwind 같은 CSS 프레임워크는 이런 시스템을 미리 제공하는 경우가 많습니다.
/* 기본 설정 */
html {
font-size: 16px; /* 기준점 설정 */
}
/* 스케일 시스템 (rem 기반) */
.text-xs { font-size: 0.75rem; } /* 12px */
.text-sm { font-size: 0.875rem; } /* 14px */
.text-base { font-size: 1rem; } /* 16px */
.text-lg { font-size: 1.125rem; } /* 18px */
.text-xl { font-size: 1.25rem; } /* 20px */
.text-2xl { font-size: 1.5rem; } /* 24px */
.text-3xl { font-size: 1.875rem; } /* 30px */
.text-4xl { font-size: 2.25rem; } /* 36px */
/* 반응형 타이포그래피 */
@media (max-width: 768px) {
html {
font-size: 14px; /* 모바일에서 기준 크기 조정 */
}
}
간격 시스템
간격도 일관성 있게 관리해야 디자인의 일관성을 유지할 수 있습니다.
/* 8px 기반 간격 시스템 */
.space-1 { margin: 0.25rem; } /* 4px */
.space-2 { margin: 0.5rem; } /* 8px */
.space-3 { margin: 0.75rem; } /* 12px */
.space-4 { margin: 1rem; } /* 16px */
.space-5 { margin: 1.25rem; } /* 20px */
.space-6 { margin: 1.5rem; } /* 24px */
.space-8 { margin: 2rem; } /* 32px */
.space-10 { margin: 2.5rem; } /* 40px */
.space-12 { margin: 3rem; } /* 48px */
.space-16 { margin: 4rem; } /* 64px */
/* 방향별 간격 유틸리티 */
.mt-4 { margin-top: 1rem; }
.mb-4 { margin-bottom: 1rem; }
.mx-4 { margin-left: 1rem; margin-right: 1rem; }
.my-4 { margin-top: 1rem; margin-bottom: 1rem; }
컨테이너와 레이아웃
반응형 컨테이너를 만들 때 단위 조합이 중요합니다.
.container {
max-width: 1200px; /* 최대 너비는 px로 고정 */
width: 90%; /* 기본 너비는 %로 반응형 */
margin: 0 auto; /* 가운데 정렬 */
padding: 0 1rem; /* 내부 여백은 rem */
}
/* 유동적인 그리드 */
.grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 2rem; /* 간격은 rem */
}
/* 고정 사이드바 + 유동 메인 */
.layout {
display: grid;
grid-template-columns: 250px 1fr; /* 사이드바 고정, 메인 유동 */
gap: 2rem;
}
@media (max-width: 768px) {
.layout {
grid-template-columns: 1fr; /* 모바일에서 단일 컬럼 */
}
}
반응형 디자인 패턴
/* 모바일 퍼스트 접근 */
.responsive-text {
font-size: 1rem; /* 기본: 모바일 */
}
@media (min-width: 768px) {
.responsive-text {
font-size: 1.125rem; /* 태블릿 */
}
}
@media (min-width: 1024px) {
.responsive-text {
font-size: 1.25rem; /* 데스크톱 */
}
}
/* 유동적 타이포그래피 */
.fluid-text {
/* 뷰포트에 따라 유동적으로 변하되, 최소/최대값 제한 */
font-size: clamp(1rem, 2.5vw, 2rem);
}
/* 컨테이너 쿼리 (최신 기능) */
.card-container {
container-type: inline-size;
}
@container (min-width: 400px) {
.card-container .card {
display: grid;
grid-template-columns: 150px 1fr;
}
}
성능 최적화 팁
선택자 성능
브라우저는 선택자를 오른쪽에서 왼쪽으로 평가합니다.
/* 나쁜 예: 모든 a 태그를 찾고, 그 중 .nav .list li 안에 있는 것 필터링 */
.nav .list li a { }
/* 좋은 예: .nav-link 클래스만 찾으면 됨 */
.nav-link { }
/* 매우 나쁜 예: 모든 태그 검사 */
.container * { }
/* 개선: 필요한 요소만 명시 */
.container > div { }
상속 활용
상속을 잘 활용하면 불필요한 선언을 줄일 수 있습니다.
/* 나쁜 예: 모든 요소에 개별 선언 */
.card h2 { font-family: 'Roboto', sans-serif; }
.card p { font-family: 'Roboto', sans-serif; }
.card span { font-family: 'Roboto', sans-serif; }
/* 좋은 예: 부모에 한 번만 선언 */
.card { font-family: 'Roboto', sans-serif; }
리플로우 최소화
지난 포스트에서 reflow와 repaint, composite 에 대해서 알아봤습니다. width, height 같은 속성은 지오메트리를 다시 계산하고 그 이후 단계를 모두 재수행하므로 성능에 악영향을 끼칩니다. 가능한 한 transform과 opacity를 사용하세요.
/* 나쁜 예: 리플로우 발생 */
.box:hover {
width: 200px;
height: 200px;
top: -10px;
}
/* 좋은 예: GPU 가속, 리플로우 없음 */
.box:hover {
transform: scale(1.1) translateY(-10px);
}
정리
이번 포스트는 상당히 길었습니다. 저도 이번에 작성하면서 마진과 패딩 값을 %
로 했을 때 무엇을 기준으로 하는지는 처음 알게 되었습니다. CSS를 직접 작성할 일은 많지 않고 가끔 디자인이 필요할 때만 잠깐 다루게되는데 그때마다 기억은 잘 나지않고… 그렇습니다. 다음 포스트는 박스 모델을 다루겠습니다.
선택자와 결합자:
- 기본 선택자부터 속성 선택자까지 다양한 타겟팅 방법
>
,+
,~
결합자로 정확한 요소 관계 표현- 가상 클래스와 가상 요소로 동적 스타일링
- 브라우저가 선택자를 오른쪽에서 왼쪽으로 평가한다는 성능 관점
상속과 우선순위:
- 텍스트 속성은 상속되고, 박스 모델은 상속되지 않음
- 특정성 계산법을 통한 우선순위 결정 (인라인 > ID > 클래스 > 태그)
- 캐스케이딩 규칙과
!important
의 절제된 사용
CSS 단위 시스템:
- px: 세밀한 디자인 요소 (보더, 그림자, 아이콘)
- rem: 타이포그래피와 간격 시스템 (일관성과 접근성)
- em: 컴포넌트 내부의 상대적 크기 (누적 주의)
- %: 부모 기준 반응형 레이아웃
- vw/vh: 뷰포트 기준 전체 화면 활용
- calc(): 단위 간 계산으로 복잡한 레이아웃 해결
참고자료:
- MDN - CSS Selectors
- MDN - Cascade, specificity, and inheritance
- MDN - CSS values and units
- CSS Tricks - Specifics on CSS Specificity
- Web.dev - CSS Performance
- Ahmad Shadeed - Modern CSS Units
Subscribe via RSS