Skip to content
This page has been auto-translated and may contain errors.View in English

타이포그래피

docs.scrimba.com

웹에서 사람들이 읽는 것은 대부분 텍스트이고, 페이지가 주는 느낌 역시 그 텍스트가 어떻게 짜여 있느냐에서 나옵니다. 서체를 바꾸고, 줄 간격을 살짝 조정하고, 한 줄의 길이를 제한하는 것만으로도 같은 문단이 답답하고 거부감 드는 느낌에서 편안하고 읽기 좋은 느낌으로 바뀝니다. 이건 단순한 꾸미기가 아닙니다. 바로 타이포그래피, 즉 글이 얼마나 읽기 편한지를 결정하는 몇 가지 CSS 속성들이며, 이 장에서는 매일 마주하게 될 속성들을 하나씩 살펴봅니다.

서체 선택하기

폰트를 지정하는 속성은 font-family이고, 여기에는 하나의 폰트가 아니라 목록을 넘겨줍니다. 이 목록을 **폰트 스택(font stack)**이라고 부르는데, 브라우저는 목록의 첫 번째 폰트를 시도하고, 그 폰트를 쓸 수 없으면 다음 폰트로, 그다음 폰트로 차례차례 넘어갑니다.

css
body {
  font-family: "Helvetica Neue", Arial, sans-serif;  /* Helvetica를 먼저 시도하고, 없으면 Arial, 그다음 아무 sans-serif */
}

목록의 마지막 이름은 항상 sans-serifserif 같은 제네릭 계열(generic family)이어야 합니다. 이것이 일종의 안전망이 되어줍니다. 지정한 폰트 중 어느 것도 사용자 기기에 없더라도, 브라우저가 임의로 고른 기본값이 아니라 그래도 무난한 폰트를 보여주게 됩니다. 이름에 공백이 있는 폰트는 따옴표로 감싸야 하고, 한 단어짜리 이름은 그럴 필요가 없습니다.

font-family는 쉼표로 구분한 **폰트 스택(font stack)**을 받고, 브라우저는 목록에서 실제로 렌더링할 수 있는 첫 번째 폰트를 사용합니다. 각 이름은 앞의 이름이 없을 때를 대비한 대체 폰트이며, 목록은 항상 제네릭 계열(sans-serif, serif, monospace)로 끝나야 최종 답이 보장됩니다.

css
body {
  font-family: "Inter", "Helvetica Neue", Arial, sans-serif;
}

지정할 폰트에는 크게 두 가지 선택지가 있습니다. 시스템 폰트 스택은 각 운영체제의 기본 인터페이스 폰트를 나열해서, 페이지가 사용자 기기에 이미 있는 폰트를 그대로 빌려 씁니다. 다운로드 비용이 전혀 들지 않고 네이티브 느낌이 나기 때문에 많은 앱이 이 방식을 씁니다.

css
body {
  font-family: -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
}

다른 선택지는 웹 폰트입니다. 폰트 파일을 불러와서 모든 독자가 같은 서체를 보게 만드는 방식이죠. Google Fonts 같은 호스팅 서비스에서 링크로 가져오거나, @font-face로 직접 호스팅할 수 있습니다. 이렇게 하면 디자인을 완전히 통제할 수 있지만, 대신 독자가 다운로드를 기다려야 하는 비용이 따릅니다.

font-family는 **폰트 스택(font stack)**을 왼쪽부터 순서대로 확인해서, 브라우저가 렌더링할 수 있는 첫 번째 계열을 선택합니다. 그래서 목록은 확실한 최후의 수단으로 제네릭 계열(sans-serif, serif, monospace)로 끝나야 합니다. 어떤 이름을 고르느냐에는 두 가지 전략이 있고, 이 둘은 서로 다른 것을 맞바꿉니다.

시스템 폰트 스택은 각 플랫폼의 네이티브 UI 폰트를 나열해서, 페이지가 운영체제가 이미 제공하는 서체를 그대로 물려받습니다. 다운로드가 전혀 없으니 로딩 지연도 없고 레이아웃 시프트도 없으며, 모든 기기에서 텍스트가 네이티브하게 보입니다. 대신 플랫폼마다 페이지가 조금씩 다르게 보이는데, 앱 같은 인터페이스에는 괜찮지만 하나의 일관된 서체가 필요한 브랜드에는 맞지 않습니다.

