Skip to main content Home About the Design SystemRoadmap OverviewDesignersDevelopers OverviewColorGridIconographyInteractionsSpacingTypography Overview Global colorBox shadowTypographyBorderOpacitySpaceLengthIconBreakpointsMedia queries All elements Accordion Alert Announcement Audio player Avatar Back to top Badge Blockquote Breadcrumb Button group Button Card Chip Code block Call to action Dialog Disclosure Footer Health index Icon Jump links Menu dropdown Navigation link Navigation (primary) Navigation (secondary) Navigation (vertical) Pagination PopoverPlanned Progress stepper ReadtimeNew Scheme toggle SelectNew Site status Skeleton Skip link Spinner Statistic Subnavigation Surface Switch Table Tabs Tag Textarea Tile Timestamp Tooltip Video embed OverviewColor PalettesCustomizingDevelopers All PatternsAccordionAlertCall to ActionCardFilterFormLink with iconLogo wallSearch barSticky bannerSticky cardTabsTagTile All Personalization PatternsAnnouncement FundamentalsAccessibility toolsAssistive technologiesCI/CDContentContributorsDesignDevelopmentManual testingResourcesScreen readers Design/code status Release notes Get support

Textarea

OverviewStyleGuidelinesCodeAccessibilityDemos
ImportingUsageValidation and error staterh-textareaImportingUsageValidation and error staterh-textarea

Importing

Add rh-textarea to your page with this import statement:

<script type="module">
  import '@rhds/elements/rh-textarea/rh-textarea.js';
</script>
Copy to Clipboard Wrap lines

To learn more about installing RHDS elements on your site using an import map read our getting started docs.

Usage

<label for="my-textarea">
  Notes
</label>
<rh-textarea id="my-textarea" placeholder="Enter your notes here"></rh-textarea>

<script type="module">
  import '@rhds/elements/rh-textarea/rh-textarea.js';
</script>

<style>
  label,
  rh-textarea {
    margin-inline: 20px;
    max-inline-size: 320px;
  }

  label {
    display: block;
    font-family: var(--rh-font-family-body-text);
    font-weight: var(--rh-font-weight-body-text-medium, 500);
    margin-block: var(--rh-space-md, 8px);
  }
</style>
Copy to Clipboard Wrap lines

Validation and error state

Built-in validation

When users set the required property and the textarea is empty, the component participates in the Constraint Validation API. It sets internal validity states (valueMissing, tooShort, tooLong), so the browser can show validation messages when the user submits the form or when you call reportValidity(). Use checkValidity() or reportValidity() on the <rh-textarea> element to validate before submit.

The component validates:

  • required — value must not be empty
  • minlength — value must meet the minimum character count
  • maxlength — value must not exceed the maximum character count

See the Required demo for an example of this functionality.

Custom validation and error state

This component does not set aria-invalid when setting state="danger". For custom errors, you should:

  1. Visual state: Set state="danger" and help-text="My error message" with the error message.
  2. Semantic state for assistive tech: Set aria-invalid="true" on the <rh-textarea> host element so screen readers announce the invalid state.
  3. Blocking form submit: The component only sets validity for required, minlength, and maxlength. For custom rules, handle submit yourself:
    • In your submit handler, run your custom check.
    • If the check fails: call preventDefault() so the form does not submit then set state="danger", help-text, and aria-invalid="true" so the user sees and hears the error.
    • If the check passes: clear the error state and allow the form to submit.

Example: validate on submit and show a custom error state when the textarea content fails a rule.

<form id="my-form">
  <label for="notes">Notes</label>
  <rh-textarea id="notes" name="notes" placeholder="Enter your notes"></rh-textarea>
  <button type="submit">Submit</button>
</form>

<script type="module">
  import '@rhds/elements/rh-textarea/rh-textarea.js';

  const form = document.getElementById('my-form');
  const textarea = document.getElementById('notes');

  form.addEventListener('submit', (e) => {
    if (textarea.value.includes('forbidden')) {
      e.preventDefault();
      textarea.setAttribute('state', 'danger');
      textarea.setAttribute('help-text', 'Text contains a forbidden word.');
      textarea.setAttribute('aria-invalid', 'true');
      textarea.focus();
    } else {
      textarea.removeAttribute('state');
      textarea.removeAttribute('help-text');
      textarea.removeAttribute('aria-invalid');
    }
  });
