선택자
기본 선택자
CSS 선택자는 스타일링을 위해 HTML 요소를 대상으로 합니다. 타입 선택자는 요소 이름을 매칭합니다(p, div). 클래스 선택자(.)는 class 속성을 매칭하고 재사용할 수 있습니다. ID 선택자(#)는 단일 요소를 매칭하고 고유해야 합니다. 범용 선택자(*)는 모든 것을 매칭합니다. 쉼표로 선택자를 그룹화하여 스타일을 공유하세요.
/* Type selector - all <p> elements */
p { color: #333; }
/* Class selector - elements with class="btn" */
.btn { padding: 8px 16px; }
/* ID selector - element with id="header" */
#header { background: #fff; }
/* Universal selector - all elements */
* { box-sizing: border-box; }
/* Grouping selector */
h1, h2, h3 { font-family: Arial, sans-serif; }결합자
결합자는 요소 간의 관계를 정의합니다. 자손(공백)은 중첩된 모든 요소를 매칭합니다. 자식(>)은 직계 자식만 매칭합니다. 인접 형제(+)는 바로 다음 요소를 매칭합니다. 일반 형제(~)는 이후의 모든 형제를 매칭합니다. 추가 클래스 없이 정밀한 스타일링을 위해 결합자를 이해하는 것이 필수적입니다.
/* Descendant - any <a> inside .nav */
.nav a { text-decoration: none; }
/* Child - direct <li> children of <ul> */
ul > li { list-style: none; }
/* Adjacent sibling - <p> right after <h1> */
h1 + p { font-size: 1.2em; }
/* General sibling - all <p> after <h1> */
h1 ~ p { color: gray; }속성 선택자
속성 선택자는 속성 값을 기반으로 요소를 매칭합니다. [attr]은 존재를 매칭합니다. [attr=val]은 정확한 값을 매칭합니다. ^=는 접두사, $=는 접미사, *=는 부분 문자열을 매칭합니다. 이는 추가 클래스 없이 폼 입력, 유형별 링크, 또는 data 속성이 있는 요소를 스타일링하는 데 강력합니다.
/* Elements with type attribute */
[type] { border: 1px solid #ccc; }
/* Exact match */
[type="text"] { padding: 4px; }
/* Starts with */
a[href^="https"] { color: green; }
/* Ends with */
a[href$=".pdf"] { color: red; }
/* Contains */
a[href*="example"] { font-weight: bold; }의사 클래스
의사 클래스는 상태나 위치를 기반으로 요소를 선택합니다. 대화형: :hover, :focus, :active, :visited, :disabled. 구조적: :first-child, :last-child, :nth-child(n), :nth-of-type(n). :not()은 선택자를 부정합니다. :nth-child(odd/even)는 얼룩무늬 줄을 만듭니다. :nth-child(3n)은 3번째마다 선택합니다. 이는 추가 클래스의 필요성을 줄입니다.
/* Interactive states */
a:hover { color: red; }
a:visited { color: purple; }
input:focus { border-color: blue; }
input:disabled { background: #eee; }
button:active { transform: scale(0.98); }
/* Structural */
li:first-child { font-weight: bold; }
li:last-child { border: none; }
li:nth-child(odd) { background: #f9f9f9; }
li:nth-child(3n) { color: blue; }
p:not(.highlight) { color: #333; }의사 요소
의사 요소(::콜론 두 개)는 요소의 특정 부분을 스타일링합니다. ::before와 ::after는 생성된 콘텐츠를 삽입합니다(content 속성 필요). ::first-letter와 ::first-line은 텍스트 부분을 스타일링합니다. ::selection은 강조된 텍스트를 스타일링합니다. ::placeholder는 입력 플레이스홀더를 스타일링합니다. 참고: ::before/::after는 기본적으로 인라인입니다 - 블록 동작을 위해 display:block을 설정하세요.
/* First line of a paragraph */
p::first-line { font-weight: bold; }
/* First letter (drop cap) */
p::first-letter { font-size: 3em; float: left; }
/* Insert content before/after */
.quote::before { content: "\201C"; }
.quote::after { content: "\201D"; }
/* Selection styling */
::selection { background: yellow; color: black; }
/* Placeholder styling */
input::placeholder { color: #999; }특이성 & !important
특이성은 선택자가 충돌할 때 어떤 규칙이 적용되는지 결정합니다. 인라인 스타일 > ID > 클래스 > 타입. 특이성이 동점일 때, 마지막 규칙이 이깁니다. !important는 모든 것을 재정의하지만 캐스케이드를 깨뜨립니다 - 피하세요. DevTools로 특이성을 검사하세요. 유지보수성을 위해 클래스 기반 선택자를 선호하세요. 클래스 반복(.btn.btn)으로 특이성을 높이는 것은 해킹입니다 - 피하세요.
/* Specificity hierarchy (low to high):
1. Type selectors (p, div) = 0,0,0,1
2. Class selectors (.btn) = 0,0,1,0
3. ID selectors (#header) = 0,1,0,0
4. Inline styles (style="...") = 1,0,0,0
5. !important = overrides all
*/
/* ID beats class */
#nav .link { color: red; } /* wins */
.nav .link { color: blue; }
/* Avoid !important unless necessary */
.critical { color: red !important; }박스 모델
Margin & Padding
모든 요소는 content, padding, border, margin을 가진 박스입니다. padding은 border 내부에 있고( 배경에 영향), margin은 외부에 있습니다(투명). 축약: 1값 = 모든 면, 2값 = 상/하 좌/우, 3 = 상 좌/우 하, 4 = 상 우 하 좌(시계 방향). margin: 0 auto는 정의된 너비로 블록 요소를 가운데 정렬합니다.
.box {
/* TRBL: top right bottom left */
margin: 10px 20px 10px 20px;
/* Shorthand: top/bottom left/right */
margin: 10px 20px;
/* All sides */
padding: 15px;
/* Individual sides */
margin-top: 0;
padding-left: 24px;
/* Center horizontally (block) */
margin: 0 auto;
}Border & Outline
border는 padding 주위에 선을 추가하여 레이아웃에 영향을 줍니다. outline은 레이아웃에 영향을 주지 않고 border 외부에 그립니다 - 포커스 표시기에 유용합니다. border-radius는 모서리를 둥글게 합니다(단일 값 또는 모서리별: 좌상 우상 우하 좌하). outline-offset은 border와 outline 사이에 공간을 추가합니다. 접근성을 위해 항상 보이는 포커스 스타일을 제공하세요.
.box {
/* Shorthand: width style color */
border: 2px solid #333;
/* Individual sides */
border-bottom: 3px dashed red;
border-radius: 8px;
/* Outline (doesn't affect layout) */
outline: 2px solid blue;
outline-offset: 4px;
}
/* Remove default focus, add custom */
button:focus {
outline: none;
box-shadow: 0 0 0 3px rgba(0,123,255,0.5);
}Box Sizing
box-sizing: content-box(기본값)는 width/height가 content에만 적용됨을 의미합니다 - padding과 border가 전체 크기에 추가됩니다. box-sizing: border-box는 padding과 border를 width/height에 포함시켜 크기를 예측 가능하게 합니다. 일관된 레이아웃을 위해 항상 전역에 border-box를 설정하세요. 이는 가장 중요한 CSS reset 중 하나입니다.
/* Default: width = content only */
.content-box {
box-sizing: content-box;
width: 200px;
padding: 20px;
border: 5px solid;
/* Total width: 200 + 40 + 10 = 250px */
}
/* Recommended: width includes padding+border */
.border-box {
box-sizing: border-box;
width: 200px;
padding: 20px;
border: 5px solid;
/* Total width: 200px */
}
/* Apply globally */
*, *::before, *::after {
box-sizing: border-box;
}Box Shadow
box-shadow는 그림자 효과를 추가합니다: offset-x offset-y blur-radius spread-radius color. 양수 오프셋은 그림자를 우/하로 이동합니다. inset은 내부 그림자를 만듭니다. 여러 그림자가 레이어링됩니다(첫 번째 = 맨 위). 자연스럽게 혼합되는 반투명 그림자에 rgba를 사용하세요. 그림자는 깊이에 좋지만 과용하면 성능을 해칩니다 - 미묘한 그림자를 선호하세요.
/* offset-x offset-y blur spread color */
.card {
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}
/* Multiple shadows */
.button {
box-shadow:
0 1px 2px rgba(0,0,0,0.1),
0 4px 8px rgba(0,0,0,0.05);
}
/* Inset shadow */
.input:focus {
box-shadow: inset 0 1px 3px rgba(0,0,0,0.1);
}
/* No shadow */
.no-shadow { box-shadow: none; }Display & Visibility
display: none은 요소를 레이아웃에서 완전히 제거합니다(공간 없음). visibility: hidden은 숨기지만 공간을 유지합니다. opacity: 0은 투명하게 만들지만 여전히 대화형입니다. block 요소는 전체 너비를 차지하고 줄을 바꿉니다. inline 요소는 텍스트와 함께 흐릅니다. inline-block은 인라인 흐름과 블록 차원(width, height)을 결합합니다. 콘텐츠 토글에 display: none을 사용하세요.
/* Display types */
div { display: block; } /* full width, line break */
span { display: inline; } /* content width, no break */
.inline-block { display: inline-block; } /* inline but block props */
.flex { display: flex; } /* flex container */
.grid { display: grid; } /* grid container */
.none { display: none; } /* removed from layout */
/* Visibility (keeps space) */
.hidden { visibility: hidden; }
/* Opacity (keeps space, can interact) */
.fade { opacity: 0; }색상 & 단위
색상 형식
CSS는 다양한 색상 형식을 지원합니다. Hex(#rrggbb)가 가장 일반적입니다. RGB/RGBA는 알파 투명도를 추가합니다. HSL(색조 0-360, 채도%, 밝기%)는 직관적입니다 - 색조를 변경하여 색을 이동하고, 밝기로 음영을 조정하세요. currentColor는 요소의 color 속성을 상속합니다. 최신 CSS는 또한 더 넓은 색역을 위해 oklch()와 color()를 지원합니다. 투명도에 rgba/hsla를 사용하세요.
/* Named colors */
.color { color: red; background: tomato; }
/* Hexadecimal */
.hex { color: #ff6600; } /* 6-digit */
.hex-short { color: #f60; } /* 3-digit shorthand */
/* RGB / RGBA */
.rgb { color: rgb(255, 102, 0); }
.rgba { background: rgba(0, 0, 0, 0.5); }
/* HSL / HSLA (hue, saturation, lightness) */
.hsl { color: hsl(20, 100%, 50%); }
.hsla { background: hsla(120, 100%, 50%, 0.3); }
/* Current color keyword */
.box { color: blue; border: 2px solid currentColor; }길이 단위
px는 절대적이고 예측 가능합니다. em은 부모의 font-size에 상대적입니다(중첩 시 합성). rem은 root(html) font-size에 상대적입니다 - 일관되고 접근성을 위해 선호됩니다. %는 부모에 상대적입니다. vh/vw는 viewport에 상대적입니다(100vh = 전체 높이). font 크기에는 rem을, 레이아웃에는 %를, border/세부 사항에는 px를 사용하세요.
/* Absolute units */
.px { font-size: 16px; } /* 1px = 1/96 inch */
.pt { font-size: 12pt; } /* 1pt = 1/72 inch */
/* Relative to parent font-size */
.em { font-size: 1.5em; } /* 1.5x parent */
/* Relative to root font-size (html) */
.rem { font-size: 1.2rem; } /* 1.2x root (usually 16px) */
/* Relative to parent dimensions */
.pct { width: 50%; } /* 50% of parent */
/* Viewport units */
.vh { height: 100vh; } /* 100% of viewport height */
.vw { width: 50vw; } /* 50% of viewport width */
.vmin { font-size: 2vmin; } /* 2% of smaller dimension */CSS 함수
calc()는 혼합 단위로 수학을 수행합니다(예: 100% - 250px). min()은 가장 작은 값을 선택합니다(반응형 max-width에 좋음). max()는 가장 큰 값을 선택합니다. clamp(min, preferred, max)는 경계 사이에서 확장되는 유동 값을 만듭니다 - 반응형 타이포그래피에 완벽합니다. var()는 선택적 폴백과 함께 사용자 정의 속성을 참조합니다. 이 함수들은 media query 없이 CSS를 동적으로 만듭니다.
/* calc() - mathematical calculations */
.sidebar { width: calc(100% - 250px); }
.gap { margin: calc(1rem + 10px); }
/* min() / max() - choose smaller/larger */
.responsive { width: min(90%, 1200px); }
.min-width { width: max(300px, 50%); }
/* clamp() - fluid sizing with bounds */
.title { font-size: clamp(1.5rem, 4vw, 3rem); }
/* var() - use custom properties */
.btn { color: var(--primary, #007bff); }그라데이션
그라데이션은 부드러운 색상 전환을 만듭니다. linear-gradient(방향, 색상1, 색상2)는 방향으로 이동합니다(to right, 45deg). radial-gradient는 중심점에서 확장합니다. conic-gradient는 중심 주위로 회전합니다. 위치로 색상 정지 를 추가할 수 있습니다: linear-gradient(to right, red 0%, blue 50%, green 100%). 그라데이션은 색상이 아닌 이미지이며 background-image가 허용되는 어디서든 사용할 수 있습니다.
/* Linear gradient */
.bg1 {
background: linear-gradient(to right, #ff0000, #0000ff);
}
/* Diagonal with angle */
.bg2 {
background: linear-gradient(45deg, #ff0000, #00ff00, #0000ff);
}
/* Radial gradient */
.bg3 {
background: radial-gradient(circle, #ff0000, #0000ff);
}
/* Conic gradient */
.bg4 {
background: conic-gradient(red, yellow, green, blue, red);
}필터 & 블렌드 모드
filter는 시각적 효과를 적용합니다: blur(), brightness(), contrast(), grayscale(), sepia(), hue-rotate(), invert(), opacity(), saturate(). 여러 필터가 연결됩니다. mix-blend-mode는 요소를 뒤에 있는 것과 혼합합니다(multiply, screen, overlay 등). backdrop-filter는 요소 뒤 영역에 필터를 적용합니다(glassmorphism에 좋음). 필터는 성능에 영향을 미칠 수 있습니다 - 드물게 사용하세요.
/* Filters */
img.bw { filter: grayscale(100%); }
img.blur { filter: blur(5px); }
img.bright { filter: brightness(1.5); }
img.sepia { filter: sepia(0.8); }
/* Multiple filters */
img.vintage {
filter: sepia(0.5) contrast(1.2) brightness(0.9);
}
/* Blend mode */
.overlay {
background: rgba(255,0,0,0.5);
mix-blend-mode: multiply;
}타이포그래피
폰트 속성
font-family는 폴백 목록을 받습니다 - 브라우저가 사용 가능한 첫 번째 것을 사용합니다. 항상 일반 패밀리(serif, sans-serif, monospace)로 끝내세요. font-weight는 100(얇음)에서 900(굵음)까지입니다. line-height: 1.5는 font 크기의 1.5배를 의미합니다 - 본문 텍스트 가독성에 1.4-1.6이 이상적입니다. font 축약은 최소한 size와 family를 포함해야 합니다.
body {
/* Font shorthand: style weight size/line-height family */
font: italic bold 16px/1.5 Arial, sans-serif;
/* Individual properties */
font-family: "Helvetica Neue", Arial, sans-serif;
font-size: 16px;
font-weight: 400; /* 100-900, normal=400, bold=700 */
font-style: italic; /* normal, italic, oblique */
line-height: 1.5;
}텍스트 스타일링
text-align은 수평 정렬을 제어합니다. text-decoration은 선을 추가합니다(underline, overline, line-through). text-transform은 대소문자를 변경합니다. letter-spacing(자간)과 word-spacing은 문자와 단어 간 간격을 조정합니다. white-space: nowrap은 텍스트 줄바꿈을 방지합니다. 수직 정렬에는 vertical-align(인라인) 또는 flexbox/grid 정렬(블록)을 사용하세요.
p {
text-align: justify; /* left, right, center, justify */
text-decoration: underline; /* none, overline, line-through */
text-transform: capitalize; /* uppercase, lowercase, capitalize */
text-indent: 2em; /* indent first line */
letter-spacing: 0.05em; /* tracking */
word-spacing: 0.1em;
white-space: nowrap; /* prevent wrapping */
}
a {
text-decoration: none;
color: #0066cc;
}텍스트 오버플로우 & 줄바꿈
말줄임표로 텍스트를 자르려면 세 가지 속성이 필요합니다: white-space: nowrap, overflow: hidden, text-overflow: ellipsis. overflow-wrap: break-word는 오버플로우를 방지하기 위해 긴 단어를 끊습니다. word-break: break-all은 어떤 문자에서든 끊습니다. text-wrap: balance(최신)은 제목의 줄 길이를 균형 있게 합니다. 자르기가 작동하려면 항상 max-width나 width를 설정하세요.
/* Truncate with ellipsis */
.truncate {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 200px;
}
/* Break long words */
.break-word {
overflow-wrap: break-word;
word-break: break-all;
}
/* Balance text wrapping (newer) */
h1 {
text-wrap: balance;
}웹 폰트 (@font-face)
@font-face는 사용자 정의 폰트를 로드합니다. woff2가 최신 형식입니다(최상의 압축). 폴백으로 woff를 제공하세요. font-display: swap은 폰트 로드 시 대체 텍스트를 즉시 표시한 다음 교체합니다(보이지 않는 텍스트 방지). 항상 폴백 font-family를 선언하세요. Google Fonts는 @import나 <link>를 통해 호스팅된 폰트를 제공합니다. 성능을 위해 중요 폰트를 preload하세요.
@font-face {
font-family: 'MyCustomFont';
src: url('fonts/custom.woff2') format('woff2'),
url('fonts/custom.woff') format('woff');
font-weight: 400;
font-style: normal;
font-display: swap;
}
body {
font-family: 'MyCustomFont', Arial, sans-serif;
}
/* Google Fonts import */
@import url('https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap');리스트 & 링크 스타일링
list-style: none은 사용자 정의 내비게이션이나 스타일된 리스트를 위해 기본 글머리를 제거합니다. list-style-type은 글머리를 변경합니다(disc, circle, square, decimal, none). list-style-position: inside는 글머리를 콘텐츠 영역 내부에 넣습니다. 링크의 경우 LVHA 순서가 중요합니다: :link, :visited, :hover, :active. 이는 링크 상태의 적절한 캐스케이드를 보장합니다.
/* Reset list styles */
ul {
list-style: none;
padding: 0;
margin: 0;
}
/* Custom bullets */
ul.custom {
list-style-type: square;
list-style-position: inside;
}
/* Image bullets */
ul.image {
list-style-image: url('bullet.png');
}
/* Link states (order matters!) */
a:link { color: blue; }
a:visited { color: purple; }
a:hover { color: red; text-decoration: underline; }
a:active { color: orange; }Flexbox 레이아웃
Flex 컨테이너
display: flex는 flex 컨테이너를 만듭니다. justify-content는 주축을 따라 항목을 정렬합니다(행에서 수평). align-items는 교차축을 따라 정렬합니다(수직). flex-direction은 주축을 변경합니다. flex-wrap은 항목이 새 줄로 줄바꿈을 허용합니다. gap은 항목 간 간격을 설정합니다(margin 해킹 대체). Flexbox는 1D 레이아웃(행 또는 열)에 이상적입니다.
.container {
display: flex;
/* Main axis alignment */
justify-content: space-between;
/* flex-start, center, flex-end, space-around, space-evenly */
/* Cross axis alignment */
align-items: center;
/* flex-start, center, flex-end, stretch, baseline */
/* Direction */
flex-direction: row;
/* row, row-reverse, column, column-reverse */
/* Wrapping */
flex-wrap: wrap;
/* nowrap, wrap, wrap-reverse */
/* Gap between items */
gap: 16px;
}Flex 항목
flex-grow는 항목이 여분의 공간을 공유하는 방법을 제어합니다(0 = 늘어나지 않음, 1 = 동등하게 늘어남). flex-shrink는 공간이 제한될 때 항목이 축소하는 방법을 제어합니다. flex-basis는 초기 크기를 설정합니다. 축약 flex: 1 은 flex-grow:1, flex-shrink:1, flex-basis:0%를 의미합니다. align-self는 컨테이너의 align-items를 한 항목에 대해 재정의합니다. order는 DOM을 변경하지 않고 항목을 시각적으로 재정렬합니다.
.item {
/* Grow: how much space to take (0 = don't grow) */
flex-grow: 1;
/* Shrink: how much to shrink when space is tight */
flex-shrink: 0;
/* Basis: initial size before growing/shrinking */
flex-basis: 200px;
/* Shorthand: flex: grow shrink basis */
flex: 1 0 200px;
/* Override align-items for this item */
align-self: flex-end;
/* Order (default 0, lower = earlier) */
order: -1;
}일반적인 Flexbox 패턴
Flexbox는 가운데 정렬을 간단하게 만듭니다: justify-content: center + align-items: center. sticky footer의 경우 body를 min-height: 100vh로 flex 열로 만들고 메인 콘텐츠를 flex: 1로 설정하세요. navbar의 경우 justify-content: space-between이 첫 번째와 마지막 항목을 반대쪽 끝으로 밀어냅니다. 이 패턴들은 flexbox 이전에 어려웠던 일반적인 레이아웃 문제를 해결합니다.
/* Center anything */
.center {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
}
/* Sticky footer */
body {
display: flex;
flex-direction: column;
min-height: 100vh;
}
.main { flex: 1; }
/* Navbar: logo left, links right */
.nav {
display: flex;
justify-content: space-between;
align-items: center;
}Flex Direction & Wrap
flex-direction: column은 수직 레이아웃을 만듭니다(쌓기에 유용). flex-wrap: wrap은 공간이 부족할 때 항목이 새 줄로 흐르게 합니다. flex: 1 1 300px은 항목이 300px에서 시작하고 공간을 채우기 위해 늘어나며 필요에 따라 축소됨을 의미합니다. align-content는 줄바꿈된 줄 간 간격을 제어합니다(wrap에서만 작동). 이 패턴은 반응형 카드 그리드를 만듭니다.