css
body {
  /* 현대적인 시스템 스택: San Francisco, Segoe UI, Roboto, 그다음 대체 폰트들 */
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
}

웹 폰트는 브라우저가 다운로드하는 폰트 파일로, 모든 독자가 같은 서체를 보게 해줍니다. 호스팅 서비스에서 링크로 가져오거나, 계열 이름을 파일에 매핑하는 @font-face 규칙으로 직접 호스팅할 수 있습니다. 직접 호스팅하면 폰트가 자신의 오리진에 남아 있으니 서드파티 요청을 피할 수 있고, 캐싱과 font-display 동작을 통제할 수 있습니다. font-display는 폰트가 로드되는 동안 대체 폰트로 텍스트를 보여줄지를 결정하는 속성입니다.

css
@font-face {
  font-family: "Satoshi";
  src: url("/fonts/satoshi.woff2") format("woff2");
  font-weight: 400 700;         /* 하나의 가변 파일이 여러 굵기 범위를 담당 */
  font-display: swap;           /* 즉시 대체 텍스트를 보여주고, 로드되면 교체 */
}

body {
  font-family: "Satoshi", system-ui, sans-serif;  /* 지정한 웹 폰트, 그다음 네이티브 대체 폰트 */
}

웹 폰트를 쓸 때도 대체 폰트가 여전히 중요한 이유는, 다운로드가 느리거나 실패할 수 있기 때문입니다. 그럴 때 font-display: swap이 그 사이에 대체 계열을 렌더링해줍니다. 웹 폰트와 비슷한 크기 비율을 가진 대체 폰트를 고르면 교체될 때 레이아웃이 덜컹거리지 않습니다.

Juno서체 선택하기font-family는 폰트 하나가 아니라 목록을 받고, 브라우저는 그중 찾을 수 있는 첫 번째 폰트를 사용합니다. 안전한 대체 폰트가 있도록 목록은 항상 sans-serif 같은 제네릭 계열로 끝내세요. 공백이 들어간 폰트 이름은 따옴표로 감싸주세요.
Juno서체 선택하기 폰트 스택은 제네릭 계열로 끝나는 대체 목록이고, 브라우저는 렌더링할 수 있는 첫 번째 폰트를 사용합니다. 시스템 폰트 스택은 다운로드 없이 기기에 이미 있는 폰트를 공짜로 빌려 쓰고, 웹 폰트는 파일을 로드해서 모두가 같은 서체를 보게 합니다. 앱 같은 작업에는 시스템 스택을, 일관된 룩이 필요할 때는 웹 폰트를 선택하세요.
Juno서체 선택하기 스택은 왼쪽부터 순서대로 확인되고 반드시 제네릭 계열로 끝나야 하므로, 독자는 항상 텍스트를 볼 수 있습니다. 시스템 스택은 비용이 없고 레이아웃도 흔들리지 않지만 플랫폼마다 다르게 보이고, 웹 폰트는 일관된 서체를 주는 대신 다운로드 비용이 들어서 font-display: swap과 잘 맞는 대체 폰트로 보완해야 합니다. 캐싱을 통제하고 서드파티 요청을 없애고 싶다면 @font-face로 직접 호스팅하세요.

텍스트 크기 정하기

텍스트 크기는 font-size로 지정합니다. 픽셀 값을 줄 수도 있지만, 실제로 사용해야 할 단위는 **rem**입니다. 이 단위는 페이지의 기본 폰트 크기에 연결되어 있습니다. 1rem은 브라우저의 기본 텍스트 크기와 같은데, 보통 16px이므로 1rem은 일반적인 읽기 크기이고 1.25rem은 그보다 조금 큰 크기가 됩니다.

css
body {
  font-size: 1rem;             /* 기본 읽기 크기, 보통 16px */
}
h1 {
  font-size: 2rem;             /* 기본 크기의 두 배 */
}

font-size는 텍스트 크기를 정하는데, 본문 텍스트라면 px보다는 **rem**으로 지정해야 합니다. 1rem은 루트 요소의 폰트 크기이며, 기본값은 16px이지만 독자가 브라우저 설정에서 바꿀 수 있는 값입니다. rem으로 크기를 정하면 텍스트가 그 설정에 맞춰 함께 늘어나고, px로 정하면 크기가 고정됩니다.

