CSS 기초 | 선택자, 속성, 색상, 폰트
이 글의 핵심
같은 요소에 여러 선언이 겹칠 때, 브라우저는 캐스케이드 규칙으로 ‘한 값’을 고릅니다. 특이도·상속·레이어를 알아야 예측이 됩니다.
시리즈 안내
#03 | 📋 전체 목차 | 이전: #02 HTML 기본
들어가며
CSS는 HTML이 만든 요소에 색·크기·배치 규칙을 입힙니다. 박스 모델과 Flexbox는 같은 “상자” 관점에서 읽으면 연결됩니다.
심화: 캐스케이드, 특이도(Specificity), 상속
아래에서 다루는 선택자 예제들이 같은 속성에 서로 다른 값을 주면, 브라우저는 캐스케이드(Cascade) 알고리즘으로 하나를 고릅니다. “ID가 클래스보다 강하다”는 말만으로는 부족하며, 출처(origin)·중요도(importance)·레이어(@layer)·특이도·선언 순서를 함께 봐야 합니다.
캐스케이드가 비교하는 단계(요약)
일반적으로 한 선언이 다른 선언을 이기려면, 아래 순서로 먼저 다른 쪽을 이겨야 합니다(같은 단계 안에서는 다음 단계로).
-
출처와 중요도
사용자!important→ 작성자!important→ 작성자 일반 → 사용자 일반 → UA(브라우저 기본) 스타일시트.
(실제 엔진은 명세의 cascade sort에 따라 더 세밀합니다.) -
레이어(
@layer)
레이어가 없는 일반 선언은 레이어 안 선언보다 우선할 수 있습니다(명세의 레이어 순서 규칙). 디자인 시스템에서 베이스/컴포넌트/유틸을 레이어로 나누면!important없이도 순서를 제어하기 쉽습니다. -
선택자 특이도(Specificity)
동일 출처·중요도·레이어라면 특이도가 큰 선언이 이깁니다. -
선언 순서
그래도 동률이면 문서에서 뒤에 온 선언이 이깁니다(같은 스타일시트 내import순서와 링크 순서도 여기에 포함).
특이도 계산: 단순 “ID > 클래스”를 넘어서
CSS2 시절의 직관(ID=100, class=10, 요소=1)은 여전히 직관용으로 쓰이지만, 최신 선택자는 4개의 카운터로 이해하는 편이 정확합니다(Selectors Level 4 기준 개념).
- 인라인 스타일(
style="...")은 선택자 특이도보다 위에 올라갑니다(별도로 처리). :where()는 인자 선택자의 특이도를 0으로 만듭니다. 반면:is(),:not(),:has()는 인자 안의 가장 특이도 높은 선택자를 반영합니다.- 가상 요소(
::before,::after)는 타입 선택자와 동급으로 1을 더합니다. :nth-child()등 구조 의사 클래스는 특이도에 포함됩니다.
복합 선택자 .a.b#c는 각 구성 요소의 특이도가 합산됩니다. 따라서 “클래스 하나만 더 추가했다”가 ID가 아닌 이상 ID 규칙을 이기지 못하는 이유가 수치로 설명됩니다.
실무에서 자주 쓰는 팁은 다음과 같습니다.
- 특이도 전쟁을 피하려면 클래스·데이터 속성 하나로 범위를 잡으며, 불가피할 때만
@layer로 정리합니다. !important는 디버깅을 어렵게 만들고 레이어·순서 문제를 가립니다. 정말 필요한 경우(예: 유틸리티 오버라이드)만 제한적으로 씁니다.
상속(Inheritance)과 초기값
모든 CSS 속성은 상속 여부가 정해져 있습니다.
- 상속되는 속성:
color,font-*,line-height등 — 자식은 부모의 계산값(computed value)을 상속받습니다(단,rem처럼 루트 기준인 값은 부모와 무관). - 상속되지 않는 속성:
margin,padding,border,width등 — 초기값(initial value)에서 시작합니다. 브라우저 기본 스타일(UA)이 일부 요소에margin등을 넣는 이유가 여기에 있습니다.
전역 리셋(* { margin: 0 })은 상속이 아니라 모든 요소에 직접 적용되는 것입니다.
inherit, initial, unset, revert
inherit: 부모의 계산값을 강제로 물려받습니다(상속 여부와 무관).initial: 해당 속성의 표준 초기값으로 맞춥니다.unset: 속성이 상속되면inherit, 아니면initial과 같이 동작합니다.revert: 캐스케이드를 한 단계 되실행하여 UA/작성자 스타일 중 이전 층으로 돌아갑니다(레이어·출처 맥락이 있으므로 “완전 초기화”와는 다릅니다).
이 단계까지 이해하면, “같은 선택자인데 왜 이 속성만 이상한가?” 같은 문제가 상속·초기값·더 구체적인 규칙 중 어디에 속하는지로 분해됩니다. 레이아웃과 겹침은 박스 모델과 position·쌓임 맥락과 연결됩니다.
1. CSS 선택자
기본 선택자
CSS 선택자는 스타일을 적용할 HTML 요소를 선택합니다:
/* 1. 태그 선택자 (Type Selector) */
p {
/* 모든 <p> 태그에 적용 */
color: blue;
}
h1 {
/* 모든 <h1> 태그에 적용 */
font-size: 32px;
}
/* 2. 클래스 선택자 (Class Selector) */
.highlight {
/* class="highlight"를 가진 모든 요소에 적용 */
/* 여러 요소에 재사용 가능 */
background-color: yellow;
}
.button {
/* class="button"을 가진 요소 */
padding: 10px 20px;
border-radius: 5px;
}
/* HTML 예시:
<p class="highlight">강조된 텍스트</p>
<div class="highlight">강조된 영역</div>
*/
/* 3. ID 선택자 (ID Selector) */
#header {
/* id="header"를 가진 요소에 적용 */
/* 페이지에서 유일해야 함 (한 번만 사용) */
font-size: 24px;
}
#main-content {
/* id="main-content"인 요소 */
max-width: 1200px;
}
/* HTML 예시:
<div id="header">헤더</div>
*/
/* 4. 전체 선택자 (Universal Selector) */
* {
/* 모든 요소에 적용 */
/* CSS 리셋에 자주 사용 */
margin: 0; /* 모든 요소의 외부 여백 제거 */
padding: 0; /* 모든 요소의 내부 여백 제거 */
box-sizing: border-box; /* 박스 크기 계산 방식 통일 */
}
선택자 우선순위 (직관용 숫자): 아래 숫자는 교육용 비유이며, 실제 엔진은 위 「심화: 캐스케이드, 특이도, 상속」에서 설명한 대로 출처·레이어·:where() 등을 함께 봅니다.
/* (비유) ID > 클래스 > 태그 — 복합 선택자는 각 부분이 합산됨 */
p { color: black; } /* 타입 1개 */
.text { color: blue; } /* 클래스 1개 */
#title { color: red; } /* ID 1개 */
/* <p id="title" class="text">텍스트</p> → 보통 #title 이김 */
/* !important는 같은 조건에서 특이도보다 앞선 “중요도” 축에서 판정됨 */
p { color: green !important; }
선택자 조합:
/* 여러 클래스 동시 적용 */
.button.primary {
/* class="button primary"를 가진 요소 */
background: blue;
}
/* 여러 선택자에 같은 스타일 */
h1, h2, h3 {
/* h1, h2, h3 모두에 적용 */
font-family: Arial;
}
복합 선택자
/* 자손 선택자 (모든 하위) */
div p {
color: red;
}
/* 자식 선택자 (직접 하위만) */
div > p {
color: blue;
}
/* 인접 형제 선택자 */
h1 + p {
font-weight: bold;
}
/* 일반 형제 선택자 */
h1 ~ p {
color: gray;
}
속성 선택자
/* 속성 존재 */
[type] {
border: 1px solid;
}
/* 속성 값 일치 */
[type="text"] {
background: white;
}
/* 속성 값 포함 */
[class*="btn"] {
padding: 10px;
}
/* 속성 값 시작 */
[href^="https"] {
color: green;
}
/* 속성 값 끝 */
[href$=".pdf"] {
color: red;
}
가상 클래스
가상 클래스는 요소의 특정 상태를 선택합니다:
/* 1. 링크 상태 (LVHA 순서 권장) */
a:link {
/* 방문하지 않은 링크 */
color: blue;
}
a:visited {
/* 방문한 링크 */
color: purple;
}
a:hover {
/* 마우스를 올렸을 때 */
color: red;
text-decoration: underline;
}
a:active {
/* 클릭하는 순간 */
color: orange;
}
/* 2. 구조 가상 클래스 */
li:first-child {
/* 첫 번째 자식 요소 */
font-weight: bold;
}
li:last-child {
/* 마지막 자식 요소 */
font-style: italic;
}
li:nth-child(2) {
/* 두 번째 자식 요소 */
color: red;
}
li:nth-child(odd) {
/* 홀수 번째 자식 (1, 3, 5, ...) */
background: #f0f0f0;
}
li:nth-child(even) {
/* 짝수 번째 자식 (2, 4, 6, ...) */
background: white;
}
/* nth-child 고급 사용 */
li:nth-child(3n) {
/* 3의 배수 (3, 6, 9, ...) */
color: blue;
}
li:nth-child(3n+1) {
/* 3으로 나눈 나머지가 1 (1, 4, 7, ...) */
color: green;
}
/* 3. 상태 가상 클래스 */
input:focus {
/* 포커스를 받았을 때 (클릭 또는 Tab 키) */
border-color: blue;
outline: 2px solid blue;
}
input:disabled {
/* 비활성화된 입력 필드 */
opacity: 0.5;
cursor: not-allowed;
}
input:checked + label {
/* 체크된 input의 바로 다음 label */
/* + : 인접 형제 선택자 */
color: green;
font-weight: bold;
}
/* HTML 예시:
<input type="checkbox" id="agree">
<label for="agree">동의합니다</label>
*/
/* 4. 기타 유용한 가상 클래스 */
button:hover {
/* 마우스 오버 시 */
background: #0056b3;
cursor: pointer;
}
input:valid {
/* 유효한 입력 */
border-color: green;
}
input:invalid {
/* 유효하지 않은 입력 */
border-color: red;
}
div:empty {
/* 내용이 비어있는 요소 */
display: none;
}
:not(.active) {
/* active 클래스가 없는 요소 */
opacity: 0.5;
}
가상 클래스 실전 예시:
/* 테이블 줄무늬 */
tr:nth-child(odd) {
background: #f9f9f9;
}
/* 첫 단락만 크게 */
article p:first-child {
font-size: 1.2em;
}
/* 마지막 아이템 구분선 제거 */
li:last-child {
border-bottom: none;
}
가상 요소
/* 첫 글자 */
p::first-letter {
font-size: 2em;
font-weight: bold;
}
/* 첫 줄 */
p::first-line {
color: blue;
}
/* 앞에 내용 추가 */
.note::before {
content: "📌 ";
}
/* 뒤에 내용 추가 */
.external-link::after {
content: " 🔗";
}
2. 색상
색상 표현 방법
/* 색상 이름 */
color: red;
color: blue;
color: green;
/* HEX 코드 */
color: #FF0000; /* 빨강 */
color: #00FF00; /* 초록 */
color: #0000FF; /* 파랑 */
color: #FFF; /* 축약형 */
/* RGB */
color: rgb(255, 0, 0);
color: rgb(0, 255, 0);
color: rgb(0, 0, 255);
/* RGBA (투명도) */
color: rgba(255, 0, 0, 0.5); /* 50% 투명 */
background: rgba(0, 0, 0, 0.8);
/* HSL */
color: hsl(0, 100%, 50%); /* 빨강 */
color: hsl(120, 100%, 50%); /* 초록 */
color: hsl(240, 100%, 50%); /* 파랑 */
/* HSLA (투명도) */
color: hsla(0, 100%, 50%, 0.5);
색상 활용
.box {
/* 글자 색 */
color: #333;
/* 배경색 */
background-color: #f5f5f5;
/* 테두리 색 */
border-color: #ddd;
/* 그라데이션 */
background: linear-gradient(to right, #667eea, #764ba2);
background: radial-gradient(circle, #667eea, #764ba2);
}
3. 폰트
폰트 기본
.text {
/* 폰트 종류 */
font-family: Arial, sans-serif;
font-family: 'Malgun Gothic', '맑은 고딕', sans-serif;
/* 폰트 크기 */
font-size: 16px;
font-size: 1.5em;
font-size: 1.5rem;
/* 폰트 굵기 */
font-weight: normal; /* 400 */
font-weight: bold; /* 700 */
font-weight: 600;
/* 폰트 스타일 */
font-style: normal;
font-style: italic;
/* 줄 높이 */
line-height: 1.6;
line-height: 24px;
}
웹 폰트
/* Google Fonts */
@import url('https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@400;700&display=swap');
body {
font-family: 'Noto Sans KR', sans-serif;
}
/* 로컬 폰트 */
@font-face {
font-family: 'MyFont';
src: url('fonts/myfont.woff2') format('woff2'),
url('fonts/myfont.woff') format('woff');
font-weight: normal;
font-style: normal;
}
.custom {
font-family: 'MyFont', sans-serif;
}
4. 텍스트 스타일
텍스트 정렬
.text {
/* 수평 정렬 */
text-align: left;
text-align: center;
text-align: right;
text-align: justify;
/* 수직 정렬 (인라인 요소) */
vertical-align: top;
vertical-align: middle;
vertical-align: bottom;
}
텍스트 장식
.text {
/* 밑줄 */
text-decoration: underline;
text-decoration: none;
text-decoration: line-through;
/* 대소문자 변환 */
text-transform: uppercase; /* 대문자 */
text-transform: lowercase; /* 소문자 */
text-transform: capitalize; /* 첫 글자만 대문자 */
/* 들여쓰기 */
text-indent: 20px;
/* 자간 */
letter-spacing: 2px;
/* 단어 간격 */
word-spacing: 5px;
/* 그림자 */
text-shadow: 2px 2px 4px rgba(0,0,0,0.5);
}
텍스트 오버플로우
.text {
/* 한 줄 말줄임 */
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
/* 여러 줄 말줄임 (Webkit) */
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
overflow: hidden;
}
5. 단위
절대 단위
// 실행 예제
.element {
width: 100px; /* 픽셀 */
width: 2.54cm; /* 센티미터 */
width: 25.4mm; /* 밀리미터 */
width: 72pt; /* 포인트 */
}
상대 단위
.element {
/* em: 부모 요소 기준 */
font-size: 1.5em;
/* rem: 루트 요소 기준 */
font-size: 1.5rem;
/* %: 부모 요소 기준 */
width: 50%;
/* vw/vh: 뷰포트 기준 */
width: 50vw; /* 뷰포트 너비의 50% */
height: 100vh; /* 뷰포트 높이의 100% */
/* vmin/vmax */
width: 50vmin; /* 뷰포트 작은 쪽 기준 */
width: 50vmax; /* 뷰포트 큰 쪽 기준 */
}
6. CSS 변수
변수 정의와 사용
:root {
/* 변수 정의 */
--primary-color: #3498db;
--secondary-color: #2ecc71;
--font-size-base: 16px;
--spacing-unit: 8px;
}
.button {
/* 변수 사용 */
background-color: var(--primary-color);
font-size: var(--font-size-base);
padding: calc(var(--spacing-unit) * 2);
}
.button:hover {
background-color: var(--secondary-color);
}
/* 기본값 지정 */
.element {
color: var(--text-color, #333);
}
7. 실전 예제
예제: 버튼 스타일
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>버튼 스타일</title>
<style>
:root {
--primary: #3498db;
--success: #2ecc71;
--danger: #e74c3c;
--warning: #f39c12;
}
.btn {
display: inline-block;
padding: 12px 24px;
font-size: 16px;
font-weight: 600;
text-decoration: none;
border: none;
border-radius: 5px;
cursor: pointer;
transition: all 0.3s;
}
.btn-primary {
background-color: var(--primary);
color: white;
}
.btn-primary:hover {
background-color: #2980b9;
transform: translateY(-2px);
box-shadow: 0 4px 8px rgba(0,0,0,0.2);
}
.btn-success {
background-color: var(--success);
color: white;
}
.btn-danger {
background-color: var(--danger);
color: white;
}
.btn-outline {
background-color: transparent;
color: var(--primary);
border: 2px solid var(--primary);
}
.btn-outline:hover {
background-color: var(--primary);
color: white;
}
</style>
</head>
<body>
<button class="btn btn-primary">Primary</button>
<button class="btn btn-success">Success</button>
<button class="btn btn-danger">Danger</button>
<button class="btn btn-outline">Outline</button>
</body>
</html>
정리
핵심 요약
- 선택자: 태그, 클래스, ID, 가상 클래스
- 색상: HEX, RGB, RGBA, HSL
- 폰트: font-family, font-size, font-weight
- 텍스트: text-align, text-decoration
- 단위: px, em, rem, %, vw, vh
- 변수: —변수명, var(—변수명)
다음 단계
관련 글
- HTML/CSS 시작하기 | 웹 개발 첫걸음
- CSS 박스 모델 | Margin, Padding, Border 완벽 정리
- CSS Flexbox | 플렉스박스 레이아웃 완벽 가이드
- CSS Grid | 그리드 레이아웃 완벽 가이드
- 반응형 웹 디자인 | 미디어 쿼리와 모바일 최적화
자주 묻는 질문 (FAQ)
Q. 이 내용을 실무에서 언제 쓰나요?
A. 선택자·캐스케이드·특이도 계산·상속까지. 출처·중요도·레이어·상속/초기값을 포함해 스타일이 최종적으로 어떻게 확정되는지 고급 관점에서 정리합니다. 실무에서는 위 본문의 예제와 선택 가이드를 참고해 적용하면 됩니다.
Q. 선행으로 읽으면 좋은 글은?
A. 각 글 하단의 이전 글 또는 관련 글 링크를 따라가면 순서대로 배울 수 있습니다. C++ 시리즈 목차에서 전체 흐름을 확인할 수 있습니다.
Q. 더 깊이 공부하려면?
A. cppreference와 해당 라이브러리 공식 문서를 참고하세요. 글 말미의 참고 자료 링크도 활용하면 좋습니다.
같이 보면 좋은 글 (내부 링크)
이 주제와 연결되는 다른 글입니다.
- [2026] CSS 완전 정복 — 특이성·캐스케이드·박스모델·스택킹·실무 패턴
- HTML/CSS 시작하기 | 웹 개발 첫걸음
- CSS 박스 모델 | Margin, Padding, Border 완벽 정리
이 글에서 다루는 키워드 (관련 검색어)
CSS, 스타일, 선택자, 디자인, 캐스케이드 등으로 검색하시면 이 글이 도움이 됩니다.