Character Counter
A character counter displays the number of characters a user has typed into an input field, providing real-time feedback to help users stay within constraints. It is commonly used alongside text inputs with character limits such as tweets, SMS messages, form fields, or bios. The counter shows "count / max" when a maximum is provided, or just the count otherwise.
The component uses role="status" with aria-live="polite" so screen readers announce updates without interrupting the user, and exposes data attributes for consumer CSS styling based on count state.
Implementation Notes
- Renders as a
<span>element withrole="status"andaria-live="polite"for non-intrusive screen reader announcements - Uses derived value to compute
remainingcount andoverLimitboolean fromcountandmaxprops - Displays "count / max" when
maxis provided, otherwise displays just the count - Exposes data attributes for consumer CSS:
data-count,data-max,data-remaining,data-over-limit - The
data-over-limitattribute is only present when the count exceeds the max, enabling conditional styling - Spreads
...restPropson the root<span>element for consumer customization
Props
count: number (default: 0) -- current character countmax: number (optional) -- maximum allowed characters; when provided, enables remaining/over-limit trackinglabel: string (optional) -- accessible label for the counter via aria-label
Usage
Basic counter linked to a text-area-input:
<CharacterCounter count={text.length} max={280} label="Characters remaining" />
Counter with threshold display (consumer shows/hides based on data attributes):
<CharacterCounter count={referralNotes.length} max={500} label="Referral note characters" />
Counter without a maximum, showing only the current count:
<CharacterCounter count={message.length} label="Message length" />
Keyboard Interactions
None -- this component is a passive status display.
ARIA
role="status"-- identifies the element as a live region that presents advisory informationaria-live="polite"-- screen readers announce updates at the next convenient pause, without interrupting the useraria-label-- set from thelabelprop to provide context for what the counter represents
When to Use
- Use when there is a clear reason for limiting the number of characters, such as a database field constraint or regulatory requirement.
- Use when evidence shows users regularly enter more text than needed for the purpose of the field.
- Use to help users understand how much text they can still enter, with a dynamic count that updates as they type.
- Use with a threshold setting so the counter only appears after users have entered a significant portion of the limit, reducing visual noise.
- Use alongside text inputs that have a maximum length, such as referral notes, feedback fields, SMS messages, or bio descriptions.
When Not to Use
- Do not use if the character limit could be increased or removed — relax backend constraints instead of restricting users.
- Do not use without first testing whether your service works without a character limit.
- Do not use for short fields like names or postcodes — use TextInput with an appropriate width instead.
- Do not use as a standalone component — pair it with TextAreaInput inside TextAreaInputWithCharacterCounter for a complete user experience.
Headless
This headless CharacterCounter component provides role="status" with aria-live="polite" for non-intrusive screen reader announcements, and exposes data-count, data-max, data-remaining, and data-over-limit attributes for styling hooks. The consumer provides all visual styling including typography, colors, positioning relative to the input, and over-limit warning styles.
Styles
The consumer provides all CSS styling. The component renders with a .character-counter class for targeting. No default styles are included — this is a fully headless component.
Testing
- Verify the component renders a
<span>element with classcharacter-counter - Verify role="status"` -- identifies the element as a live region that presents advisory information
- Verify aria-label
-- set from thelabel` prop to provide context for what the counter represents - Verify pass-through attributes are applied
Advice
- Designers: Position the counter near the associated input field, typically below or to the right. Use a warning color when the user approaches or exceeds the limit.
- Developers: Bind the
countprop to your input's character length. Use thedata-over-limitattribute in CSS to trigger visual warnings when the maximum is exceeded.
Related components
text-area-input-with-character-counter— a multi-line text area input with a caption below that is a character counter "[number] of [maximum] characters"character— a single character display element