css
:root {
  font-size: 100%;             /* 독자의 기본값을 존중하며, 보통 16px */
}
p {
  font-size: 1rem;             /* 독자가 기본값을 바꾸면 함께 스케일된다 */
}

본문 텍스트는 px가 아니라 rem으로 크기를 정해서 독자가 선택한 크기를 존중하세요. 크기 단위 장에서는 rem, em, 백분율, 뷰포트 단위가 어떻게 계산되는지 자세히 다룹니다. 타이포그래피에서 짧게 정리하면, rem은 예측 가능한 계산으로 확장 가능하고 접근성을 지키는 텍스트를 만들어준다는 점입니다.

font-size는 여러 단위를 받지만, 본문 텍스트라면 선택은 결국 접근성 문제로 귀결됩니다. rem(root em)은 루트 요소(<html>)의 font-size에 대한 상대값인데, 이 기본값은 독자가 브라우저에서 설정한 값이며 보통 16px이지만 자유롭게 바꿀 수 있습니다. 픽셀 값은 이 설정을 무시합니다. 편의를 위해서든 시각적 장애 때문이든 기본 텍스트 크기를 키운 독자에게는 rem 크기의 텍스트는 함께 커지지만 px 크기의 텍스트는 그대로 머물러 있습니다. 즉 px로 정한 본문은 독자가 일부러 선택한 접근성 설정을 조용히 무시해버립니다.

css
:root {
  /* 루트는 독자의 기본값 그대로 두세요. px로 16px에 고정하지 마세요 */
  font-size: 100%;
}

p {
  font-size: 1rem;             /* 1rem = 독자의 루트 크기, 그것과 함께 스케일된다 */
}

.lead {
  font-size: 1.125rem;         /* 16px 루트에서 18px, 여전히 스케일된다 */
}

font-size에는 em보다 rem을 선호하는 게 좋은데, 그 이유는 em부모의 폰트 크기에 대한 상대값이라서 중첩될 때 값이 누적되기 때문입니다. em 크기 요소가 또 다른 em 크기 요소 안에 있으면 값이 곱해지고, 세 겹으로 중첩된 목록은 예상치 못하게 작아지거나 커질 수 있습니다. rem은 항상 하나의 루트 값을 참조하므로, 요소가 얼마나 깊이 있든 예측 가능하게 유지됩니다. 참고로 이건 페이지 확대(줌)와는 다른 문제입니다. 줌은 px를 포함한 모든 것을 함께 확대하지만, rem이 보호해주는 상황은 독자가 기본 폰트 크기를 구체적으로 올리는 경우입니다. 이런 설정을 바꾸는 사람이 많고, px 텍스트는 이를 무시해버립니다.

Juno텍스트 크기 정하기font-size는 텍스트가 얼마나 큰지를 정하고, rem이 그때 사용할 단위입니다. 1rem은 브라우저의 일반적인 텍스트 크기이므로 1rem은 보통 크기, 2rem은 두 배 크기입니다. 본문 텍스트를 px로 정하는 건 피하세요. 다음 레벨에서 그 이유를 더 자세히 다룹니다.
Juno텍스트 크기 정하기 본문 텍스트는 px가 아니라 rem으로 크기를 정하세요. 1rem은 독자의 루트 폰트 크기이므로, rem으로 정한 텍스트는 독자가 기본값을 바꾸면 함께 스케일되고 px로 정한 텍스트는 그대로 고정됩니다. 크기 단위 장에서 계산 방식을 다루지만, 타이포그래피 규칙은 간단합니다. 사람이 읽는 것이라면 rem을 쓰세요.
Juno텍스트 크기 정하기rem은 독자가 조절하는 루트 폰트 크기를 따라가므로, px로 정한 본문 텍스트는 독자가 일부러 선택한 접근성 설정을 조용히 무시해버립니다. em보다도 rem을 선택하세요. em은 부모에 대한 상대값이라 요소가 중첩될 때 값이 누적됩니다. 이건 독자의 기본 텍스트 크기에 관한 문제로, 페이지 줌과는 별개입니다.

굵기와 스타일