</script>

For accessibility implications and why the component does not set aria-invalid from state, see Validation and error state in the Textarea accessibility documentation.

ARIA attributes

Always set ARIA attributes on the host element, not on the inner textarea — the host is the form-associated custom element and the browser exposes its ARIA attributes via ElementInternals.

rh-textarea

A textarea element allows users to enter multi-line text. It functions as a branded, accessible <textarea> element with cross-root ARIA wiring, form association, and constraint validation.

Theming

Themable

This element uses Red Hat design system theming and can be used in themable contexts.

Slots 1

Slot Name Summary Description
help-text

Help or error text displayed below the textarea. Overrides the help-text attribute.

Attributes 21

Attribute DOM Property Description Type Default
accessible-label accessibleLabel

Accessible name when no external <label> is present.

string
unknown
autocomplete autocomplete

Browser autocomplete hint forwarded to the inner textarea.

string
unknown
cols cols

Visible width in average character widths.

number
unknown
disabled disabled

Whether the textarea is disabled. Uses aria-disabled on the inner textarea (not native disabled) so the element remains keyboard-focusable for screen reader users.

boolean
false
field-sizing fieldSizing

When set to content, the textarea automatically grows in height to fit its content instead of using a fixed row count. Uses the CSS field-sizing property as a progressive enhancement; not supported in Firefox, where the textarea falls back to fixed height.

'content'
unknown
help-text helpText

Help text displayed below the control. Content slotted into the help-text slot overrides this attribute.

string
unknown
value-missing-message valueMissingMessage

Validation message shown when required is set and the field is empty.

string
'Please fill out this field.'
too-short-message tooShortMessage

Validation message shown when the value is shorter than minlength. Use {minlength} and {length} as placeholders for the constraint and current character count. The component will update those placeholders to their correct respective values.

string
'Please lengthen this text to {minlength} characters or more'\n + ' (you are currently using {length} characters).'
too-long-message tooLongMessage

Validation message shown when the value exceeds maxlength. Use {maxlength} and {length} as placeholders for the constraint and current character count. The component will update those placeholders to their correct respective values.

string
'Please shorten this text to {maxlength} characters or less'\n + ' (you are currently using {length} characters).'
maxlength maxlength

Maximum number of characters (UTF-16 code units) allowed.

number
unknown
minlength minlength

Minimum number of characters (UTF-16 code units) required.

number
unknown
name name

The name of the control, used for form submission.

string
unknown
placeholder placeholder

Placeholder hint text shown when the textarea is empty.

string
unknown
readonly readonly

Whether the textarea is read-only. Value is still submitted.

boolean
false
required required

Whether a value is required before form submission. Syncs to aria-required and constraint validation.

boolean
false
resize resize

Controls whether the textarea is resizable by the user. Mapped to the CSS resize property via attribute selectors.

'none' | 'vertical' | 'horizontal' | 'both'
unknown
rows rows

Number of visible text lines. Defaults to 5 for a comfortable editing area, matching the ux.redhat.com form pattern sizing.

number
5
show-character-count showCharacterCount

Opt-in character counter. Only renders when both this attribute and maxlength are set. Format: 42/500.

boolean
false
state state

Visual and semantic state of the form control for user feedback. Use 'danger' for blocking errors, 'warning' for non-blocking issues, and 'success' for valid input. Affects styling only; does not set aria-invalid automatically.

'danger' | 'success' | 'warning'
unknown
value value

Current value of the textarea. Not reflected to an attribute.

string
''
wrap wrap

How the textarea wraps text for form submission.

'soft' | 'hard' | 'off'
unknown

Methods 5

Method Name Description
checkValidity()

Returns true if the element's value passes constraint validation. Updates validity state before checking.

reportValidity()

Returns true if the element's value passes constraint validation. If invalid, reports the problem (e.g. browser tooltip) and returns false.

select()

Selects all text in the textarea.

setRangeText(replacement: string, start: number, end: number, selectMode: SelectionMode)

Replaces a range of text. Defaults start/end to current selection when not provided (matching the Shoelace fix for this edge case).

setSelectionRange(start: number | null, end: number | null, direction: 'forward' | 'backward' | 'none')

Sets the cursor position or text selection range.

Events 0

None

CSS Shadow Parts 1

