🐙
「1文字ずつ表示」させただけで終わるのはエアコンつけたまま実家に帰るのと同じ【アクセシビリティ】
突然のコードサンプル
よくみるヤツに今更何を?
1文字ずつ表示する系の演出自体は頻繁に要求されるので「はいはい、アレね」くらいのテンションでやっていましたが、上記ツイートの参考サイトとして掲載されていた
↑である気づきを得ました。1文字ずつ表示させて満足したら困るユーザーがいる
大量生成されたspanが全部アクセシビリティツリーに入っちゃったらスクリーンリーダーユーザーは「エイチ オー ジー イー エフ ユー ジー エー」みたいに読み上げられて「?」状態になってしまうという、ちょっと考えたらわかることを見落としていました。大量生成されたspanにはaria-hidden="true"が指定されていなければならない...
悔い改めたコードを供養します。
ソース
思いつきで書いたので伸び代のあるコードに仕上がってると思いますがご容赦ください
HTML
<p class="text-onebyone">
<span class="for-accessibility">1文字ずつ表示させる</span>
<span class="text-split">1文字 ずつ 表示 させる</span>
</p>
SCSS
.text-onebyone {
position: relative;
.text-split {
font-size: 4rem;
clip-path: inset(0 0 0);
.text-each {
display: inline-block;
opacity: 0;
transform: translateY(100%);
&.is-active {
transition: 1s;
opacity: 1;
transform: translateY(0%);
}
}
}
.for-accessibility {
position: absolute;
width: 1px;
height: 1px;
clip: rect(0, 0, 0, 0);
}
}
JavaScript
const textOneByOne = document.querySelector(".text-split");
let getText = textOneByOne.textContent;
textOneByOne.textContent = "";
getText = getText.split("");
getText.forEach(function (elem, index) {
const newText = "<span aria-hidden='true' class='text-each'>" + elem + "</span>";
textOneByOne.insertAdjacentHTML("beforeend", newText);
});
const textEach = textOneByOne.querySelectorAll(".text-each");
const delayTime = 100; //何秒遅れで次の文字が表示されるか設定
textEach.forEach(function (elem, index) {
setTimeout(function () {
elem.style.transitionDelay = delayTime * index + "ms";
elem.classList.add("is-active");
}, delayTime);
});
おわり
引用元のツイート著者も発信していますが、隠れている部分をoverflowではなくclip-pathで実現するのがclip-pathのプチハックとして満足度が非常に高かった...
WAI-ARIAにわかなので、アクセシビリティ的に「ここ詰め甘いぞ」ってポイントあるかもしれません。誤りを流布したくないのでご指摘頂けると非常に助かります
Discussion