글자의 모양을 바꾸는 속성은 두 가지입니다. font-weight는 텍스트가 얼마나 굵은지를 정하고, font-style은 **이탤릭(italics)**을 켭니다.

css
strong {
  font-weight: bold;           /* 더 무겁고 두꺼운 획 */
}
em {
  font-style: italic;          /* 기울임 */
}

boldnormal은 일상적으로 쓰는 굵기 키워드입니다. 이탤릭의 경우 italic은 텍스트를 기울이고 normal은 그대로 세워둡니다.

font-weight는 텍스트가 얼마나 무거운지를 정하는데, normalbold가 익숙한 키워드이긴 하지만 실제로는 100부터 900까지 100 단위로 **숫자 굵기**를 받습니다. 400normal에 대응하고, 700bold에 대응합니다. 이 숫자가 중요한 이유는 많은 폰트가 키워드로는 닿을 수 없는 추가 굵기들을 제공하기 때문입니다.

css
h1 {
  font-weight: 700;            /* bold와 같음 */
}
.caption {
  font-weight: 300;            /* 가벼운 굵기, 이에 대응하는 키워드는 없음 */
}

font-style: italic은 폰트에 진짜 이탤릭 디자인이 있을 경우 그것을 보여주는데, 이는 기계적으로 기울인 게 아니라 별도로 그려진 사선형 서체입니다. 큰 블록 전체를 이탤릭으로 꾸미기보다는 진짜 강조나 책 제목 같은 관례에만 아껴서 사용하세요. 이탤릭은 글을 읽기 더 어렵게 만듭니다.

font-weight100부터 900까지의 **숫자 굵기**를 받습니다. normal400의 별칭이고 bold700의 별칭입니다. 하지만 숫자가 별개의 굵기로 실제로 나타나는 건 폰트가 그 굵기를 실제로 담고 있을 때뿐입니다. 400700만 제공하는 폰트에 600을 요청하면, 브라우저는 실제로 있는 굵기로 반올림하거나 획을 두껍게 만들어 가짜 볼드를 합성하는데, 이는 원래 디자인된 굵기보다 못하게 보입니다. 그러니 사용할 수 있는 굵기는 여러분이 로드한 것에 따라 달라집니다. 두 가지 굵기만 링크한 웹 폰트라면 어떤 숫자를 써도 결과는 두 가지뿐입니다.

css
h1 {
  font-weight: 800;            /* 폰트에 800 서체가 있을 때만 별개로 나타남 */
}
p {
  font-weight: 400;
}

font-style: italic은 폰트에 그려진 이탤릭 서체를 선택하는데, 이는 기계적인 기울임이 아니라 글자 모양 자체가 다른 별도의 디자인입니다. 이탤릭 서체가 없는 경우 브라우저는 세워진 서체를 기울여 가짜로 만들어내는데, 이를 합성 이탤릭(synthetic italic)이라 하며 저렴해 보이는 결과를 만듭니다. oblique라는 것도 있는데 이는 세워진 디자인을 진짜로 기울인 것이지만, 본문 글에는 italic을 써야 합니다. 폰트에 제대로 그려진 서체가 있으면 그것을 선택하기 때문입니다.

Juno굵기와 스타일font-weight는 텍스트를 더 굵거나 가늘게 만들고, font-style: italic은 텍스트를 기울입니다. boldnormal 키워드만으로도 일상적인 필요는 대부분 해결됩니다. 이탤릭은 전체 문단이 아니라 강조에만 사용하세요. 전체에 쓰면 읽기 어려워집니다.
Juno굵기와 스타일font-weight는 실제로는 100부터 900까지 있고, 400이 normal, 700이 bold이며, 숫자를 쓰면 키워드로는 이름 붙일 수 없는 굵기까지 사용할 수 있습니다. 폰트가 실제로 제공하는 굵기만 보이며, 나머지는 가짜로 만들어지거나 반올림됩니다. italic은 긴 문장이 아니라 강조나 제목에 한정해서 사용하세요.
Juno굵기와 스타일 숫자 굵기는 100부터 900까지 있지만, 폰트가 그 서체를 실제로 담고 있어야만 제대로 표현됩니다. 그렇지 않으면 브라우저가 반올림하거나 더 못해 보이는 가짜 볼드를 합성합니다. 그래서 두 굵기만 로드한 웹 폰트라면 무엇을 입력해도 결과는 두 가지뿐입니다. italic은 이탤릭 서체가 있으면 그것을 선택하고, 없으면 합성된 기울임으로 대체됩니다.

