#15 letter by letter

submitted on by Claire

Bad code

Letters are wrapped in divs to animate each letter with JavaScript.

<h3>
<div style="display: block; text-align: start; position: relative;" class="title">
<div style="position: relative; display: inline-block; transform: rotateX(90deg); transform-origin: 50% 50% -30.8917px;" class="char">H</div>
<div style="position: relative; display: inline-block; transform: rotateX(90deg); transform-origin: 50% 50% -30.8917px;" class="char">e</div>
<div style="position: relative; display: inline-block; transform: rotateX(90deg); transform-origin: 50% 50% -30.8917px;" class="char">a</div>
<div style="position: relative; display: inline-block; transform: rotateX(90deg); transform-origin: 50% 50% -30.8917px;" class="char">d</div>
<div style="position: relative; display: inline-block; transform: rotateX(90deg); transform-origin: 50% 50% -30.8917px;" class="char">i</div>
<div style="position: relative; display: inline-block; transform: rotateX(90deg); transform-origin: 50% 50% -30.8917px;" class="char">n</div>
<div style="position: relative; display: inline-block; transform: rotateX(90deg); transform-origin: 50% 50% -30.8917px;" class="char">g</div>
</div>
</h3>

Issues and how to fix them

  1. Assistive technology may announce the word letter by letter, if each letter is wrapped in an element.

    Code for this demo
  2. Try to avoid excessive DOM sizes. Too many DOM nodes and nested DOM elements may harm your page performance.

  3. A large DOM tree results in a large accessibility tree, which may have a bad impact on the performance of assistive technology.

  4. The separation of presentation from content is advised. Move styles that don’t change dynamically into a CSS file.

Good code (Solution 1)

<h3> Heading </h3>

Good code (Solution 2)

If you really have to.
Provide an accessible version of the text for screen readers and hide the inaccessible text by using aria-hidden="true".

<h3 class="title">
<span class="sr-only">Heading</span>
<div aria-hidden="true">
<div style="transform-origin: 50% 50% -30.8917px;" class="char">H</div>
<div style="transform-origin: 50% 50% -30.8917px;" class="char">e</div>
<div style="transform-origin: 50% 50% -30.8917px;" class="char">a</div>
<div style="transform-origin: 50% 50% -30.8917px;" class="char">d</div>
<div style="transform-origin: 50% 50% -30.8917px;" class="char">i</div>
<div style="transform-origin: 50% 50% -30.8917px;" class="char">n</div>
<div style="transform-origin: 50% 50% -30.8917px;" class="char">g</div>
</div>
</h3>

Unfortunately, there’s no native way of hiding content only visually.
The .sr-only class makes sure that content is visually hidden but still accessible to screen reader users.

.title { display: block; text-align: start; position: relative; }
.char { position: relative; display: inline-block; transform: rotateX(90deg); }
.sr-only { position: absolute; white-space: nowrap; width: 1px; height: 1px; overflow: hidden; border: 0; padding: 0; clip: rect(0 0 0 0); clip-path: inset(50%); margin: -1px; }