Textarea

Multi-line text input with auto-resize and character count.

Default

Plain <textarea class="textarea"> — fixed rows, manual resize handle left to the browser default. No JS involved.

<label class="sc-field">
  <span class="sc-field-label">Message</span>
  <textarea class="textarea sc-textarea" rows="4" placeholder="Write your message…"></textarea>
</label>

Auto-resize

Grows with its content instead of scrolling internally. The height reset-then-measure happens on every keystroke via a plain Alpine x-on:input expression — short enough that it doesn't need a named function in the JS file.

<textarea
  class="textarea sc-textarea sc-textarea--auto"
  rows="2"
  x-data
  x-on:input="$el.style.height = 'auto'; $el.style.height = $el.scrollHeight + 'px'"
></textarea>

Character / word count

A live counter below the field, with a max length and a colour change as the limit approaches — handled entirely with Alpine state, no DaisyUI equivalent needed.

/ characters

<div x-data="{ value: '', max: 160 }">
  <textarea class="textarea sc-textarea" :class="{ 'textarea-error': value.length > max }"
            x-model="value" :maxlength="max"></textarea>
  <p class="sc-textarea-counter"><span x-text="value.length"></span> / <span x-text="max"></span></p>
</div>

Floating label

Label sits inside the field until focused or filled, then floats above the border. Pure CSS via Tailwind's peer/peer-focus variants — DaisyUI's floating-label class targets single-line inputs only.

Min / max rows (clamped auto-resize)

Same auto-resize behaviour, clamped between 3 and 8 visible rows via min-height / max-height — beyond the max it scrolls internally instead of pushing the rest of the page down.

States

Default, disabled, error, and empty.

Default

Disabled

Error

Minimum 10 characters required.

Empty