텍스트를 읽기 좋게 만드는 간격

편안한 텍스트는 대부분 간격에서 나옵니다. line-height는 줄 사이의 간격을 조절하고, 여기에 여유를 조금만 줘도 문단을 훨씬 읽기 편하게 만들 수 있습니다.

css
p {
  line-height: 1.5;            /* 폰트 크기의 1.5배 */
}

1.5처럼 단위 없는 순수한 숫자를 사용하세요. 이는 "폰트 크기의 1.5배"라는 뜻이므로, 텍스트가 커지면 간격도 함께 커집니다. 답답한 줄 간격은 페이지가 읽기 어렵게 느껴지는 가장 흔한 원인 중 하나인데, 이 값 하나로 대부분 해결됩니다.

읽기 좋은 텍스트를 만드는 일은 대부분 세 가지 속성이 담당합니다. line-height는 줄 사이의 세로 간격을 정하는데, 1.5처럼 **단위 없는 값**을 줘야 하고, 이는 요소의 폰트 크기의 1.5배라는 뜻입니다. letter-spacing은 글자 사이의 간격을 조절하는데, 대문자 제목에 소량 사용하면 유용합니다. 그리고 한 줄의 길이도 이 둘만큼이나 중요합니다. 아주 긴 줄은 읽기에 지치므로 max-width로 줄의 길이를 제한합니다.

css
p {
  line-height: 1.5;            /* 단위 없음: 폰트 크기와 함께 스케일됨 */
  max-width: 65ch;             /* 측정값을 약 65자로 제한 */
}
.eyebrow {
  text-transform: uppercase;
  letter-spacing: 0.05em;      /* 대문자가 붐비지 않도록 살짝 벌림 */
}

ch 단위는 "0" 글자의 너비이므로, 65ch는 대략 65자 너비가 됩니다. 편안한 측정값(measure), 즉 한 줄당 글자 수는 대략 45에서 75 사이인데, 이를 제한하는 것은 여러분이 할 수 있는 가장 효과적인 타이포그래피 작업 중 하나입니다.

가독성은 결국 세 가지 조절 요소로 귀결됩니다. 줄 높이, 글자 간격, 그리고 줄 길이입니다. line-height단위가 없어야(1.5, 24px가 아니라) 하는데, 그 이유는 상속(inheritance) 방식 때문입니다. 단위 없는 줄 높이는 비율로 상속되므로, 각 자손 요소는 이를 자신의 폰트 크기에 곱해서 요소마다 비례적인 간격을 갖게 됩니다. 단위가 있는 줄 높이는 계산된 길이로 상속되므로, 더 큰 폰트 크기를 가진 자식 요소는 부모의 고정된 줄 상자를 물려받아 줄들이 겹치게 됩니다.

css
body {
  line-height: 1.5;            /* 비율로 상속됨: 모든 요소가 이를 스케일함 */
}

h1 {
  font-size: 2.5rem;
  /* 1.5를 상속받아 1.5 x 2.5rem으로 계산됨; 고정된 24px 줄 높이였다면 여기서 잘렸을 것 */
}

.article {
  max-width: 65ch;             /* 약 65자의 측정값 */
  text-wrap: balance;          /* 선택 사항: 제목의 들쭉날쭉한 줄을 고르게 함 */
}

letter-spacing(트래킹)은 본문 텍스트라면 폰트의 기본값 그대로 두는 것이 최선입니다. 디자이너가 이미 이를 튜닝해 두었기 때문이죠. 작은 양의 양수값은 그렇지 않으면 붐비게 될 대문자나 스몰캡스 텍스트에 도움이 되고, 아주 작은 음수값은 큰 디스플레이 제목을 조금 더 조밀하게 만들 수 있습니다. 줄 길이는 측정값, 즉 한 줄당 글자 수를 뜻하고, 편안한 범위는 대략 45에서 75자입니다. 이를 max-widthch("0" 글리프의 진행 너비) 단위로 지정하면 제한값이 폰트에 맞춰 따라가고, 이 효과는 거의 어떤 폰트 선택보다도 읽기 편안함에 큰 영향을 줍니다.

