Lists and counters/Indenting lists

김동현·2026년 3월 21일

mdn 학습 번역 - CSS

목록 보기
116/190

안녕하세요! 예비 프론트엔드 개발자님.

오늘은 웹 페이지에서 정말 밥 먹듯이 사용되지만, 막상 레이아웃을 잡으려고 하면 은근히 우리를 괴롭히는 '목록(List) 들여쓰기'에 대해 아주 자세히 파헤쳐 보겠습니다. MDN 공식 문서를 기반으로, 제가 실무에서 겪었던 팁들을 팍팍 얹어서 쉽고 재미있게 설명해 드릴게요. 자, 시작해 볼까요?


일관된 목록 들여쓰기 (Consistent list indentation)

목록(list)을 스타일링할 때 우리가 가장 흔하게 하는 작업 중 하나는 바로 들여쓰기 간격(indentation distance)을 조절하는 것입니다. 즉, 목록의 항목들이 오른쪽으로 얼마나 밀려나게 할 것인지를 정하는 일이죠. 이 문서에서는 목록의 글머리 기호(마커, marker)가 잘 보이도록 목록 항목들을 어떻게 들여쓰기 하는지 확실히 이해할 수 있게 도와드릴 거예요.

왜 리스트가 이런 식으로 작동하는지, 그리고 더 중요하게는 레이아웃이 꼬이는 문제를 어떻게 아예 피할 수 있는지 이해하려면, 브라우저가 목록을 생성하는 세부적인 원리를 들여다볼 필요가 있습니다.

목록 만들기 (Creating a list)

독립적인 목록 항목 (Stand-alone list item)

먼저, <ul>이나 <ol> 같은 목록 컨테이너에 중첩되지 않고 덜렁 혼자 있는 순수한 목록 항목을 생각해 보겠습니다. HTML <li> 요소를 사용하면, 브라우저는 이 요소의 display 값을 list-item으로 설정합니다.

목록 안에 들어있지 않은 이 독립적인 <li> 항목들에 마커(흔히 "글머리 기호"나 "불릿"이라고 부르죠)가 표시될지 말지는 브라우저의 마음에 달려 있습니다. 만약 이 불릿을 없애고 싶다면 list-style-type: none을 사용하면 됩니다.

👨‍🏫 강사의 팁:
실무에서는 <li> 태그를 독립적으로 쓰는 경우는 거의 없어요! 항상 <ul>이나 <ol> 안에 자식으로 넣는 것이 웹 표준과 접근성에 맞습니다. 또한, 우리가 네비게이션 메뉴나 탭을 만들 때 점(bullet)을 없애기 위해 list-style-type: none;은 정말 숨 쉬듯이 사용하는 속성이니 꼭 기억해 두세요!

li {
  border: 1px dashed red;
}
li:nth-of-type(n + 4) {
  list-style-type: none;
}
li {
  width: 15em;
}
<p>Default bullets depend on the browser:</p>
<li>A list item</li>
<li>A list item</li>
<li>A list item</li>
<p>These list items have their bullets removed:</p>
<li>A list item</li>
<li>A list item</li>
<li>A list item</li>

위의 점선으로 된 빨간 테두리는 각 목록 항목(<li>)이 차지하는 콘텐츠 영역(content area)의 바깥쪽 가장자리를 보여줍니다. 현재 이 상태에서는 목록 항목들에 패딩(padding)이나 테두리 두께 등의 여백이 전혀 들어가지 않은 상태입니다.

중첩된 목록 항목 (Nested list items)

이제 이 <li> 항목들을 부모 요소 안에 감싸보겠습니다. 이번에는 순서가 없는 목록인 <ul> 요소 안에 넣어볼게요. CSS 박스 모델(box model)에 따르면, 목록 항목(<li>)들의 박스는 반드시 부모 요소(<ul>)의 콘텐츠 영역 내부에 표시되어야 합니다.

ul {
  border: 1px dashed blue;
}
li {
  border: 1px dashed red;
  list-style-type: none;
}
body {
  width: 15em;
}
<ul>
  <li>A list item</li>
  <li>A list item</li>
  <li>A list item</li>
</ul>

파란색 점선 테두리는 <ul> 요소의 콘텐츠 영역 가장자리를 보여줍니다. 보시면 부모인 <ul>에는 이미 마진(margin)과 패딩(padding)이 들어가 있는 것을 확인할 수 있어요. 브라우저는 순서 없는 목록(<ul>)에 기본적으로 아래와 같은 스타일을 부여합니다.

👨‍🏫 강사의 팁:
바로 이 부분 때문에 처음 CSS를 배우시는 분들이 많이 당황합니다. "어? 나는 여백을 준 적이 없는데 왜 리스트가 오른쪽으로 밀려있지?" 하고요. 브라우저가 기본적으로 제공하는 User-Agent 스타일이 떡하니 자리 잡고 있기 때문입니다.

ul {
  /* user-agent styles */
  display: block;
  list-style-type: disc;
  margin-block-start: 1em;
  margin-block-end: 1em;
  padding-inline-start: 40px;
}

기본 글머리 기호 위치 (Default bullet position)

