Textboxes
It may surprise a lot of people that you can make editable textboxes without JavaScript and without using
<input type="text">
or <textarea>
tags.
Why would you use the ARIA method? I can see two reasons:
- Maybe because you can't use
::before
or::after
pseudo-elements to style form elements, although there are other ways around this without using ARIA. - If you wanted to create a WYSIWYG editor, then you would have to do this, since form elements don't allow the editing of formatted text.
This last use case we do not cover since creating an accessible WYSIWYG editor would involve quite a bit of JavaScript (I will be adding a page in Enable about WYSIWYG editors in the future).
HTML example
Code Walkthrough of the Above Example
Below is the HTML of the above example. Use the dropdown to highlight each of the individual steps that make the example accessible.
ARIA example
Keep in mind that if you use this in a form, the nice free-form functionality (e.g. HTML5 validation, inclusion of data when submitting a form in an HTTP request, etc.) won't work. These examples do, however, show up in Voiceover's Rotor and NVDA's Element Dialogue.
- No JavaScript was involved in making these (you would need to use JavaScript, though, to make a true WYSIWYG editor).
- The first example is simply a
div
with itscontenteditable
attribute set to"true"
. Textareas can be simulated usingaria-multiline="true"
and using CSSresize: both
to make them resizable. - The element will not submit its data to the server like a real form field.
Code Walkthrough of the Above Example
Below is the HTML of the above example. Use the dropdown to highlight each of the individual steps that make the example accessible.
Textbox with Character Counter
A character counter is something that shows users how many characters they can type into a textbox. It is visible at all times. Our implementation has the character count information announced to screen reader users in the following scenarios:
- When the screen reader user uses the keyboard to access the textbox (e.g. by using the TAB key or swiping into the textbox on a mobile device)
- When there are 20 characters left before the textbox is filled. This value can be changed by the developer by setting the
data-warning-threshold
attribute. - When they use the keyboard to press the Escape key. This key can be changed by the developer by setting the
data-read-count-key
attribute
Note that the code walkthrough below is specific to our implemtation.
Code Walkthrough of the Above Example
Below is the HTML of the above example. Use the dropdown to highlight each of the individual steps that make the example accessible.
When data-has-character-count
is set, the character counter will be created for the textbox and ARIA regions will be appended below the textbox. These ARIA regions will not be visible to sighted users but will provide the information needed for screen readers to announce the character count:
- ARIA-describedby Region: this area will be populated when the textbox comes into focus so that screen readers can read the description (i.e. that this is a textbox with a character limit) and instructions on how to use it (i.e. use the Escape key to report how many characters have been used up).
- ARIA-live Region: this area will be updated when the textbox comes into focus as well as whenever the user presses the Escape key (i.e. the instructions outlined in point #1)
- Note: Chrome only announces the character count when there's a change to the text. In order to have Chrome announce on each key press—to align with other browsers—the JavaScript toggles between appending and removing an exclamation mark to the end of the announcement text.
The character counter can also be customized using additional data attributes. The character counter below shows the available data attributes and their default values.
Below is the HTML markup needed to add the character counter to a textarea element, as well as instructions on how to use it in your own projects.
Code Walkthrough of the Above Example
Below is the HTML of the above example. Use the dropdown to highlight each of the individual steps that make the example accessible.
Installation Instructions
You can load this JavaScript library into your application in several ways:
- as an ES6 module using Webpack.
- as a CommonJS module using
require()
and Webpack. - as a native ES6 module within the browser.
- as an old-school ES4/JavaScript library.
If you haven't done so already, choosing which you should use is a major architectural decision. Here are a few articles that will help you decide:
- Jan Olaf Krems gives a great overview of the JavaScript file format differences.
- Joe Honton discusses that with ES modules and HTTP/2, you may not need Webpack anymore
- Stack Overflow has a really good thread about Webpack vs. ES6 modules as well.
Using NPM/Webpack to load ES6 Modules:
-
Install the
enable-a11y
NPM project. -
Edit your webpack.config.json file to resolve the
~
modifier by adding the following:module.exports = { ... resolve: { extensions: ['.js', '.jsx', '.scss', '.css', '*.html'], modules: [ path.resolve('./src/js'), path.resolve('./node_modules') ], alias: { '~enable-a11y': path.resolve(__dirname, 'node_modules/enable-a11y') }, ... }, ... }
-
You can use the module like this:
// import the JS module import enableCharacterCount from '~enable-a11y/js/modules/enable-character-count'; // How to initialize the enableCharacterCount library enableCharacterCount.init();
Using NPM/Webpack to Load Modules Using CommonJS Syntax
-
Install the
enable-a11y
NPM project. -
You can import the module using
require
like this:var enableCharacterCount = require('enable-a11y/enable-character-count').default; ... enableCharacterCount.init();
Using ES6 modules natively.
This is the method by which the page you are reading now loads the scripts.
- Grab the source by either using NPM, grabbing a ZIP file, or cloning the enable source code from GitHub.
-
If you want to load the module as a native ES6 module, copy
js/modules/enable-character-count.js
from the repo and put them in the appropriate directories in your project (all JS files must be in the same directory). -
Load your scripts using the following code (NOTE: you must use
<script type="module">
):<script type="module"> import enableCharacterCount from "path-to/enable-character-count.js" enableCharacterCount.init(); </script>
Using ES4
Just do the same as the ES6 method, except you should get the JavaScript files from thejs/modules/es4
directory instead of the js/modules/
:
<script src="path-to/es4/enable-character-count.js"></script>