Juno텍스트를 읽기 좋게 만드는 간격line-height는 줄 사이의 간격을 정하고, 1.5 정도의 값을 주면 텍스트가 훨씬 읽기 쉬워집니다. 단위 없는 순수한 숫자로 써서 텍스트와 함께 간격이 커지게 하세요. 답답한 줄 간격은 페이지가 읽기 어렵게 느껴지는 대표적인 원인인데, 이걸로 대부분 해결됩니다.
Juno텍스트를 읽기 좋게 만드는 간격line-height1.5 같은 단위 없는 값을 줘서 각 요소의 폰트 크기와 함께 스케일되게 하세요. 줄 길이는 max-widthch로 지정해서 45에서 75자 정도로 제한하면 가장 효과적인 가독성 개선 중 하나가 됩니다. letter-spacing은 아껴서 사용하고, 주로 대문자 제목을 조금 넓힐 때만 쓰세요.
Juno텍스트를 읽기 좋게 만드는 간격line-height는 단위 없이 두어서 비율로 상속되고 요소마다 스케일되게 하세요. 단위가 있으면 계산된 길이가 상속되어 큰 제목들이 서로 겹치게 됩니다. 본문 텍스트에는 letter-spacing을 건드리지 말고, 대문자나 큰 디스플레이 타이프에만 살짝 조정하세요. max-widthch로 지정해 측정값을 45에서 75자 정도로 제한하면, 대부분의 폰트 선택보다 가독성에 더 큰 효과를 냅니다.

정렬과 장식

정렬과 마무리 작업은 세 가지 속성이 담당합니다. text-align은 텍스트를 왼쪽, 오른쪽, 또는 가운데로 옮깁니다. text-transform은 대소문자를 바꾸는데, 예를 들어 텍스트를 전부 대문자로 만들 수 있습니다. 그리고 text-decoration은 밑줄 같은 줄을 추가하거나 제거합니다.

css
h1 {
  text-align: center;          /* 제목을 가운데로 */
}
.button {
  text-transform: uppercase;   /* 전부 대문자로 표시 */
  text-decoration: none;       /* 링크 밑줄 제거 */
}

text-transform: uppercase는 다시 입력할 필요 없이 텍스트를 대문자로 보여주므로, 원래 내용은 여전히 평범한 단어로 남아 있습니다. 밑줄은 text-decoration으로 추가하거나 제거합니다.

text-align은 인라인 텍스트를 상자 안에서 배치합니다(left, right, center, justify). text-transform은 화면에 보이는 대소문자를 바꾸지만(uppercase, lowercase, capitalize) 실제 텍스트는 바꾸지 않으므로, 화면 낭독기는 여전히 실제 단어를 읽고 HTML은 깨끗하게 유지됩니다. text-decoration은 밑줄, 위줄, 취소선을 조절합니다.

css
.card-title {
  text-align: center;
}
.nav-link {
  text-decoration: none;              /* 기본 밑줄 제거 */
}
.price--old {
  text-decoration: line-through;      /* 취소선이 그려진 옛 가격 */
}

지켜볼 만한 습관이 두 가지 있습니다. 웹 본문 텍스트에는 text-align: justify를 피하세요. 세밀한 하이픈 처리 없이는 단어 사이에 보기 흉한 공백의 물줄기가 생기기 때문입니다. 그리고 링크의 밑줄을 없앨 때는 색상 같은 다른 신호가 여전히 그것이 링크임을 표시해주는지 확인하세요. 그러지 않으면 클릭 가능하다는 사실을 숨겨버리게 됩니다. 색상과 배경 장에서 링크에 눈에 띄고 접근성 있는 색을 주는 방법을 다룹니다.

text-align은 콘텐츠가 속한 컨테이너 안에서의 인라인 정렬을 정합니다. 웹 본문 텍스트에는 justify를 쓰지 마세요. 브라우저는 단어 사이 간격을 늘려서 정렬하는데, 인쇄 조판사가 갖고 있는 하이픈 처리나 줄바꿈 제어 능력이 없기 때문에 공백의 물줄기가 생기고, 깔끔해 보이는 가장자리가 주는 이점보다 가독성 손실이 더 큽니다.

