Use the aria-live
attribute to announce a live character and word count to screen readers such as VoiceOver on macOS.
Want to learn how to build this? Join the next session of the Vanilla JS Academy ⚓️
A Pen by Kieran Barker on CodePen.
Use the aria-live
attribute to announce a live character and word count to screen readers such as VoiceOver on macOS.
Want to learn how to build this? Join the next session of the Vanilla JS Academy ⚓️
A Pen by Kieran Barker on CodePen.
<header> | |
<h1>Announcing the Count</h1> | |
<p> | |
<strong>NOTE: In CodePen, the changes sometimes get announced more than once. This does not happen when I test <em>outside</em> CodePen. I think this is because CodePen runs the demo inside an <code><iframe></code>.</strong> | |
</p> | |
</header> | |
<main> | |
<label for="text">Enter your text below.</label> | |
<textarea id="text"></textarea> | |
<p id="count" aria-live="polite">You've written 0 words and 0 characters.</p> | |
</main> | |
<footer> | |
<p>Want to learn how to build this? Join the next session of the <a href="https://vanillajsacademy.com/">Vanilla JS Academy</a> ⚓️</p> | |
</footer> |
// | |
// Variables | |
// | |
// Get the #text element | |
var text = document.querySelector("#text"); | |
// Get the #count element | |
var count = document.querySelector("#count"); | |
// | |
// Functions | |
// | |
/** | |
* Get the number of words in a text area | |
* @param {Node} textArea The text area | |
* @returns {Number} The word count | |
*/ | |
function getWordCount (textArea) { | |
// Trim whitespace from the value | |
var value = textArea.value.trim(); | |
// If it's an empty string, return zero | |
if (!value) return 0; | |
// Otherwise, return the word count | |
return value.split(/\s+/).length; | |
} | |
/** | |
* Get the number of characters in a text area | |
* @param {Node} textArea The text area | |
* @returns {Number} The character count | |
*/ | |
function getCharacterCount (textArea) { | |
return textArea.value.length; | |
} | |
/** | |
* Update the word and character counts | |
*/ | |
function updateCounts () { | |
count.textContent = ( | |
"You've written " + getWordCount(this) + " words " + | |
"and " + getCharacterCount(this) + " characters." | |
); | |
} | |
// | |
// Inits & Event Listeners | |
// | |
// Update both counts when the value of #text changes | |
text.addEventListener("input", updateCounts); |
<script src="https://polyfill.io/v3/polyfill.min.js"></script> |
* { | |
box-sizing: border-box; | |
} | |
body { | |
width: 88%; | |
max-width: 30em; | |
margin: 1em auto; | |
line-height: 1.5; | |
background-color: aliceblue; | |
font-family: "Roboto", sans-serif; | |
} | |
h1 { | |
font-weight: normal; | |
} | |
label { | |
display: block; | |
} | |
textarea { | |
width: 100%; | |
min-height: 7em; | |
padding: .5em; | |
border: .125em solid #d7d7d7; | |
border-radius: .25em; | |
background-color: white; | |
font: inherit; | |
} | |
textarea:focus { | |
outline: .125em solid #ffd346; | |
} | |
strong { | |
font-weight: bold; | |
} | |
a { | |
color: #068; | |
} | |
a:hover { | |
text-decoration: none; | |
} | |
footer { | |
border-top: .5em solid #d7d7d7; | |
margin-top: 2em; | |
} |
<link href="https://fonts.googleapis.com/css2?family=Roboto&display=swap" rel="stylesheet" /> |