목차9개 항목
출처와 참고
Rachel Andrew의 「CSS를 배우는 방법」(2019.02)과 Greg Whitworth의 「중괄호에서 픽셀로」(Braces to Pixels, 2019.01, 웹액츄얼리 번역)를 바탕으로 재구성한 노트다. 캐스케이드의 출처·중요도는 web.dev 「Learn CSS」 강좌의 The cascade 모듈로, CSS의 역할 개관은 ByteByteGo의 System Design 101 가이드 「What is CSS?」로 보강했다.
CSS가 하는 일
CSS(Cascading Style Sheets)는 HTML 요소를 화면에 어떻게 그릴지 기술하는 스타일 언어다. 초기 웹에서는 HTML이 내용과 모양을 함께 맡았다. CSS는 구조(HTML)와 표현(CSS)을 분리해, 색 구성을 바꿀 때 CSS 파일만 고치면 되게 했다.
| 역할 | 내용 | 상세 노트 |
|---|---|---|
| 규칙 | 선택자로 요소를 고르고, 속성 선언으로 모양을 정한다 (p { color: blue; }) | CSS 기초, 선택자 |
| 캐스케이드 | 규칙이 충돌하면 출처·중요도·특정도·순서로 이길 규칙을 정한다 | 아래 「캐스케이드」 |
| 레이아웃 | 표나 float 꼼수 대신 Flexbox·Grid로 배치한다 | Flexbox, CSS Grid |
| 애니메이션 | transition과 @keyframes로 자바스크립트 없이 상태 변화를 움직인다 | CSS 애니메이션 |
| 반응형 | 화면 크기·해상도에 맞춰 레이아웃과 스타일을 바꾼다 | 반응형 디자인 |
속성보다 원리
CSS 속성과 값은 외울 필요가 없다. 필요할 때 MDN에서 찾으면 된다. 대신 아래 개념을 모르면 CSS가 "이상하게" 동작한다고 느끼게 된다. CSS 질문의 대부분은 속성이 실제와 다르게 동작한다고 가정해서 생긴다. 특히 크기 결정과 정렬에서 그렇다.
치트시트는 기억을 되살리는 용도다. 배우는 도구가 아니다. CSS가 예상과 다르게 동작하면 문제만 남긴 최소 재현 예제(reduced test case)를 만들고, 개발자 도구에서 어떤 규칙이 이기고 졌는지(취소선) 확인한다. 스타일 창 표시를 읽는 법은 DevTools로 DOM과 CSS 다루기에 있다.
핵심 개념
| 개념 | 핵심 | 자세히 |
|---|---|---|
| 선택자 | 문서 위치·상태로 요소를 고른다. 가상 클래스는 "클래스를 붙인 것처럼", 가상 요소는 "요소를 끼워 넣은 것처럼" 동작한다 | CSS 선택자와 우선순위 |
| 캐스케이드·상속·특정도 | 여러 규칙이 겹칠 때 무엇이 이기는지, 무엇이 자식에게 물려지는지 | 아래 "캐스케이드" |
| 박스 모델 | 모든 것은 상자다. content-box는 너비에 패딩·테두리를 더하고, border-box는 너비 안에 포함한다 | 박스 모델과 display |
| 일반 흐름 | 블록은 블록 방향으로, 인라인은 인라인 방향으로 쌓인다. 잘 짠 HTML은 CSS 없이도 읽힌다 | |
| 서식 맥락 | display는 바깥쪽 타입(형제와 어떻게 놓이나)과 안쪽 타입(자식을 어떻게 배치하나)을 정한다. display: flex = block flex | Float와 Flexbox 레이아웃 |
| 흐름 안과 밖 | float, position: absolute는 요소를 흐름에서 빼낸다. 빠진 요소는 다른 요소와 공간을 나누지 않아 겹침을 직접 관리해야 한다 | CSS position과 z-index |
| 레이아웃 방법 | 일반 흐름, 플렉스, 그리드, 다단, 위치 지정. 경쟁이 아니라 상황별 선택지다. 억지로 맞추고 있다면 다른 방법을 시도한다 | CSS 그리드 레이아웃 |
| 박스 정렬 | justify-*, align-*은 플렉스만의 기능이 아니다. 그리드·다단·블록에도 같은 모듈이 적용된다 | 쓰기 모드와 논리적 속성 |
| 크기 결정 | 내재적 크기(내용 기반: min-content, max-content)와 외재적 크기(맥락 기반: 고정값, %). 플렉스 공간 분배와 fr이 이 위에서 동작한다 | |
| 반응형 | 유연한 레이아웃 덕분에 미디어 쿼리는 줄고, 필요한 곳에만 브레이크포인트를 둔다 | 반응형 디자인과 다국어 타이포그래피 |
| 글꼴 | 가변 폰트로 파일 하나에서 굵기·폭을 연속 조절한다 | 웹 타이포그래피: 가독성, 글줄 길이, 웹폰트 |
| 변형·애니메이션 | transform, transition, @keyframes. 필요할 때 찾아 쓰되, JS·SVG·Web Animations API와의 선택 기준을 안다 | transform: 이동·회전·확대·기울이기 |
중괄호가 픽셀이 되기까지
브라우저가 CSS를 처리하는 전체 흐름은 브라우저 렌더링 과정에 있다. 여기서는 CSS 쪽 단계를 자세히 본다.
CSS 텍스트는 해석(축약형은 긴 속성으로 풀린다) → 캐스케이드(요소마다 이기는 선언 고르기) → 값 계산(em·vh·calc()를 px로) → 레이아웃 → 페인트 → 합성을 거친다. 값 계산까지 끝난 결과가 getComputedStyle()이 돌려주는 계산된 스타일이다. :hover 같은 변경이 어느 단계부터 다시 도는지는 브라우저 렌더링 과정의 표에 있다.
캐스케이드
선언이 여러 개면 아래 순서로 비교해 처음 차이가 나는 단계에서 승자가 정해진다.
| 순서 | 기준 | 내용 |
|---|---|---|
| 1 | 출처와 중요도 | 일반 선언은 작성자 > 사용자 > 브라우저 기본(user agent). !important는 이 순서가 뒤집혀 브라우저 기본 > 사용자 > 작성자. 그래서 사용자의 접근성 설정이 !important로 작성자 스타일을 이길 수 있다. 실행 중인 애니메이션 값은 일반 선언보다 강하고, 실행 중인 전환(transition) 값은 !important보다도 강하다. 상태를 바꾸는 것이 둘의 목적이기 때문이다 |
| 2 | 맥락(context) | 섀도 DOM 안팎의 규칙이 부딪치면 캡슐화 규칙으로 가린다 |
| 3 | 요소에 붙은 스타일 | 인라인 style 속성은 어떤 선택자보다 강하다. 레이어·특정도보다 먼저 비교한다 |
| 4 | 캐스케이드 레이어 | @layer로 묶은 규칙은 레이어 순서가 특정도보다 먼저다. 일반 선언은 나중 레이어가, 레이어 밖 규칙이 가장 강하다. !important는 반대로 먼저 선언한 레이어가 이긴다 |
| 5 | 특정도 | ID > 클래스·속성·가상 클래스 > 요소·가상 요소. :where()는 0, :is()·:has()는 인자 중 가장 높은 값 |
| 6 | 등장 순서 | 모두 같으면 나중에 나온 선언이 이긴다 |
이긴 값이 없는 속성은 상속되는 속성(글자색, 글꼴 등)이면 부모에게서, 아니면 초깃값을 쓴다. 상속 목록과 inherit·unset·revert 같은 되돌리기 키워드는 CSS 선택자와 우선순위의 상속에 있다.
출처는 세 가지다. 브라우저 기본 스타일시트(user agent), 사용자 스타일(OS의 기본 글자 크기·움직임 줄이기 설정, 사용자 CSS를 넣는 확장 프로그램), 작성자 스타일(<link>, <style>, @import, style 속성, Bootstrap 같은 라이브러리도 작성자 출처다). 같은 단계에서 비긴 <link>와 <style>은 문서에서 뒤에 나온 것이 이긴다. 개발자 도구의 스타일 창은 일치하는 모든 선언을 보여 주고 진 선언에 취소선을 긋는다. 기대한 규칙이 아예 없다면 선택자가 맞지 않은 것(오타, 잘못된 값)이다.
계산값
계산 단계를 거치면 길이 값은 대부분 픽셀, 퍼센트, auto 중 하나로 정리된다. width: 50%와 height: auto는 레이아웃 전까지 그대로 남는다. 부모 크기를 알아야 풀 수 있기 때문이다.
레이아웃
- DOM을 따라 내려가며 요소마다 주 박스(principal box)를 만든다. 텍스트는 줄 상자(line box)가 된다.
- 내용이 넘치면 자식이 부모에게 알리고, 부모는 줄 상자를 이어 만들어 나머지를 배치한다. 다 놓은 뒤 트리를 거슬러 올라가며
auto와%를 확정한다. - float, 절대 위치 요소,
auto너비의 표 셀은 내용에 맞춰 줄어드는(shrink-to-fit) 박스다. 브라우저는 먼저 무한한 공간에서 내용을 재 최소 너비(가장 긴 단어)와 최대 너비(한 줄로 늘였을 때)를 구하고, 부모가 줄 수 있는 공간 안에서 너비를 정한다. - float는 새 블록 서식 맥락을 만들고, 주변 블록의 줄 상자들이 그 영역을 피해 배치된다.
- 다단·인쇄처럼 내용을 여러 칸으로 나누는 것을 조각화(fragmentation)라고 한다. 한 칸을 채우면 다음 칸을 만들어 이어서 배치한다.
페인트와 합성
- 각 박스는 배경 → 테두리 → 내용 순으로 그려진다. 텍스트도 결국 비트맵이 된다.
z-index는 레이어를 만드는 것이 아니라 쌓임 맥락(stacking context)을 만들어 그리는 순서를 바꾼다.- 합성기(compositor)는 레이어 비트맵을 겹쳐 화면에 낸다.
transform·opacity애니메이션은 해당 요소를 별도 레이어로 두면 매 프레임 다시 그리지 않고 위치만 옮겨 합성할 수 있다. 합성기는 보통 별도 스레드에서 돌아 메인 스레드가 바빠도 애니메이션이 부드럽다.
정리
- 속성은 찾아 쓰고, 캐스케이드·박스 모델·흐름·서식 맥락·크기 결정을 이해한다.
- 이상하게 동작하면 최소 재현 예제와 개발자 도구로 원인을 찾는다.
- CSS는 해석 → 캐스케이드 → 계산 → 레이아웃 → 페인트 → 합성을 거쳐 픽셀이 된다.
- 캐스케이드는 출처·중요도 → 맥락 → 인라인 스타일 → 레이어 → 특정도 → 순서로 비교한다.
관련 노트: 브라우저 렌더링 과정, CSS 선택자와 우선순위, 박스 모델과 display, CSS 기초: 문법, 적용 방법, 단위, CSS position과 z-index