text-transform(uppercase, lowercase, capitalize)은 렌더링된 대소문자만 바꾸고 원본 텍스트는 그대로 두므로, 접근성 트리와 마크업은 실제 대소문자를 유지합니다. 이것이 전부 대문자로 보여주는 올바른 방법입니다. HTML에 직접 대문자를 입력하는 대신 CSS에서 변환하면, 보조 기술이 단어를 한 글자씩 읽어버리는 일이 없고 콘텐츠도 평범한 글로 편집 가능하게 유지됩니다. 대문자로 바꿀 때는 약간의 양수 letter-spacing을 함께 주세요. 본문의 기본 트래킹 그대로 대문자를 쓰면 답답해 보입니다.

text-decoration은 선, 스타일, 색상, 두께를 한꺼번에 지정하는 축약형(text-decoration: underline wavy crimson 2px)이며, text-decoration-color, text-underline-offset 같은 개별 속성으로 더 세밀하게 조절할 수 있습니다. 흔한 사례는 링크에 text-decoration: none을 주는 것인데, 이때 함께 지켜야 할 규칙은 다른 눈에 보이는 신호를 남겨두는 것입니다. 밑줄을 없애면 텍스트가 링크라는 걸 알려주는 주된 신호를 지워버리기 때문입니다.

css
.headline {
  text-transform: uppercase;
  letter-spacing: 0.04em;             /* 대문자는 숨 쉴 공간이 필요함 */
}

a {
  text-decoration-color: currentColor;
  text-underline-offset: 0.15em;      /* 밑줄을 베이스라인에서 살짝 떼어냄 */
}

text-align, text-transform, line-height는 상속되므로, 컨테이너에 지정하면 안의 텍스트로 흘러갑니다. 선택자 장에서는 이 속성을 지정할 알맞은 컨테이너를 지정하는 방법을 다룹니다.

Juno정렬과 장식text-align은 텍스트를 왼쪽, 오른쪽, 가운데로 옮기고, text-transform: uppercase는 대문자로 보여주고, text-decoration은 밑줄 같은 줄을 추가하거나 제거합니다. CSS로 대문자를 만들면 실제 텍스트는 평범한 단어로 남아 있어서 다시 입력할 필요가 없습니다. 링크의 밑줄을 없애고 싶을 때는 text-decoration: none을 사용하세요.
Juno정렬과 장식text-align은 인라인 텍스트를 배치하고, text-transform은 화면에 보이는 대소문자만 바꾸며, text-decoration은 밑줄과 취소선을 다룹니다. 웹에서는 justify를 피하세요. 단어 사이에 보기 흉한 공백이 생깁니다. 링크의 밑줄을 없앤다면 색상 같은 다른 신호를 남겨서 클릭 가능하다는 걸 알아볼 수 있게 하세요.
Juno정렬과 장식 웹 본문 텍스트에는 justify를 피하세요. 브라우저가 단어 간격을 늘려서 공백의 물줄기를 만듭니다. 대문자는 직접 입력하지 말고 text-transform으로 처리해서 보조 기술이 실제 단어를 읽고 소스가 깨끗하게 유지되도록 하고, 대문자에는 letter-spacing을 조금 더해주세요. 링크에 text-decoration: none을 줄 때는 다른 신호를 남겨서 여전히 링크로 보이게 하세요.

font 축약형과 상속

폰트 속성에는 편리한 특성이 있습니다. 아래로 전달된다는 점이죠. <body>font-family를 지정하면 그 안의 모든 문단, 제목, 링크가 이를 물려받으므로, 같은 걸 반복해서 쓸 일이 거의 없습니다.

css
body {
  font-family: system-ui, sans-serif;  /* 안의 모든 요소가 이를 물려받음 */
  line-height: 1.5;
}

이 덕분에 타이포그래피 설정 대부분은 스타일시트 위쪽 한 곳에 모여 있고, 각 요소는 달라야 할 부분만 재정의합니다.

폰트 속성은 **상속**됩니다. font-family, font-size, font-weight, font-style, line-height, 그리고 색상은 재정의되지 않는 한 요소에서 그 자손으로 전달됩니다. 그래서 body에 기본 타입을 한 번만 설정하고 아래로 흘러가게 두는 것인데, 이 내용은 CSS 동작 방식 장에서 자세히 다룹니다.