이제 다시 목록 항목에 마커(불릿)를 넣어보겠습니다. 이것은 순서 없는 목록(<ul>)이므로, 자식인 <li> 항목들은 부모인 <ul>로부터 list-style-type: disc; 라는 브라우저 스타일을 상속받습니다. 이 disc가 바로 우리가 아는 까만색으로 채워진 동그라미 불릿입니다.

li {
  border: 1px dashed red;
}
ul {
  border: 1px dotted blue;
}
ul:last-of-type {
  list-style-position: inside;
}
ul {
  width: 15em;
}
<p>These default to <code>list-style-position: outside</code>.</p>
<ul>
  <li>A list item</li>
  <li>A list item</li>
  <li>A list item</li>
</ul>
<p>These have <code>list-style-position: inside</code> set.</p>
<ul>
  <li>A list item</li>
  <li>A list item</li>
  <li>A list item</li>
</ul>

시각적으로 보면, 마커(까만 점)들은 <ul>의 콘텐츠 영역 바깥쪽에 위치해 있습니다. 하지만 여기서 진짜 중요한 건 그게 아니에요. 핵심은 마커들이 <ul>이 아니라 <li> 요소의 "주요 박스(principal box)" 바깥쪽에 배치된다는 점입니다! 이 마커들은 마치 <li> 요소의 콘텐츠 영역 바깥에 대롱대롱 매달려 있는 일종의 부속물(appendage)과 같지만, 여전히 <li>에 단단히 붙어있는 형태입니다.

👨‍🏫 강사의 팁:
방금 제가 첨부해 드린 다이어그램을 머릿속에 꼭 넣어두세요! outside일 때는 점이 박스 밖에 있어서 테두리를 쳐도 점이 테두리 밖으로 삐져나옵니다. 그래서 가끔 리스트 요소에 패딩을 0으로 리셋해버리면 점이 화면 밖으로 날아가서 안 보이는 버그가 생기곤 해요.

이러한 작동 방식 때문에, 모든 최신 브라우저에서는 list-style-position의 값이 기본값인 outside이거나 명시적으로 outside로 설정된 경우, <li> 요소에 테두리(border)를 주면 마커는 그 테두리 바깥에 자리 잡게 됩니다.

반대로 우리가 이 값을 inside로 바꾸면 어떻게 될까요? 마커들이 <li>의 콘텐츠 안쪽으로 쏙 들어옵니다. 마치 <li>가 시작되는 맨 앞부분에 인라인 박스(inline box)가 하나 추가된 것처럼 말이죠.

기본 들여쓰기 (Default indentation)

위에서 언급했듯이, 모든 브라우저는 <ul> 부모 요소에 마진과 패딩을 모두 제공합니다. 브라우저(user agents)마다 CSS가 아주 약간씩 다를 순 있지만, 기본적으로 아래의 내용들을 모두 포함하고 있습니다.

ul,
ol {
  /* user-agent styles */
  display: block;
  list-style-type: disc;
  margin-block-start: 1em;
  margin-block-end: 1em;
  padding-inline-start: 40px;
}
ol {
  list-style-type: decimal;
}
li {
  display: list-item;
  text-align: match-parent;
}
::marker {
  unicode-bidi: isolate;
  font-variant-numeric: tabular-nums;
  text-transform: none;
}

모든 브라우저는 기본적으로 <ul> 요소에 대해 padding-inline-start 값을 40px로 설정합니다. 영어한국어처럼 왼쪽에서 오른쪽으로 읽는(left-to-right) 언어 환경에서는 이것이 왼쪽 패딩(left padding)으로 작동하죠. 물론, 작성자 스타일시트(즉, 여러분이 직접 작성하는 CSS 파일)에서 패딩을 설정하면 그 값이 브라우저의 기본값보다 우선순위를 가집니다.

👨‍🏫 강사의 팁:
여기서 padding-left가 아니라 padding-inline-start라는 논리적 속성(Logical Properties)이 쓰인 것에 주목해 주세요! 아랍어처럼 오른쪽에서 왼쪽(RTL)으로 읽는 언어로 사이트가 번역되면, inline-start는 자동으로 오른쪽이 되기 때문에 레이아웃이 깨지지 않는답니다. 똑똑하죠?

만약 들여쓰기를 아주 명확하게 통제하고 싶다면, 여러분의 스타일시트에 다음과 같은 코드를 추가해 보세요. 이렇게 하면 다른 곳에서 덮어쓰지 않는 이상, <main> 섹션 영역 내에 있는 목록 항목(<li>)들이 적절하고 일관되게 들여쓰기 되도록 보장할 수 있습니다.

:where(main ol, main ul) {
  margin-inline-start: 0;
  padding-inline-start: 40px;
}

그리고 명심하세요. <li> 요소는 항상 <ul>이나 <ol> 안에 자식으로 안전하게 중첩(nest)시켜서 사용해야 합니다!


어떠신가요? 이제 왜 처음 리스트를 만들면 글머리 기호가 저만치 밀려있는지, 테두리를 쳤을 때 점이 왜 밖으로 튀어나가는지 완벽하게 이해하셨죠? 브라우저의 이런 기본 동작 원리를 이해하고 나면, 리셋(Reset) CSS를 작성하거나 원하는 디자인의 리스트를 만들 때 훨씬 수월해지실 거예요! 코딩 파이팅입니다! 😊

profile
프론트에_가까운_풀스택_개발자

0개의 댓글