Part Name Summary Description
textarea

The inner native <textarea> element

CSS Custom Properties 4

CSS Property Description Default
--rh-textarea-resize-direction

Sets the resize direction for the textarea / input. Overridden by resize attribute.

vertical
--rh-color-status-disabled light-dark( var(--rh-color-gray-30, #c7c7c7), var(--rh-color-gray-40, #a3a3a3))
--rh-color-text-status-disabled light-dark( var(--rh-color-gray-50, #707070), var(--rh-color-gray-60, #4d4d4d))
--rh-textarea-icon-size 14px

Design Tokens 32

Token Description Copy
--rh-font-family-body-text

Textarea font family

Body text font family

Full CSS Variable Permalink to this token
--rh-font-weight-body-text-regular

Textarea font weight

Regular font weight

Full CSS Variable Permalink to this token
--rh-line-height-body-text

Textarea line height

Line height for body text

Full CSS Variable Permalink to this token
--rh-color-surface-lightest

Input surface color for light schemes

Primary surface (light theme)

Full CSS Variable Permalink to this token
--rh-color-surface-darkest

Input surface color for dark schemes

Primary surface (dark theme)

Full CSS Variable Permalink to this token
--rh-border-width-sm

Input border width

1px border width; Example: Secondary CTA or Button

Full CSS Variable Permalink to this token
--rh-color-border-subtle

Input border color

Full CSS Variable Permalink to this token
--rh-border-radius-default

Default border radius

3px border radius; Example: Card

Full CSS Variable Permalink to this token
--rh-color-text-primary

Textarea text color

Input text color

Full CSS Variable Permalink to this token
--rh-space-lg

Left and right padding for input

16px spacer

Full CSS Variable Permalink to this token
--rh-border-width-lg

Outer focus ring width when focused

3px border width: Example: Expanded Accordion panel

Full CSS Variable Permalink to this token
--rh-color-border-interactive

Input hover border color

Textarea border color when focused

Outer focus ring color when focused

Full CSS Variable Permalink to this token
--rh-color-gray-30

Subtle borders (light theme)

Full CSS Variable Permalink to this token
--rh-color-gray-40

Subtle icon (hover state)

Full CSS Variable Permalink to this token
--rh-color-gray-50

Subtle icon

Full CSS Variable Permalink to this token
--rh-color-gray-60

Secondary text (light theme)

Full CSS Variable Permalink to this token
--rh-color-surface-lighter

Readonly surface color for light schemes

Tertiary surface (light theme)

Full CSS Variable Permalink to this token
--rh-color-surface-darker

Readonly surface color for dark schemes

Secondary surface (dark theme)

Full CSS Variable Permalink to this token
--rh-color-gray-20

Readonly border in light schemes

Secondary surface (light theme)

Full CSS Variable Permalink to this token
--rh-color-gray-70

Readonly border in dark schemes

Tertiary surface (dark theme)

Full CSS Variable Permalink to this token
--rh-color-text-secondary

Textarea placeholder text color

Secondary text color for the character counter

Full CSS Variable Permalink to this token
--rh-font-size-body-text-xs

Extra-small font size for the character counter

12px font size

Full CSS Variable Permalink to this token
--rh-space-md

Top and bottom padding for input

Block start margin for the character counter

Help text CSS gap

Help text margin-block-start

8px spacer

Full CSS Variable Permalink to this token
--rh-font-size-body-text-sm

Textarea text size

Help text slotted elements font size

14px font size

Full CSS Variable Permalink to this token
--rh-color-border-status-success
Full CSS Variable Permalink to this token
--rh-color-border-status-warning
Full CSS Variable Permalink to this token
--rh-color-border-status-danger
Full CSS Variable Permalink to this token
--rh-font-weight-body-text-medium

Medium font weight

Full CSS Variable Permalink to this token
--rh-color-icon-status-success

Success icon color design token for the help-text status indicator

Full CSS Variable Permalink to this token
--rh-color-icon-status-warning

Warning icon color design token for the help-text status indicator

Full CSS Variable Permalink to this token
--rh-color-icon-status-danger

Danger icon color design token for the help-text status indicator

Full CSS Variable Permalink to this token
--rh-length-6xl

96px length token

Full CSS Variable Permalink to this token
© 2026 Red Hat Deploys by Netlify