여러 속성을 하나의 선언으로 묶는 font 축약형도 있는데, 쓰기 전에 알아둘 만한 함정이 있습니다.

css
body {
  font: 1rem/1.5 system-ui, sans-serif;   /* 크기/줄높이 계열 */
}

순서는 고정되어 있고 font-sizefont-family는 둘 다 필수입니다. line-height는 크기 뒤에 슬래시로 붙입니다. 축약형이기 때문에, 빠뜨린 폰트 속성은 초기값으로 재설정되는데, 이는 다른 곳에서 지정한 font-weight를 지워버릴 수도 있습니다.

폰트 속성은 트리를 따라 **상속**되므로, 컨테이너에 지정한 font-family, font-size, font-weight, font-style, line-height는 어떤 요소가 재정의하기 전까지 그 안의 모든 것에 적용됩니다. body에 기본 타입을 한 번 설정하고 선택적으로 재정의하는 것이 관용적인 패턴입니다. CSS 동작 방식 장에서는 상속과 캐스케이드가 최종값을 어떻게 결정하는지 자세히 다룹니다.

font 축약형은 이 속성들 여러 개를 한꺼번에 설정하는데, 여기에는 정말로 조심해야 할 함정이 있습니다. 축약형이기 때문에, 설정할 수 있지만 여러분이 생략한 각 개별 속성은 초기값으로 재설정됩니다. font: 1rem/1.5 system-ui라고 쓰면 이전에 지정했던 font-weight, font-style, font-variant는 조용히 normal로 되돌아갑니다. 문법에는 고정된 순서와 두 개의 필수 요소, font-sizefont-family가 있으며, line-height는 슬래시로 크기에 붙는 선택 사항입니다.

css
.callout {
  font: italic 700 1rem/1.5 system-ui, sans-serif;  /* 스타일 굵기 크기/줄높이 계열 */
}

조금 더 고급 내용 두 가지가 있습니다. 최신 *가변 폰트(variable fonts)*는 연속적인 굵기 범위(그리고 때로는 너비와 기울임까지)를 하나의 파일에 담고 있어서, 폰트가 그 축을 지원한다면 font-weight: 550이 반올림된 값이 아니라 실제로 그려진 값이 될 수 있습니다. 그리고 크기 섹션에서 나온 접근성 규칙은 이 모든 내용에 그대로 적용됩니다. 크기는 rem으로, 줄 높이는 단위 없이 유지해서, 독자가 기본 폰트 크기를 조정하거나 페이지를 확대할 때 텍스트를 고정된 픽셀 격자에 못 박는 대신 전체 타입 시스템이 함께 스케일되도록 하세요.

Junofont 축약형과 상속 폰트 설정은 안에 있는 요소들로 전달되므로, bodyfont-family를 한 번만 지정하면 모두가 이를 물려받습니다. 그러면 타이포그래피 설정이 스타일시트 위쪽 한곳에 모여 있게 됩니다. 각 요소는 달라야 할 부분만 재정의합니다.
Junofont 축약형과 상속 폰트 속성은 상속되므로, body에 지정한 기본 타입이 아래로 흘러가고 다른 부분만 재정의하면 됩니다. font 축약형은 크기, 줄 높이, 계열을 한꺼번에 묶어주지만, 조심할 점이 있습니다. 빠뜨린 항목은 초기값으로 재설정되어 다른 곳에서 지정한 굵기를 지워버릴 수 있습니다. 순서는 고정되어 있고 크기와 계열은 필수입니다.
Junofont 축약형과 상속 폰트 속성은 상속되므로, body에 기본 타입을 설정하고 선택적으로 재정의하세요. font 축약형은 생략한 모든 개별 속성을 초기값으로 재설정하므로, 이전에 지정한 굵기나 스타일을 조용히 지워버릴 수 있습니다. 이 점을 알고 사용하세요. 크기는 rem으로, 줄 높이는 단위 없이 유지해서 독자의 기본 크기 설정과 줌에 맞춰 타입이 스케일되게 하고, 하나의 파일에서 연속적인 굵기 범위가 필요할 때는 가변 폰트를 활용하세요.