이전 포스트에서 HTML이 웹 페이지의 '뼈대(구조)'를 만드는 역할을 한다고 정리했습니다. 이번에는 그 뼈대에 옷을 입히고 디자인하는, 즉 웹 페이지의 '스타일'을 담당하는 **CSS(Cascading Style Sheets)**에 대해 알아보겠습니다. 🎨
백엔드 개발자가 CSS 전문가일 필요는 없지만, 기본적인 CSS 원리를 이해하면 프론트엔드와의 협업이 원활해지고, 간단한 UI를 직접 수정하거나 구성할 수 있게 됩니다.
## 1. CSS의 기본 문법
CSS는 매우 간단하고 직관적인 구조를 가집니다. **"어떤(Selector) HTML 요소의, 어떤 속성(Property)을, 어떻게(Value) 바꿀 것인가?"**를 정의하는 규칙의 집합입니다.
- 선택자 (Selector): 스타일을 적용할 HTML 요소를 선택합니다. (예: h1, .title, #header)
- 선언 블록 (Declaration Block): { } 중괄호로 감싸진 부분으로, 하나 이상의 스타일 선언이 들어갑니다.
- 속성 (Property): 변경하고자 하는 스타일의 종류입니다. (예: color, font-size)
- 값 (Value): 속성에 적용할 구체적인 값입니다. (예: blue, 16px)
/* p 태그의 글자색을 파란색으로, 글자 크기는 16px로 지정 */
p {
color: blue;
font-size: 16px;
}
## 2. HTML에 CSS 적용하기
HTML 문서에 CSS를 적용하는 방법은 세 가지가 있으며, 외부 스타일 시트 방식이 가장 권장됩니다.
- 인라인 스타일 (Inline Style): HTML 태그에 style 속성을 직접 추가하는 방식입니다. 특정 요소 하나에만 스타일을 적용할 때 사용하지만, 유지보수가 어려워 권장되지 않습니다.
HTML
<p style="color: red;">이 글자만 빨간색입니다.</p> - 내부 스타일 시트 (Internal Style Sheet): HTML 문서의 <head> 태그 안에 <style> 태그를 만들어 CSS 코드를 작성하는 방식입니다. 해당 HTML 페이지에만 적용됩니다.
HTML<head> <style> p { color: blue; } </style> </head> - 외부 스타일 시트 (External Style Sheet): 별도의 .css 파일을 만들어 CSS 코드를 작성하고, HTML 문서의 <head> 태그에서 <link> 태그로 연결하는 방식입니다. 여러 페이지에 동일한 스타일을 적용할 수 있고, 코드의 분리로 유지보수가 용이하여 가장 널리 사용됩니다.
HTML<head> <link rel="stylesheet" href="styles.css"> </head>
## 3. 핵심 개념 1: 선택자 (Selectors)
선택자는 CSS가 HTML 요소를 찾아가는 가장 중요한 방법입니다.
- 타입 선택자 (Type Selector): HTML 태그 이름을 직접 사용합니다. (예: h1, p, div)
CSS
/* 모든 p 태그에 적용 */ p { margin: 10px; } - 클래스 선택자 (Class Selector): 가장 많이 사용되는 방식입니다. HTML 요소의 class 속성값을 사용하며, 이름 앞에 점(.)을 붙입니다. 하나의 클래스는 여러 요소에 중복해서 적용할 수 있습니다.
HTML
<p class="error">이용약관에 동의해주세요.</p>CSS/* class="error"를 가진 모든 요소에 적용 */ .error { color: red; } - ID 선택자 (ID Selector): HTML 요소의 id 속성값을 사용하며, 이름 앞에 해시(#)를 붙입니다. id는 한 페이지 내에서 오직 하나의 요소에만 유일하게 부여되어야 합니다.
HTML
<header id="header"> ... </header>CSS/* id="header"를 가진 요소에 적용 */ #header { background-color: #f2f2f2; }
## 4. 핵심 개념 2: 박스 모델 (Box Model)

CSS에서 **모든 HTML 요소는 사각형의 박스(Box)**로 간주됩니다. 이 박스는 네 가지 요소로 구성되며, 이 구조를 이해하는 것은 레이아웃을 다룰 때 매우 중요합니다.
- 콘텐츠 (Content): 텍스트나 이미지가 표시되는 실제 내용 영역입니다.
- 패딩 (Padding): 콘텐츠와 테두리 사이의 내부 여백입니다.
- 테두리 (Border): 패딩을 감싸는 선입니다.
- 마진 (Margin): 테두리 바깥의 외부 여백으로, 다른 요소와의 간격을 만들 때 사용됩니다.
div {
width: 200px; /* 콘텐츠 너비 */
padding: 20px; /* 내부 여백 */
border: 1px solid black;/* 테두리 */
margin: 30px; /* 외부 여백 */
}
CSS에서 크기를 정하는 단위는 크게 고정된 값과 상황에 따라 변하는 값으로 나뉩니다.
| 단위 | 기준 | 간단한 설명 | 주요 사용처 |
| px | 절대 크기 | 고정된 값. 모니터의 작은 점(픽셀) 하나. | 이미지 크기, 테두리처럼 변하면 안 되는 곳 |
| % | 부모 요소 | 부모 크기의 몇 퍼센트인지. | 레이아웃 너비 잡을 때 |
| em | 부모 글자 크기 | 부모 글자 크기의 몇 배인지. | 특정 컴포넌트 내부에서만 크기 조절할 때 |
| rem | 최상위 글자 크기 | 사이트 전체 기준 글자 크기의 몇 배인지. | 사이트 전체 글꼴, 여백의 일관성 유지 |
| vw, vh | 브라우저 화면 | 화면 너비/높이를 100조각으로 나눈 값. | 화면을 꽉 채우는 배너 등을 만들 때 |
## 5. 자주 사용되는 기본 속성들
- 색상: color (글자색), background-color (배경색)
- 글꼴: font-size (크기), font-weight (굵기), font-family (서체)
- 텍스트: text-align (정렬), line-height (줄 간격)
- 크기와 여백: width (너비), height (높이), padding, margin, border
- 디스플레이: display (요소를 어떻게 보여줄지 결정. block, inline, flex, grid 등)
## 심화 CSS 선택자: 관계와 상태를 이용한 스타일링
기본 선택자만으로는 복잡한 구조의 HTML 문서를 스타일링하기 어렵습니다. CSS는 요소 간의 관계나 특정 상태를 이용하여 더욱 정밀하게 요소를 선택할 수 있는 강력한 결합자(Combinator)와 가상 클래스(Pseudo-class)를 제공합니다. 🧩
## 1. 자식 결합자 (Child Combinator): >
A > B 형태로 사용하며, A 요소의 직계 자식인 B 요소만을 선택합니다. 자손(descendant)은 포함하지 않고, 바로 아래 단계의 자식만 해당됩니다.
/* id가 'parent'인 요소의 직계 자식인 p 태그만 선택 */
#parent > p {
color: blue;
}
<div id="parent">
<p>이 텍스트는 파란색입니다.</p> <div>
<p>이 텍스트는 파란색이 아닙니다.</p> </div>
</div>
## 2. 인접 형제 결합자 (Adjacent Sibling Combinator): +
A + B 형태로 사용하며, A 요소 바로 다음에 오는 형제 B 요소 하나만을 선택합니다.
/* h1 태그 바로 다음에 오는 p 태그 하나만 선택 */
h1 + p {
font-weight: bold;
}
<h1>제목입니다</h1>
<p>이 텍스트는 굵게 표시됩니다.</p> <p>이 텍스트는 일반 텍스트입니다.</p>
## 3. 일반 형제 결합자 (General Sibling Combinator): ~
A ~ B 형태로 사용하며, A 요소 다음에 오는 모든 형제 B 요소를 선택합니다.
/* h1 태그 다음에 오는 모든 p 태그를 선택 */
h1 ~ p {
border-left: 3px solid #ccc;
padding-left: 10px;
}
<h1>제목입니다</h1>
<div>div 태그입니다</div>
<p>이 p 태그는 선택됩니다.</p>
<p>이 p 태그도 선택됩니다.</p>
div는 적용되진 않습니다.
## 4. 속성 선택자 (Attribute Selector): []
HTML 요소가 가진 특정 속성이나 속성값을 조건으로 요소를 선택합니다. 매우 강력하고 실용적입니다.
/* a 태그 중 target 속성을 가진 요소만 선택 */
a[target] {
background-color: yellow;
}
/* a 태그 중 target 속성값이 "_blank"인 요소만 선택 */
a[target="_blank"] {
font-style: italic;
}
/* input 태그 중 type 속성값이 "text"인 요소만 선택 */
input[type="text"] {
border: 1px solid #ddd;
}
## 5. 가상 클래스 선택자 (Pseudo-class Selector): :
요소의 **특정한 상태(state)**나 위치를 기반으로 요소를 선택합니다. 이름 앞에 콜론(:)을 붙입니다.
/* a 태그에 마우스를 올렸을 때 (hover 상태) */
a:hover {
text-decoration: underline;
}
/* input 요소가 포커스되었을 때 */
input:focus {
outline: 2px solid blue;
}
/* li 요소 중 부모의 첫 번째 자식일 때 */
li:first-child {
color: red;
}
/* li 요소 중 짝수 번째 자식일 때 (구조적 가상 클래스) */
li:nth-child(even) {
background-color: #f2f2f2;
}
## Cascading
브라우저는 충돌하는 스타일 규칙이 있을 때, 다음 3가지 기준을 우선순위 순서대로 적용하여 어떤 스타일을 적용할지 결정합니다: 1. 중요도 → 2. 명시도 → 3. 코드 순서.
## 🥇 1. 중요도 (Importance)
!important 키워드가 붙은 스타일이 모든 것을 이깁니다.
가장 높은 우선순위를 가지는 규칙입니다. 어떤 선택자를 사용했는지, 어디에 작성되었는지와 상관없이 !important가 붙은 스타일은 다른 모든 스타일을 덮어씁니다.
p {
color: blue !important; /* 이 규칙이 무조건 적용됩니다. */
}
#intro {
color: red; /* !important가 없어서 무시됩니다. */
}
주의: !important는 CSS의 자연스러운 상속 구조를 깨뜨려 유지보수를 매우 어렵게 만드므로, 디버깅 등 꼭 필요한 상황을 제외하고는 가급적 사용을 피해야 합니다.
## 🥈 2. 명시도 (Specificity)
더 구체적으로 작성된 선택자가 이깁니다.
!important가 없다면, 브라우저는 각 선택자가 얼마나 구체적인지를 계산하여 점수가 높은 쪽의 스타일을 적용합니다. 점수는 다음과 같은 계층 구조를 가집니다.
- 인라인 스타일: style="color: red;" (1000점)
- ID 선택자: #header (100점)
- 클래스(.class), 속성([type]), 가상 클래스(:hover) 선택자: (10점)
- 타입(태그) 선택자: p, div (1점)
예시: #main p.text (ID 1개 + 클래스 1개 + 타입 1개 = 111점)는 div .text (클래스 1개 + 타입 1개 = 11점)보다 점수가 높으므로, #main p.text의 스타일이 적용됩니다.
## 🥉 3. 코드 순서 (Source Order)
가장 나중에 작성된 코드가 이깁니다.
만약 위 두 규칙(중요도, 명시도)으로도 우열을 가릴 수 없다면(점수가 같다면), CSS 파일에서 가장 마지막에 등장하는 규칙이 최종적으로 적용됩니다.
/* style.css */
p {
color: blue; /* 이 규칙은 아래 규칙에 의해 덮어쓰여집니다. */
}
p {
color: red; /* 명시도 점수가 같으므로, 나중에 나온 이 규칙이 적용됩니다. */
}
## Display
모든 HTML 요소는 기본적으로 블록 또는 인라인 중 하나의 display 값을 가집니다.
## 1. 블록 (Block) 요소 🧱
블록 요소는 "벽돌"처럼 쌓이는 요소라고 생각하면 쉽습니다.
- 특징:
- 항상 새로운 줄에서 시작하며, 양옆에 다른 요소를 배치하지 않습니다.
- 콘텐츠의 양과 상관없이, 부모 요소의 너비(width)를 100% 차지합니다.
- width, height, margin, padding 속성을 모두 사용하여 크기와 여백을 자유롭게 지정할 수 있습니다.
- 대표적인 태그:
- <div>, <p>, <h1>~<h6>, <ul>, <li>, <form>, <header>, <footer> 등
## 2. 인라인 (Inline) 요소 ↔️
인라인 요소는 "문장 안의 글자"처럼 흐름에 맞춰 배치되는 요소입니다.
- 특징:
- 새로운 줄에서 시작하지 않고, 다른 인라인 요소들과 같은 줄에 나란히 배치됩니다.
- 자신이 가진 콘텐츠의 크기만큼만 너비를 차지합니다.
- width와 height 속성이 적용되지 않습니다.
- margin과 padding은 좌우 여백만 정상적으로 적용되며, 상하 여백은 의도대로 동작하지 않을 수 있습니다.
- 대표적인 태그:
- <span>, <a>, <img>, <strong>, <em>, <input>, <label> 등
## 3. display 속성: 동작을 바꾸는 스위치
display 속성은 요소의 기본 동작(블록 또는 인라인)을 원하는 대로 변경할 수 있는 강력한 기능입니다.
- display: block;
- 인라인 요소를 블록 요소처럼 동작하게 만듭니다. (예: <a> 태그를 한 줄 전체 너비를 차지하는 버튼으로 만들 때)
- display: inline;
- 블록 요소를 인라인 요소처럼 동작하게 만듭니다.
- display: inline-block;
- 블록과 인라인의 특징을 모두 가진 매우 유용한 값입니다.
- 인라인 요소처럼 다른 요소와 같은 줄에 배치되면서도, 블록 요소처럼 width, height, margin, padding을 모두 정상적으로 사용할 수 있습니다. (예: 내비게이션 메뉴의 각 버튼)
- display: none;
- 요소를 화면에서 완전히 사라지게 만듭니다. 단순히 보이지만 않는 것(visibility: hidden;)을 넘어, 레이아웃 상에서 아예 공간조차 차지하지 않게 됩니다.
## 추가 정보: 현대적인 레이아웃
과거에는 위 속성들로 레이아웃을 만들었지만, 현대 CSS에서는 복잡하고 유연한 레이아웃을 만들기 위해 다음과 같은 display 값을 주로 사용합니다.
- display: flex; (Flexbox): 한 방향(가로 또는 세로)의 레이아웃을 손쉽게 구성합니다.
- display: grid; (Grid): 2차원(행과 열)의 격자 레이아웃을 정교하게 구성합니다.
사진 출처:
https://engkimbs.tistory.com/entry/HTMLCSS-%EB%B0%95%EC%8A%A4%EB%AA%A8%EB%8D%B8-Box-Model
'개발 공부 > 프론트 엔드' 카테고리의 다른 글
| JavaScript 정리 (0) | 2025.09.11 |
|---|---|
| UTF-8 (0) | 2025.09.05 |
| HTML 핵심 정리 (0) | 2025.09.04 |