너비가 동일한 텍스트 줄

각 줄의 크기가 컨테이너의 전체 너비에 걸쳐 조정되는 포스터 스타일 잠금은 시각적으로 눈에 띄는 제목을 만들 수 있습니다. text-fit를 사용하면 브라우저가 레이아웃 중에 각 줄의 크기를 조절하므로 크기 조절, 복사 변경, 글꼴 로드 시에도 올바르게 유지됩니다.

컨테이너를 채우는 한 줄 (예: 제목 또는 인용구)의 경우 해당 요소에 직접 text-fit를 적용합니다. 이 가이드에서는 여러 줄 잠금을 다룹니다.

기본 구현

강제 회선의 경우:

  • <span>의 각 줄을 display: block로 래핑합니다.
  • 각 강제 줄 <span>에 white-space: nowrap를 적용합니다.

구현 가이드라인:

  • 제목 자체에 text-fit: grow per-line-all <percentage>를 사용합니다.
  • per-line가 아닌 per-line-all를 사용합니다. per-line는 마지막 줄과 강제 줄바꿈으로 끝나는 줄을 건너뛰므로 한 줄에 한 블록이 있는 경우 아무것도 조정하지 않습니다.
  • grow은(는) shrink와(과) 결합할 수 없습니다. 더 나은 대체 또는 계산이 더 쉬운 방법에 따라 기본 font-size를 최댓값 또는 최솟값으로 설정하고 이에 따라 text-fit를 shrink 또는 grow로 설정합니다. shrink를 사용할 이유가 없다면 대부분의 경우 더 안전한 grow + font-size 설정을 최소한으로 사용하는 것이 좋습니다.
  • 항상 비율 (예: 300%)을 가드레일로 사용하여 증가 또는 감소를 제한합니다.
  • 컨테이너에는 명확한 인라인 크기가 필요합니다. text-fit는 고유 크기를 변경하지 않으므로 fit-content/max-content 너비 또는 콘텐츠 크기 플렉스/그리드 항목에는 아무런 영향을 미치지 않습니다.
  • 첫 번째 줄 위와 마지막 줄 아래의 행간을 자릅니다. 정확한 텍스트 정렬을 참고하세요.
  • line-height를 작게(1 이하) 유지하세요. 그렇지 않으면 글꼴 크기가 다른 줄 사이의 간격이 다루기 어려워집니다.
  • 중요: 계산된 font-size는 변경되지 않으므로 em 간격은 조정되지 않습니다.
  • 실수로 과도하게 강조된 고아를 방지하려면 빈 줄이 있는 경우 text-wrap: balance 또는 text-wrap: pretty를 적용하세요.

간격

모든 줄이 강제되면 간격을 더 세밀하게 제어할 수 있습니다.

  • 각 줄 블록에 text-box: trim-both cap alphabetic를 적용하여 상자가 자체 글리프를 감싸도록 합니다. 확장된 측정항목을 사용하여 자릅니다. 자세한 내용은 정확한 텍스트 정렬을 참고하세요.
  • line-height가 아닌 제목에 Flexbox 또는 Grid + gap를 사용하여 줄 간격을 조정합니다. 그러면 간격이 각 줄의 글꼴 크기에 따라 커지지 않고 균일해집니다.

일부 줄이 비어 있는 경우 text-box를 사용하지 마세요. 첫 번째 줄과 마지막 줄만 자르므로 바깥쪽 줄은 글리프를 감싸고 안쪽 간격은 행간을 유지합니다. line-height에서 모든 간격을 제어하도록 합니다.

시각 디자인

  • 로고는 줄 간 글꼴 크기 차이가 클 때 가장 보기 좋습니다. 대부분 균일한 줄로 구성된 텍스트로 록업을 만들지 마세요. 글꼴 크기가 동일하지도 않고 충분히 다르지도 않아 대비의 디자인 원칙을 위반하게 됩니다. 이를 위해 짧은 줄을 강제로 적용할 수 있습니다. 즉, 강조할 단어를 블록으로 묶고 나머지는 묶지 않는 혼합형 잠금입니다. 이는 text-wrap: balance와 결합할 때 특히 중요합니다.
  • 서양 문자와 함께 사용할 때는 text-transform: uppercase와 결합하는 것이 좋습니다. 어센더와 디센더가 갇힌 공간을 만들거나 인접한 선과 겹쳐서 미적으로 좋지 않은 결과를 초래할 수 있기 때문입니다.
  • 짧은 줄을 강제로 적용할 때는 강조하면 메시지를 더 효과적으로 전달할 수 있는 단어를 선택하세요.
  • 제한사항: 텍스트가 커지면 시각적 무게감도 증가하고 획이 더 강하게 인식됩니다. 현재로서는 이를 상쇄할 방법이 없습니다.예를 들어 큰 텍스트의 font-weight를 줄이는 방법은 없습니다. 계산에 사용할 단위가 없고 크기 조정이 em와 같은 글꼴 관련 단위에 영향을 미치지 않기 때문입니다.

대체 전략

text-box용

text-box에는 별도의 대체가 필요하지 않습니다. 고정된 락업에서도 작은 line-height를 유지하세요. text-box에서는 작동하지 않으며, 지원되지 않는 경우 간격을 좁게 유지하지만 각 줄의 글꼴 크기에 따라 간격이 조정됩니다.

text-wrap: balance용

text-fit용

강제 줄에는 짧고 충실한 대체가 있습니다. 각 줄을 기본 크기로 측정하고 동일한 상한을 사용하여 컨테이너에 대한 비율로 확장합니다.

@supports not (text-fit: grow) {
  .lockup > span {
    /* Shrink-wrap each line so its width is the text width */
    width: fit-content;
    /* --text-fit-scale is measured by the script; the cap mirrors the text-fit percentage */
    font-size: min(var(--text-fit-scale, 1) * 1em, 300%);
  }
}
if (!CSS.supports('text-fit', 'grow per-line-all')) {
  const fit = lockup => {
    const lines = [...lockup.querySelectorAll(':scope > span')];
    // Unscale first: on a refit, offsetWidth would otherwise include the previous scale
    for (const line of lines) line.style.removeProperty('--text-fit-scale');
    // MANDATORY: all reads, then all writes. Interleaving them (e.g. reading
    // lockup.clientWidth inside the write loop) forces one reflow per line.
    const scales = lines.map(line => lockup.clientWidth / line.offsetWidth);
    lines.forEach((line, i) => line.style.setProperty('--text-fit-scale', scales[i]));
  };
  // Refit on resize and font load
  for (const lockup of document.querySelectorAll('.lockup')) {
    new ResizeObserver(() => fit(lockup)).observe(lockup);
  }
}

자유로운 줄에는 정확한 대체가 없습니다 (줄바꿈은 레이아웃이 결정될 때까지 알 수 없음). clamp(2rem, 1rem + 5cqi, 5rem)와 같은 유동적인 기본 크기를 가진 균형 잡힌 제목으로 점진적 개선이 이루어집니다. 혼합된 잠금에서 위의 스크립트는 여전히 강제 줄에 맞습니다. 래핑 블록은 컨테이너만큼 넓게 측정되므로 배율 1을 유지하고 유동적인 기본 크기만 가져옵니다.

텍스트 맞춤이 중요한 경우 JS 라이브러리 (예: fitty)를 사용하고 text-fit가 지원되지 않는 경우에만 조건부로 로드하는 것이 좋습니다.