참고문헌 목록, 용어 정의, 시, 대본, 주소. 첫 줄은 왼쪽 끝에 붙고 둘째 줄부터 들여쓰는 내어쓰기(hanging indent)가 필요한 자리는 많다. 그리고 CSS에는 오랫동안 이걸 바로 말하는 문법이 없었다. 대신 모두가 같은 트릭을 썼다.
.ref {
padding-left: 2em;
text-indent: -2em;
}
블록 전체를 2em 밀어 넣고, 첫 줄만 2em 도로 당긴다. 결과는 내어쓰기처럼 보인다. 20년 넘게 쓰인 트릭이고 지금도 검색하면 이게 나온다.
이제 이 두 줄을 한 줄로 바꿀 수 있다.
.ref {
text-indent: 2em hanging;
}
2026년 3월에 크롬이 마지막으로 합류하면서 모든 브라우저에서 된다. 이 글은 hanging과 each-line이 정확히 무엇을 하는지, 트릭이 어디서 어긋났는지, 그리고 트릭으로는 아예 못 만들던 것이 무엇인지에 대한 것이다.
text-indent는 원래 "첫 줄"만 건드린다
text-indent의 정의는 이렇다. 블록 안 인라인 콘텐츠의 첫 번째 서식 줄(first formatted line) 시작 쪽에 여백을 준다. 그 뒤의 줄은 손대지 않는다. 문단 첫 줄을 들여쓰는 인쇄 관행을 그대로 옮긴 속성이다.
"첫 번째 서식 줄"이 무엇인지가 중요하다. <br>로 강제로 줄을 바꾼 다음 줄은 첫 줄이 아니다. 그래서 주소나 시처럼 <br>가 들어간 블록에서는 맨 첫 줄만 들여써지고 나머지는 전부 왼쪽에 붙는다. 이 성질이 뒤에서 each-line의 존재 이유가 된다.
CSS Text Level 3가 이 속성에 키워드 둘을 붙였다.
text-indent: [ <length-percentage> ] && hanging? && each-line?
hanging— 명세 원문은 한 문장이다. "적용되는 줄을 반전한다(Inverts which lines are affected)." 첫 줄에 주던 여백을 첫 줄을 제외한 나머지에 준다.each-line— "각 블록 컨테이너의 첫 줄, 그리고 강제 줄바꿈 뒤의 각 줄에 적용된다. 소프트 랩 뒤의 줄에는 적용되지 않는다." 즉<br>로 나뉜 줄마다 새 문단처럼 취급한다.
둘은 같이 쓸 수 있다. 조합이 넷이니 그림으로 보는 편이 빠르다.
오른쪽 아래가 핵심이다. hanging each-line은 "내가 줄을 바꾼 곳은 왼쪽에 붙이고, 폭이 모자라 저절로 이어진 줄만 들여쓴다"는 뜻이다. 시, 가사, 대본, 줄바꿈이 있는 코드 — 사람이 정한 줄 구조를 유지하면서 화면 폭에 밀려 넘어간 부분만 표시하는 것. 이게 이 속성의 진짜 쓸모이고, 트릭으로는 못 만든다.
트릭이 어긋나는 곳
padding-left + 음수 text-indent는 참고문헌 하나만 놓고 보면 완벽하다. 문제는 그 주변에서 난다.
값이 둘이라 어긋난다
트릭은 같은 값을 두 번 쓴다. 하나를 고치고 하나를 안 고치면 첫 줄이 튀어나오거나 덜 들어간다. 반응형으로 폭에 따라 들여쓰기를 줄일 때 미디어 쿼리마다 두 줄씩 고쳐야 하고, CSS 변수로 묶어도 "왜 이 변수가 두 속성에 들어가는가"를 다음 사람이 알아야 한다. text-indent: 2em hanging은 값이 하나다.
padding은 상자를 움직인다
padding-left는 텍스트만 미는 것이 아니라 상자의 콘텐츠 영역을 옮긴다. 배경, 테두리, ::before로 붙인 장식, 그리고 list-style의 불릿 위치가 전부 영향을 받는다. 목록 항목에 내어쓰기를 걸었더니 불릿과 텍스트 사이가 벌어지고, 배경색을 준 블록에서는 텍스트가 배경 왼쪽 끝에 붙지 않는다. text-indent는 줄 상자 안에서만 움직여서 상자는 그대로다.
overflow: hidden 이 첫 줄을 자른다
음수 text-indent는 첫 줄을 콘텐츠 영역 밖으로 내보낸다. 패딩이 그 자리를 마련해두니 보통은 괜찮지만, 어떤 이유로 패딩이 사라지거나 줄어들면(다른 규칙이 padding: 0으로 덮거나, 축약 속성 padding이 뒤에 오거나) 첫 줄의 왼쪽 2em이 잘려 나간다. overflow: hidden이 걸린 컨테이너에서 이 사고가 잦다. 텍스트 숨김용으로 text-indent: -9999px를 쓰던 시절이 남긴 습관인데, 같은 원리로 내어쓰기 첫 줄도 잘릴 수 있다.
물리 방향이라 RTL에서 깨진다
padding-left는 왼쪽이다. 아랍어·히브리어처럼 오른쪽에서 시작하는 문서에서는 반대쪽에 여백이 생기고, text-indent는 시작 쪽(inline-start)에 적용되니 둘이 서로 다른 쪽을 가리킨다. padding-inline-start로 바꾸면 되지만, 그걸 아는 사람만 고친다. hanging은 처음부터 논리 방향이다.
상속되는 것은 text-indent다
이건 트릭과 새 문법 모두에 해당한다. text-indent는 상속된다. 명세가 따로 주의를 준다 — 블록에 지정하면 자손 inline-block에도 적용되므로, inline-block 요소에는 text-indent: 0을 주는 것이 현명하다고. 내어쓰기한 문단 안에 inline-block 배지를 넣었더니 배지 안 텍스트가 밀린다면 이것이다.
어디에 쓰나
참고문헌·인용 목록 — 2em hanging. 학술 양식의 표준 내어쓰기다. 저자명이 왼쪽에 붙어 훑기 쉽다.
.references li {
text-indent: 2em hanging;
list-style: none;
}
정의 목록의 dd — 용어를 첫 줄 시작에 두고 설명이 길어지면 이어지는 줄을 들여쓴다. dt와 dd를 한 줄에 놓는 스타일에서 특히 유용하다.
시·가사·대본 — hanging each-line. <br>로 나눈 행은 전부 왼쪽에 붙고, 폰에서 폭이 모자라 넘어간 부분만 들여써서 "이건 새 행이 아니라 이어진 것"을 보여준다. 대본이라면 화자 이름이 왼쪽에 서고 대사가 길어지면 이어지는 줄이 들어간다.
.lyrics, .script {
text-indent: 1.5em hanging each-line;
}
줄바꿈되는 코드 — pre { white-space: pre-wrap }로 긴 코드 줄을 접을 때, 접힌 이어짐 줄에 hanging each-line을 주면 원래 줄과 이어진 줄이 구분된다. 터미널과 에디터가 하는 방식이다. 코드에서 줄바꿈은 전부 강제 줄바꿈이니 each-line이 정확히 맞는다.
pre.wrap {
white-space: pre-wrap;
text-indent: 2ch hanging each-line;
}
주소·연락처 블록 — <address> 안의 여러 줄. 첫 줄 라벨을 왼쪽에 두고 나머지를 맞춘다.
브라우저 지원과 폴백
| 브라우저 | 버전 | 출시일 |
|---|---|---|
| Safari | 15 | 2021-09-20 |
| Firefox | 121 | 2023-12-19 |
| Chrome · Edge | 146 | 2026-03-10 |
Baseline Newly available 2026-03-13. 출처: webstatus.dev, 2026-09-07 조회. hanging과 each-line은 지원 시점이 같다.
순서가 평소와 반대다. 사파리가 5년 먼저 했고 크롬이 올해 3월에야 붙었다. 그래서 "이제 된다"는 최근이지만, 안 되는 브라우저는 6개월 안 된 크롬뿐이라는 뜻이기도 하다. 크롬은 자동 갱신이라 실제 방문자 중 146 미만은 빠르게 줄어든다.
그래도 폴백은 둔다. 이 속성은 폴백이 쉽다. 키워드를 모르는 브라우저는 선언 전체를 무시하기 때문에, 트릭을 먼저 쓰고 새 문법을 @supports로 덮으면 된다.
.ref {
padding-inline-start: 2em;
text-indent: -2em;
}
@supports (text-indent: 1em hanging) {
.ref {
padding-inline-start: 0;
text-indent: 2em hanging;
}
}
@supports 없이 text-indent: -2em; text-indent: 2em hanging;으로 겹쳐 쓰는 것은 안 된다. 두 번째 줄이 무시되면 첫 줄이 남아 음수 인덴트는 걸리는데 패딩을 어디서 없앨지 정할 수 없다. 패딩과 인덴트를 같이 바꿔야 하니 @supports 블록이 필요하다.
정리
text-indent는 원래 첫 번째 서식 줄만 건드린다.<br>뒤 줄은 첫 줄이 아니다.hanging은 적용 대상을 반전한다 — 첫 줄 빼고 전부. 참고문헌·정의 목록.each-line은 강제 줄바꿈 뒤 줄을 첫 줄로 친다. 둘을 합친hanging each-line이 시·대본·접힌 코드에 맞고, 트릭으로는 만들 수 없다.- 트릭의 문제: 값 둘 동기화, 패딩이 상자를 움직임,
overflow: hidden에서 첫 줄 잘림, 물리 방향. - 지원: Safari 15 → Firefox 121 → Chrome 146(2026-03). 폴백은
@supports로 패딩과 인덴트를 함께 바꾼다. text-indent는 상속된다.inline-block자손에text-indent: 0.