tooltip은 흔하지만 그중에서도 약어에 대한 설명을 제공하는 tooltip을 어떻게 만들어볼 것인가에 대해 이야기해보겠다. 약어를 나타낼 때 abbr
요소를 사용할 수 있는데, 다음과 같이 쓸 수 있다.
1
<abbr title="HyperText Markup Language">HTML</abbr>
마우스 커서를 올렸을 때 title 속성을 통해 약어에 대한 설명을 제공해준다. 그러나 키보드 사용만으로 웹 페이지를 탐색하는 사용자의 경우 또는 마우스 이벤트가 불가능한 모바일 환경이라면? Javascript 등을 이용하여 동일한 사용자 경험을 제공해주는 게 상식에 맞다고 볼 수 있다.
방법 1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
abbr[title] {
position: relative;
cursor: help;
&:after {
content: attr(title);
display: none;
position: absolute;
top: 100%;
left: 0;
padding: 0.7em;
background: #fff;
box-shadow: rgba(0,0,0,0.2) 1px 2px 4px 0;
cursor: text;
}
&:focus:after,
&:active:after {
display: block;
}
}
See the Pen vYOJoqN by sel (@selucky) on CodePen.
abbr 요소는 title 속성없이 풀어쓸 수 있으므로1, title 속성을 가진 abbr 요소를 선택해준다. content 속성에 abbr title 속성값을 대입해주는 방법으로, JS를 활용하지 않고 CSS로만 핸들링했다는 게 특징. 하지만 IE에서 NVDA로 테스트 결과 content 속성값을 읽지 못하는 문제가 있다. 웹 접근성을 확보하고자 한다면 다음 방법을 고려해보자.
방법 2
마크업은 방법 1과 동일.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
abbr[title] {
position: relative;
border-bottom: 1px dotted #333;
text-decoration: none;
cursor: help;
}
.abbr__tooltip {
display: none;
position: absolute;
top: 100%;
left: 0;
width: auto;
height: auto;
padding: 0.7em;
background: #fff;
box-shadow: rgba(0,0,0,0.2) 1px 2px 4px 0;
cursor: text;
&--active {
display: block;
}
}
CSS는 적당히 만들어주고
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
// tooltip 생성
(function(){
const abbr = document.querySelectorAll("abbr[title]");
if (!abbr.length) return;
for (let i = 0; i < abbr.length; i++) {
const abbrSpan = document.createElement("span");
const abbr_title = "tooltip-" + encodeURI(abbr[i].title).replace(/ |%/g, "1");
abbr[i].setAttribute("tabindex", "0");
abbr[i].setAttribute("aria-describedby", abbr_title);
abbrSpan.hidden = true;
abbrSpan.setAttribute("role", "tooltip");
abbrSpan.id = abbr_title;
abbrSpan.textContent = abbr[i].title;
abbrSpan.classList.add("abbr__tooltip");
abbr[i].appendChild(abbrSpan);
}
})();
// click 이벤트
const handlerClick = (evt) => {
if (evt.target !== evt.currentTarget) return;
const abbrTooltip = evt.currentTarget.querySelector(".abbr__tooltip");
if (!abbrTooltip.classList.contains("abbr__tooltip--active")) {
abbrTooltip.hidden = false;
abbrTooltip.setAttribute("tabindex", "0");
abbrTooltip.classList.add("abbr__tooltip--active");
} else {
abbrTooltip.hidden = true;
abbrTooltip.setAttribute("tabindex", "-1");
abbrTooltip.classList.remove("abbr__tooltip--active");
}
};
// keydown 이벤트(Enter 키)
const handlerKeydown = (evt) => {
if (evt.key === "Enter") handlerClick(evt);
};
// abbr event 등록
(function() {
const abbr = document.querySelectorAll("abbr[title]");
if (!abbr.length) return;
for (let i = 0; i < abbr.length; i++) {
abbr[i].addEventListener("click", handlerClick);
abbr[i].addEventListener("keydown", handlerKeydown);
}
})();
Javascript로 다음과 같은 순서로 구현해준다.
- 모든 abbr 요소에 초점 이동 가능하게 해준다.
- 각 abbr 요소에 대한 tooltip을 생성해주고, abbr 요소의 title 속성값을
aria-describedby
속성값에 대입해준다. - 이후 tooltip 역할을 부여함과 동시에
aria-describedby
속성값을 id값에 대입, abbr과 tooltip을 연결시켜준다. - abbr 요소의 click/keydown 이벤트에 대응하는 handler를 만들어준다.
참고로 title/aria-describedby 속성값에 공백/한글이 포함되어 있을 경우 작동하지 않으므로, 공백을 문자열로 치환하고 한글도 이스케이프 문자로 치환하는 로직을 구현해야 한다.
See the Pen bGdobEo by sel (@selucky) on CodePen.
WAI-ARIA를 사용, 보조기기에서 태그의 용도를 더욱 명확하게 파악할 수 있게끔 해주었고, 결과적으로 웹 접근성 퍼포먼스가 향상되었다.
-
[1] 예)
<p>HyperText Markup Language(<abbr>HTML</abbr>)</p>
↩
Hero image from geralt