정확한 텍스트 정렬

웹 기능: text-box

문제

브라우저는 어센더 및 디센더와 같은 글꼴별 측정항목과 줄 높이를 수용하기 위해 텍스트 문자 위와 아래에 공백을 자동으로 추가합니다. 이 '고스트 공간'으로 인해 표준 CSS를 사용하여 완벽한 세로 정렬을 구현할 수 없습니다.

일반적인 문제는 다음과 같습니다.

  • 정렬되지 않은 아이콘: align-items: center를 사용해도 텍스트가 인접한 아이콘보다 시각적으로 낮거나 높게 표시됩니다.
  • 부정확한 패딩: padding: 12px가 있는 버튼은 글꼴의 내부 행간으로 인해 시각적으로 상단 또는 하단에 더 많은 공간이 있는 것처럼 보입니다.
  • 정렬 플러시: '매직 넘버' 음수 여백을 사용하지 않으면 대문자의 상단을 컨테이너 또는 인접한 이미지의 상단과 정확하게 정렬할 수 없습니다.

해결 방법

text-box-trim 및 text-box-edge 속성 (약식 text-box)을 사용하면 특정 글꼴 측정항목을 기반으로 이 내부 선행을 자를 수 있습니다. 텍스트 상자를 cap-height (대문자 상단) 및 alphabetic baseline (대부분의 문자 하단)으로 자르면 요소의 경계 상자가 시각적 콘텐츠와 일치하도록 할 수 있습니다.

구현 전략

  1. 필수: 텍스트가 포함된 요소에 text-box-trim: trim-both (또는 text-box 약식)를 적용합니다.
  2. 필수: text-box-edge을 사용하여 자르기에 사용할 측정항목을 지정합니다. 대부분의 UI 정렬에는 cap alphabetic를 사용합니다.
  3. 권장사항: 플렉스 또는 그리드 컨테이너에서 시각적 세로 중앙 정렬을 위해 이 속성을 사용합니다.
  4. 권장사항: CSS padding 값이 텍스트와 컨테이너 가장자리 사이의 시각적 간격과 일치하도록 하는 데 사용합니다.
  5. 가독성을 위해 기존 줄 간격이 필요한 긴 본문 텍스트에는 사용하지 마세요. 제목, 버튼, UI 라벨에 가장 적합합니다.

구현 가이드

사용 사례 1: 배지의 내부 선행 자르기

글꼴마다 텍스트 위아래에 기본 제공되는 간격이 다릅니다. 이로 인해 디자인을 일치시키거나 배지에서 텍스트를 시각적으로 중앙에 배치하는 데 어려움이 있을 수 있습니다. 컨테이너의 패딩이 텍스트를 정확하게 감싸도록 하려면 text-box: trim-both cap alphabetic를 사용합니다. 이는 배지나 태그와 같은 밀집된 UI 구성요소에 특히 유용합니다. 이렇게 하면 패딩이 모든 면의 텍스트 가장자리에서 바로 시작됩니다.

.badge {
  padding: 10px;
  background: hotpink;
  border-radius: 10px;
  /* 
    Trims the top to the cap-height and 
    the bottom to the alphabetic baseline.
  */
  text-box: trim-both cap alphabetic;
}

사용 사례 2: 아이콘이 있는 텍스트 중앙 정렬

Flexbox를 사용하여 텍스트와 아이콘을 정렬할 때 '고스트 공간'으로 인해 텍스트가 약간 중심에서 벗어난 것처럼 보이는 경우가 많습니다. 상자를 자르면 레이아웃 엔진이 실제 표시되는 문자 높이를 사용하여 정렬합니다.

.button {
  display: inline-flex;
  align-items: center;
  gap: 8px; 
}
/* 
  text-box does NOT inherit, and must be applied directly to the text element.
*/
.button-text{
  /* 
    The flex container now centers against the 
    visible letters, not the invisible font box.
  */
  text-box: trim-both cap alphabetic;
}

사용 사례 3: 텍스트를 위쪽 가장자리에 맞추기

제목을 인접한 이미지 또는 장식 요소의 상단과 완벽하게 정렬하려면 trim-start cap alphabetic를 사용합니다. 끝부분이 잘리지 않더라도 끝 가장자리를 정의해야 합니다.

.hero {
  display: flex;
  align-items: flex-start;
}

h1 {
  /* MANDATORY: The bottom edge must also be defined, even though only the top is trimmed. */
  text-box: trim-start cap alphabetic;
}

권장사항

  • 간결성을 위해 text-box 약어를 사용합니다(text-box: <trim-direction> <edges>).
  • 한쪽 가장자리만 자르는 경우에도 항상 양쪽 가장자리를 모두 지정해야 합니다(기본 text 가장자리를 사용하지 않는 경우).
  • line-height와 결합하여 간격을 제어합니다(권장). 자르기를 사용하면 텍스트의 첫 번째 줄과 마지막 줄 앞의 행간이 삭제되지만 line-height은 여러 줄 텍스트의 줄 간격에 여전히 영향을 미칩니다.
  • 모든 요소에 적용하지 않습니다. 정밀한 정렬이 필요한 경우에만 사용하세요.

대체 전략

text-box은 점진적 개선입니다. 이를 지원하지 않는 브라우저에서는 텍스트가 기본 행간으로 렌더링됩니다. 레이아웃은 계속 작동하지만 정밀도가 약간 떨어집니다. 이전 브라우저에서는 속성이 안전하게 무시되므로 특별한 대체 코드가 필요하지 않습니다.

기타 고려사항

  1. 글꼴 측정항목: 글꼴마다 내부 측정항목이 다릅니다. cap alphabetic는 안정적인 기본값이지만 일부 글꼴이나 사용 사례에서는 소문자 정렬을 개선하기 위해 ex (x-height)가 필요할 수 있습니다.
  2. 여러 줄 텍스트: 블록의 첫 번째 줄과 마지막 줄에 트리밍이 적용됩니다. 내부 회선은 영향을 받지 않습니다.