본문 바로가기
개발 공부/Html, CSS

[CSS] 글자 사이에 구분선 넣기

by momo'sdad 2023. 10. 18.

구체적인 기능

  • 평문 ABCDA | B | C | D의 형태로 나타내기
  • 하지만 HTML 자체를 건드리지는 않기
  • 스크린리더가 ABCD를 통째로 인식할 수 있도록
  • 코드가 복잡하지 않도록
  • 구분선은 "접근 가능한 문자"가 아니었으면
  • 스크린리더가 인식하지 않도록
  • 복사했을 때, 보여지는 A | B | C | D가 아니라 원문 ABCD가 복사되도록

이러한 기능이 필요한 이유

  • 간혹 헤딩을 이러한 형태로 디자인하는 경우가 있는데
  • 시각효과일 뿐인 구분선이 텍스트 형태로 되어있는 경우가 많아서
  • 스크린리더 사용자 입장에서는 제목을 파악하기 어렵겠다는 생각이 들었고
  • 어디론가 내용을 복사해갈 때에도 불필요한 시각효과가 함께 넘어가기 때문에

방법1: aria-hidden 속성 이용

<!-- HTML -->
<p>
  A<span aria-hidden="true"> | </span>B<span aria-hidden="true"> | </span>C<span aria-hidden="true"> | </span>D
</p>
  • 해결된 부분
  • 외관상 A | B | C | D
  • NVDA에서는 "ABCD"라고 읽어줌

  • 문제점
  • 텍스트가 분리되고 코드도 복잡함
  • 코드를 줄지어 쓴 이유는 의도하지 않은 스페이스가 들어가지 않도록 하기 위함임 |가 함께 드래그되고 복사도 됨
  • 스크린리더가 읽어주지는 않는데 드래그&복사는 가능하다면 스크린리더 사용자 입장에서는 혼란을 겪을 듯

방법2: CSS의 content 이용

/* CSS */
.separator::after {
  content: " | ";
}
<!-- HTML -->
<p>
  <span class="separator">A</span><span class="separator">B</span><span class="separator">C</span>D
  <!-- 또는 -->
  A<span class="separator"></span>B<span class="separator"></span>C<span class="separator"></span>D
</p>
  • 해결된 부분
  • 외관상 A | B | C | D
  • ABCD만 복사됨

  • 문제점
  • NVDA 기준, content가 전부 읽어지고 글자탐색으로 접근도 가능함
  • 글자 사이에 다른 글자가 들어가면 원래 단어를 제대로 읽어주지 않게 됨 (예: "exit"을 "e x i t"로 읽음)

방법3: 방법1, 방법2 모두 적용

<!-- HTML -->
<p>
  A<span aria-hidden="true" class="separator"></span>B<span aria-hidden="true" class="separator"></span>C<span aria-hidden="true" class="separator"></span>D
</p>
  • 해결된 부분
  • 외관상 A | B | C | D
  • ABCD만 복사됨
  • NVDA에서는 "ABCD"라고 읽어줌 (붙어있는 단어로 인식)

  • 문제점
  • 텍스트 코드가 단순한 ABCD와는 거리가 점점 멀어짐
  • 코드 가독성이 굉장히 떨어짐
  • aria-hidden이 필요하기 때문에 각 글자를 태그 안에 넣을 수 없음

방법4: CSS의 border 활용

/* CSS */
.border-separator {
  padding-right: 0.5em;
  border-right: 1px solid #000;
  margin-right: 0.5em;
}
<!-- HTML -->
<p>
  <span class="border-separator">A</span><span class="border-separator">B</span><span class="border-separator">C</span>D
</p>
  • 전반적으로 방법3과 큰 차이 없음
  • 글자간 간격이나 구분선 굵기, 색 등 스타일을 적용하기에는 조금 더 유리함
  • 코드가 좀더 직관적

방법5: CSS의 background 활용

/* CSS */
.bg-separator {
  font-family: monospace;
  --letter-spacing: 1em;
  letter-spacing: var(letter-spacing);
  --separator-width: 3px;
  --separator-height: 80%;
  background:
    repeating-linear-gradient(
      90deg,
      #000 0 var(--separator-width),
      #0000 0 calc(1ch + var(--letter-spacing))
    )
    calc((var(--separator-width) + var(--letter-spacing)) * -0.5)
    50%/100%
    var(--separator-height)
    no-repeat;
}
<!-- HTML -->
<span class="bg-separator">ABCD</span>
  • 해결된 부분
  • 외관상 A | B | C | D
  • ABCD만 복사됨
  • NVDA에서는 "ABCD"라고 읽어줌
  • HTML 코드가 매우 단순함

  • 문제점
  • monospace font로 제한됨
  • 픽셀이 어긋나면 텍스트 맨 뒤에도 separator가 나타나기도 함
  • CSS 코드는 좀 어려운 편 (특히 background)
  • 그렇지만 스택오버플로우 답변과는 달리, 위의 코드처럼 몇몇 팩터를 변수로 처리해두면
  • 코드를 완벽하게 이해하지는 못해도 보수하는 데에 큰 어려움은 없을 듯
  • 코드의 파라미터가 많은 만큼 커스텀도 다양하게 할 수 있다는게 장점일 수 있음
  • letter-spacing 때문에 드래그 시에 각 글자의 영역이 넓게 잡힘

방법6: 이미지로 처리

  • 미리 만든 이미지를 헤딩으로 사용
  • aria-label이나 alt 속성으로 스크린리더에 정보 제공

  • 문제점
  • 변동 사항이 있을 때마다 이미지를 새로 만들어야 함
  • 텍스트로 접근이 되지 않기 때문에 복사는 물론이고 스크린리더의 글자탐색 등의 접근이 어려움

결론

  • 개인적으로는 monospace font로 제한된다는 점만 제외하면 스택오버플로우에 답변으로 달린 방법5가 가장 마음에 드는 해결법이었음
  • 하지만 상황에 따라 다른 방법이 필요할 수도 있으므로 여러 방법을 알아두면 좋을 듯함
반응형