General
- Ensure sufficient colour contrast for all text elements
- All textareas must have associated labels
- Helper text should guide without being essential to understanding the field
- Error messages must be clear and actionable
- Keep labels concise and descriptive
- Do not use placeholder text as the primary instruction
Web
Semantic markup
- Use the <textarea> element for multi-line text input
- Use <label> associated with the textarea via the for attribute
- Never use <input> with manual line break handling as a substitute for <textarea>
Accessible labelling
All textareas must be properly labelled and associated:
- Label: Use <label for="textarea-id"> to associate the label with the textarea
- Helper text: Use aria-describedby="helper-id" to associate helper text with the textarea
- Error messages: Use aria-describedby="error-id" to associate error messages with the textarea
- Multiple associations: Stack IDs in aria-describedby for both helper text and errors: aria-describedby="helper-id error-id"
Error handling
- Use aria-invalid="true" when the textarea contains an error
- Use role="alert" on error messages to announce them to screen readers
- Update aria-describedby to include the error message ID
- Provide clear, actionable error messages that explain how to fix the issue
Character limits
If implementing a character limit:
- Display the character count and limit clearly
- Update the count dynamically as the user types
- Use aria-live="polite" on the character count to announce updates to screen readers
- Provide clear feedback when approaching or exceeding the limit
Example with character count
<label for="bio">Biography</label>
<p id="bio-helper">Describe yourself in 200 characters or less</p>
<textarea
id="bio"
name="bio"
maxlength="200"
rows="4"
aria-describedby="bio-helper bio-count"
></textarea>
<p id="bio-count" aria-live="polite">0 of 200 characters</p>
Keyboard Controls
- Users should be able to Tab to the textarea
- Standard text editing keyboard shortcuts should work (e.g., Ctrl+A to select all, arrow keys to move cursor)
- Tab key inside the textarea should insert a tab character (if supported) or move to the next field based on context
- Users should be able to navigate to the resize handle if the textarea is resizable
Required fields
- Use the required attribute for required textareas
- Use aria-required="true" for enhanced screen reader support
Placeholder text
- Avoid using placeholder text as the primary instruction — use helper text instead
- If placeholder text is used, ensure it does not replace the label
- Placeholder text should provide an example, not essential instructions
- Placeholder text often has insufficient contrast and disappears when users start typing
React Native
- Use the TextInput component with multiline={true} prop
- Provide accessibilityLabel that describes the field's purpose
- Use accessibilityHint for additional context if needed (similar to helper text)
- Set numberOfLines to indicate the expected height
- Ensure the component is labelled correctly and keyboard accessible
Error states:
- Update accessibilityLabel or use accessibilityHint to include error information
- Ensure error messages are announced when they appear
- Use accessibilityLiveRegion="polite" on error text containers