Loading Developer Playground

Loading ...

Skip to main content
ARIA ATTRIBUTEWidget Attributes

aria-multiline

Indicates whether a text box accepts multiple lines of input or only a single line. Essential for custom text widgets built with ARIA roles.

Value Type
true | false
Common Use
Custom Textboxes
Applies To
textbox role

Overview

The aria-multiline attribute indicates whether a textbox accepts multiple lines of input or only a single line. This is important for assistive technologies to convey the expected behavior to users.

Native HTML elements like <input type="text"> and <textarea> automatically communicate this information—you only need aria-multiline for custom ARIA textbox widgets.

When to Use

Only use aria-multiline on elements with role="textbox". Native inputs and textareas don't need this attribute.

Live Demo: Single-Line vs Multi-Line

Press Enter: nothing happens (single-line)

Press Enter: new line (1 line)

Screen reader: Single-line announces as "edit text". Multi-line announces as "edit text, multi-line" indicating multiple lines are expected.

Attribute Values

true

The textbox accepts multiple lines of input. Users can press Enter to create new lines. Similar to a <textarea>.

Screen reader: "[Label], edit text, multi-line"
false(default)

The textbox accepts only a single line of input. Similar to <input type="text">. This is the default when the attribute is absent.

Screen reader: "[Label], edit text"

Code Examples

Basic Usage

<!-- Basic aria-multiline usage -->

<!-- Single-line text input (default) -->
<div 
  role="textbox"
  aria-multiline="false"
  aria-label="Username"
  contenteditable="true"
  tabindex="0"
>
</div>
<!-- Screen reader: "Username, edit text" -->

<!-- Multi-line text area -->
<div 
  role="textbox"
  aria-multiline="true"
  aria-label="Message"
  contenteditable="true"
  tabindex="0"
>
</div>
<!-- Screen reader: "Message, edit text, multi-line" -->

Native vs Custom Elements

<!-- aria-multiline vs Native HTML Elements -->

<!-- Native single-line input (no aria-multiline needed) -->
<input type="text" aria-label="Username" />
<!-- Automatically understood as single-line -->

<!-- Native multi-line textarea (no aria-multiline needed) -->
<textarea aria-label="Message" rows="4"></textarea>
<!-- Automatically understood as multi-line -->

<!-- Custom textbox - NEEDS aria-multiline -->
<div 
  role="textbox"
  aria-multiline="true"
  aria-label="Bio"
  contenteditable="true"
>
  <!-- Multi-line content allowed -->
</div>

<!-- Custom searchbox (implicitly single-line) -->
<div 
  role="searchbox"
  aria-label="Search"
  contenteditable="true"
>
  <!-- Single-line expected (searchbox implies single-line) -->
</div>

Rich Text Editor

<!-- Rich Text Editor with aria-multiline -->
<div class="rich-text-editor">
  <div role="toolbar" aria-label="Text formatting">
    <button aria-label="Bold">B</button>
    <button aria-label="Italic">I</button>
    <button aria-label="Underline">U</button>
  </div>
  
  <div 
    role="textbox"
    aria-multiline="true"
    aria-label="Email content"
    aria-describedby="editor-instructions"
    contenteditable="true"
    tabindex="0"
  >
    <!-- User's text content here -->
  </div>
  
  <p id="editor-instructions" class="sr-only">
    Press Enter for new paragraph. 
    Use toolbar buttons for formatting.
  </p>
</div>

With Combobox

<!-- Combobox with multiline (editable list selection) -->

<!-- Single-line combobox (default) -->
<div 
  role="combobox"
  aria-expanded="false"
  aria-haspopup="listbox"
  aria-label="Select country"
>
  <input type="text" aria-autocomplete="list" />
</div>

<!-- Multi-line combobox (rare, for address entry) -->
<div 
  role="combobox"
  aria-expanded="false"
  aria-haspopup="listbox"
  aria-multiline="true"
  aria-label="Address"
>
  <div 
    role="textbox" 
    contenteditable="true"
    aria-multiline="true"
  >
    <!-- Multi-line address -->
  </div>
</div>

React Component

// React Custom Textbox with Multiline Support
import { useState, useRef } from 'react';

function CustomTextbox({ 
  label, 
  multiline = false,
  value,
  onChange,
  placeholder,
  rows = 4,
  ...props 
}) {
  const textboxRef = useRef(null);
  
  const handleInput = (e) => {
    const content = e.target.textContent || '';
    onChange?.(content);
  };

  const handleKeyDown = (e) => {
    // Prevent Enter key in single-line mode
    if (!multiline && e.key === 'Enter') {
      e.preventDefault();
    }
  };

  return (
    <div className="form-field">
      <label id={`${props.id}-label`}>
        {label}
      </label>
      <div
        ref={textboxRef}
        role="textbox"
        aria-labelledby={`${props.id}-label`}
        aria-multiline={multiline}
        aria-placeholder={placeholder}
        contentEditable
        tabIndex={0}
        onInput={handleInput}
        onKeyDown={handleKeyDown}
        style={{
          minHeight: multiline ? `${rows * 1.5}em` : '2em',
          whiteSpace: multiline ? 'pre-wrap' : 'nowrap',
          overflow: multiline ? 'auto' : 'hidden',
        }}
        className="custom-textbox"
        {...props}
      />
      <style>{`
        .custom-textbox {
          padding: 8px 12px;
          border: 1px solid #d1d5db;
          border-radius: 6px;
          outline: none;
        }
        .custom-textbox:focus {
          border-color: #6366f1;
          box-shadow: 0 0 0 2px rgba(99, 102, 241, 0.2);
        }
        .custom-textbox:empty::before {
          content: attr(aria-placeholder);
          color: #9ca3af;
        }
      `}</style>
    </div>
  );
}

// Usage Examples
function ContactForm() {
  const [name, setName] = useState('');
  const [message, setMessage] = useState('');

  return (
    <form>
      {/* Single-line input */}
      <CustomTextbox
        id="name"
        label="Your Name"
        multiline={false}
        value={name}
        onChange={setName}
        placeholder="Enter your name"
      />
      
      {/* Multi-line input */}
      <CustomTextbox
        id="message"
        label="Your Message"
        multiline={true}
        rows={6}
        value={message}
        onChange={setMessage}
        placeholder="Type your message here..."
      />
      
      <button type="submit">Send</button>
    </form>
  );
}

Best Practices

Use aria-multiline="true" for custom textarea-like widgets

Enforce Enter key behavior to match the aria-multiline value

Style the element appropriately (taller for multiline, single row for single-line)

Set whitespace CSS to preserve line breaks in multiline fields

Prefer native <textarea> when possible—it handles this automatically

×

Don't use aria-multiline on native input or textarea elements

×

Don't set aria-multiline="true" but block Enter key functionality

×

Don't forget to handle keyboard behavior for single-line inputs

×

Don't use on elements without role="textbox"

Common Use Cases

Rich text editors (WYSIWYG)
Custom code editors
Comment input fields
Message composition boxes
Note-taking widgets
Custom form builders
Chat input interfaces
Description text areas

Related Attributes

Specifications & Resources