Skip to main content

Theme config

Theme mode

Color palette

Grays

Border radii/radiuses/radiopedes/you know
Border radius
Field border radius
Button border radius
All
Components
Guides
API
Recent

    Components

    Textarea

    Full supportSupported since v125.Full supportSupported since v152.Full supportSupported since v26.2.

    Variants

    <script setup lang="ts">
    import { Textarea } from "opui-css/vue"
    </script>
    <template>
    <Textarea label="Default" placeholder="Placeholder" />
    <Textarea label="Filled" placeholder="Placeholder" filled />
    </template>
    <!--[--><label class="ui-textarea"
    ><span class="ui-label"><!--[-->Default<!--]--></span><!----><span
    class="ui-field"
    >
    <textarea id="s0-0" placeholder="Placeholder"></textarea
    ><!----><!----><!----><!----></span
    ><!----><!--[--><!--]--></label
    ><label class="ui-textarea ui-filled"
    ><span class="ui-label"><!--[-->Filled<!--]--></span><!----><span
    class="ui-field"
    >
    <textarea id="s0-1" placeholder="Placeholder"></textarea
    ><!----><!----><!----><!----></span
    ><!----><!--[--><!--]--></label
    ><!--]-->

    Sizes

    <script setup lang="ts">
    import { Textarea } from "opui-css/vue"
    </script>
    <template>
    <Textarea label="Small outlined" placeholder="Placeholder" small />
    <Textarea label="Small filled" placeholder="Placeholder" small filled />
    </template>
    <!--[--><label class="ui-textarea ui-small"
    ><span class="ui-label"><!--[-->Small outlined<!--]--></span><!----><span
    class="ui-field"
    >
    <textarea id="s1-0" placeholder="Placeholder"></textarea
    ><!----><!----><!----><!----></span
    ><!----><!--[--><!--]--></label
    ><label class="ui-textarea ui-filled ui-small"
    ><span class="ui-label"><!--[-->Small filled<!--]--></span><!----><span
    class="ui-field"
    >
    <textarea id="s1-1" placeholder="Placeholder"></textarea
    ><!----><!----><!----><!----></span
    ><!----><!--[--><!--]--></label
    ><!--]-->

    End text

    <script setup lang="ts">
    import { Textarea } from "opui-css/vue"
    </script>
    <template>
    <Textarea label="Label" placeholder="Default" endText="Supporting text" />
    <Textarea
    label="Label"
    placeholder="Filled"
    endText="Supporting text"
    filled
    />
    </template>
    <!--[--><label class="ui-textarea"
    ><span class="ui-label"><!--[-->Label<!--]--></span><!----><span
    class="ui-field"
    >
    <textarea id="s2-0" placeholder="Default"></textarea
    ><!----><!----><!----><!----></span
    ><span class="ui-end-text"
    ><!--[-->Supporting text<!--]--><!--[--><!--]--></span
    ><!--[--><!--]--></label
    ><label class="ui-textarea ui-filled"
    ><span class="ui-label"><!--[-->Label<!--]--></span><!----><span
    class="ui-field"
    >
    <textarea id="s2-1" placeholder="Filled"></textarea
    ><!----><!----><!----><!----></span
    ><span class="ui-end-text"
    ><!--[-->Supporting text<!--]--><!--[--><!--]--></span
    ><!--[--><!--]--></label
    ><!--]-->

    Affix

    Use the prefix, suffix, header, and footer slots to affix content inside the textarea's border. Header and footer are particularly useful for filenames and character counters.

    <script setup lang="ts">
    import { Textarea } from "opui-css/vue"
    </script>
    <template>
    <Textarea label="Notes" placeholder="Add a note...">
    <template #prefix
    ><svg
    width="16"
    height="16"
    viewBox="0 0 24 24"
    fill="none"
    stroke="currentColor"
    stroke-width="2"
    stroke-linecap="round"
    stroke-linejoin="round"
    >
    <path
    d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"
    ></path>
    <path
    d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"
    ></path></svg
    ></template>
    </Textarea>
    </template>
    <label class="ui-textarea"
    ><span class="ui-label"><!--[-->Notes<!--]--></span><!----><span
    class="ui-field"
    >
    <textarea id="s3-0" placeholder="Add a note..."></textarea
    ><span class="ui-prefix"
    ><!--[--><svg
    width="16"
    height="16"
    viewBox="0 0 24 24"
    fill="none"
    stroke="currentColor"
    stroke-width="2"
    stroke-linecap="round"
    stroke-linejoin="round"
    >
    <path
    d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"
    ></path>
    <path
    d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"
    ></path></svg
    ><!--]--></span
    ><!----><!----><!----></span
    ><!----><!--[--><!--]--></label
    >

    Headers and footers

    <script setup lang="ts">
    import { Textarea } from "opui-css/vue"
    </script>
    <template>
    <Textarea label="Code" placeholder="console.log('Hello, world!')">
    <template #header>script.js</template>
    </Textarea>
    <Textarea label="Comment" placeholder="Write a comment...">
    <template #footer>0 / 280</template>
    </Textarea>
    </template>
    <!--[--><label class="ui-textarea"
    ><span class="ui-label"><!--[-->Code<!--]--></span><!----><span
    class="ui-field"
    >
    <textarea id="s4-0" placeholder="console.log('Hello, world!')"></textarea
    ><!----><!----><span class="ui-header"><!--[-->script.js<!--]--></span
    ><!----></span
    ><!----><!--[--><!--]--></label
    ><label class="ui-textarea"
    ><span class="ui-label"><!--[-->Comment<!--]--></span><!----><span
    class="ui-field"
    >
    <textarea id="s4-1" placeholder="Write a comment..."></textarea
    ><!----><!----><!----><span class="ui-footer"
    ><!--[-->0 / 280<!--]--></span
    ></span
    ><!----><!--[--><!--]--></label
    ><!--]-->

    Validation

    Add the required attribute on the component. It is forwarded to the underlying <textarea>.

    Use the error prop to toggle invalid styles. It rendersdata-invalid on the root element. Make use of the end text to give extra feedback on the error.

    <script setup lang="ts">
    import { Textarea } from "opui-css/vue"
    </script>
    <template>
    <div class="example-row">
    <Textarea label="Label" placeholder="Default" required />
    <Textarea label="Label" placeholder="Filled" required filled />
    </div>
    <div class="example-row">
    <Textarea
    label="Label"
    placeholder="Default"
    endText="Only double-negatives are allowed."
    error
    />
    <Textarea
    label="Label"
    placeholder="Filled"
    endText="Only letters from the first half of the alphabet are allowed."
    error
    filled
    />
    </div>
    </template>
    <!--[-->
    <div class="example-row">
    <label class="ui-textarea"
    ><span class="ui-label"><!--[-->Label<!--]--></span><!----><span
    class="ui-field"
    >
    <textarea id="s5-0" placeholder="Default" required></textarea
    ><!----><!----><!----><!----></span
    ><!----><!--[--><!--]--></label
    ><label class="ui-textarea ui-filled"
    ><span class="ui-label"><!--[-->Label<!--]--></span><!----><span
    class="ui-field"
    >
    <textarea id="s5-1" placeholder="Filled" required></textarea
    ><!----><!----><!----><!----></span
    ><!----><!--[--><!--]--></label
    >
    </div>
    <div class="example-row">
    <label class="ui-textarea" data-invalid="true"
    ><span class="ui-label"><!--[-->Label<!--]--></span><!----><span
    class="ui-field"
    >
    <textarea id="s5-2" placeholder="Default"></textarea
    ><!----><!----><!----><!----></span
    ><span class="ui-end-text"
    ><!--[-->Only double-negatives are allowed.<!--]--><!--[--><!--]--></span
    ><!--[--><!--]--></label
    ><label class="ui-textarea ui-filled" data-invalid="true"
    ><span class="ui-label"><!--[-->Label<!--]--></span><!----><span
    class="ui-field"
    >
    <textarea id="s5-3" placeholder="Filled"></textarea
    ><!----><!----><!----><!----></span
    ><span class="ui-end-text"
    ><!--[-->Only letters from the first half of the alphabet are allowed.<!--]--><!--[--><!--]--></span
    ><!--[--><!--]--></label
    >
    </div>
    <!--]-->

    Spread

    Use the spread boolean prop to display the label and description on the left with the textarea on the right. The layout collapses to a column on narrow containers.

    <script setup lang="ts">
    import { Textarea } from "opui-css/vue"
    </script>
    <template>
    <Textarea spread placeholder="Hello, world!">
    <template #label>Message</template>
    <template #description
    >You can write your message here. Keep it short, preferably under 100
    characters.</template
    >
    </Textarea>
    <Textarea spread placeholder="Additional notes..." filled>
    <template #label>Notes</template>
    <template #description>Add any additional notes or comments</template>
    <template #end-text>Maximum 500 characters</template>
    </Textarea>
    <Textarea spread required label="Required">
    <template #description>You must provide a response</template>
    </Textarea>
    <Textarea spread disabled label="Disabled">
    <template #description>This textarea is disabled</template>
    </Textarea>
    <Textarea spread error label="Invalid Message">
    <template #description>This textarea has an error</template>
    <template #end-text>This value is too short.</template>
    </Textarea>
    <Textarea spread label="Bio" placeholder="Tell us about yourself...">
    <template #description>Shown on your public profile</template>
    <template #prefix>
    <svg
    width="16"
    height="16"
    viewBox="0 0 24 24"
    fill="none"
    stroke="currentColor"
    stroke-width="2"
    stroke-linecap="round"
    stroke-linejoin="round"
    >
    <path
    d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"
    ></path>
    <path
    d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"
    ></path>
    </svg>
    </template>
    <template #footer>280 characters left</template>
    </Textarea>
    <Textarea
    spread
    filled
    label="Release notes"
    placeholder="Markdown supported..."
    >
    <template #description>Shown on the changelog page</template>
    <template #header>v1.4.0</template>
    <template #footer>Saved 2 minutes ago</template>
    <template #end-text>Drafts are auto-saved</template>
    </Textarea>
    </template>
    <!--[--><label class="ui-textarea ui-spread"
    ><span class="ui-label"><!--[-->Message<!--]--></span
    ><span class="ui-start-text"
    ><!--[-->You can write your message here. Keep it short, preferably under
    100 characters.<!--]--></span
    ><span class="ui-field">
    <textarea id="s6-0" placeholder="Hello, world!"></textarea
    ><!----><!----><!----><!----></span
    ><!----><!--[--><!--]--></label
    ><label class="ui-textarea ui-filled ui-spread"
    ><span class="ui-label"><!--[-->Notes<!--]--></span
    ><span class="ui-start-text"
    ><!--[-->Add any additional notes or comments<!--]--></span
    ><span class="ui-field">
    <textarea id="s6-1" placeholder="Additional notes..."></textarea
    ><!----><!----><!----><!----></span
    ><span class="ui-end-text"
    ><!--[-->Maximum 500 characters<!--]--><!--[--><!--]--></span
    ><!--[--><!--]--></label
    ><label class="ui-textarea ui-spread"
    ><span class="ui-label"><!--[-->Required<!--]--></span
    ><span class="ui-start-text"><!--[-->You must provide a response<!--]--></span
    ><span class="ui-field">
    <textarea id="s6-2" required></textarea><!----><!----><!----><!----></span
    ><!----><!--[--><!--]--></label
    ><label class="ui-textarea ui-spread"
    ><span class="ui-label"><!--[-->Disabled<!--]--></span
    ><span class="ui-start-text"><!--[-->This textarea is disabled<!--]--></span
    ><span class="ui-field">
    <textarea id="s6-3" disabled></textarea><!----><!----><!----><!----></span
    ><!----><!--[--><!--]--></label
    ><label class="ui-textarea ui-spread" data-invalid="true"
    ><span class="ui-label"><!--[-->Invalid Message<!--]--></span
    ><span class="ui-start-text"><!--[-->This textarea has an error<!--]--></span
    ><span class="ui-field">
    <textarea id="s6-4"></textarea><!----><!----><!----><!----></span
    ><span class="ui-end-text"
    ><!--[-->This value is too short.<!--]--><!--[--><!--]--></span
    ><!--[--><!--]--></label
    ><label class="ui-textarea ui-spread"
    ><span class="ui-label"><!--[-->Bio<!--]--></span
    ><span class="ui-start-text"
    ><!--[-->Shown on your public profile<!--]--></span
    ><span class="ui-field">
    <textarea id="s6-5" placeholder="Tell us about yourself..."></textarea
    ><span class="ui-prefix"
    ><!--[--><svg
    width="16"
    height="16"
    viewBox="0 0 24 24"
    fill="none"
    stroke="currentColor"
    stroke-width="2"
    stroke-linecap="round"
    stroke-linejoin="round"
    >
    <path
    d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"
    ></path>
    <path
    d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"
    ></path></svg
    ><!--]--></span
    ><!----><!----><span class="ui-footer"
    ><!--[-->280 characters left<!--]--></span
    ></span
    ><!----><!--[--><!--]--></label
    ><label class="ui-textarea ui-filled ui-spread"
    ><span class="ui-label"><!--[-->Release notes<!--]--></span
    ><span class="ui-start-text"><!--[-->Shown on the changelog page<!--]--></span
    ><span class="ui-field">
    <textarea id="s6-6" placeholder="Markdown supported..."></textarea
    ><!----><!----><span class="ui-header"><!--[-->v1.4.0<!--]--></span
    ><span class="ui-footer"><!--[-->Saved 2 minutes ago<!--]--></span></span
    ><span class="ui-end-text"
    ><!--[-->Drafts are auto-saved<!--]--><!--[--><!--]--></span
    ><!--[--><!--]--></label
    ><!--]-->

    Auto-fit

    When enabled the Field changes size depending on its content.

    <script setup lang="ts">
    import { Textarea } from "opui-css/vue"
    </script>
    <template>
    <Textarea label="Auto-fit" placeholder="Auto-fit" autoFit />
    </template>
    <label class="ui-textarea ui-auto-fit"
    ><span class="ui-label"><!--[-->Auto-fit<!--]--></span><!----><span
    class="ui-field"
    >
    <textarea id="s7-0" placeholder="Auto-fit"></textarea
    ><!----><!----><!----><!----></span
    ><!----><!--[--><!--]--></label
    >

    Anatomy

    1. label.ui-textarea: Container element
    2. .ui-label: Field label element
    3. .ui-field: The boxed input area
    4. .ui-header: Optional inside-border header strip (with divider)
    5. .ui-prefix: Optional inline-start affix
    6. <textarea>: Textarea element
    7. .ui-suffix: Optional inline-end affix
    8. .ui-footer: Optional inside-border footer strip (with divider)
    9. .ui-end-text: Supporting text element

    API

    Text field API

    Textarea API

    Browser support

    Full supportSupported since v125.Full supportSupported since v152.Full supportSupported since v26.2.

    See also the full browser support guide.

    Installation

    Dependencies

    @layer components.extended {
    /*
    - Common styling for input, textarea and select
    - Form related styles such as: label, supporting text, error handling
    */
    :where(.ui-text-field, .ui-textarea, .ui-select) {
    --_motion: var(--motion, 1);
    --_accent-color: var(--primary);
    --_bg-color: var(--surface-default);
    --_border-color: var(--field-border-color);
    --_field-padding-block: var(--size-2);
    --_field-padding-inline: var(--size-2);
    --_filled-border-color: var(--text-primary);
    --_height: var(--field-size);
    --_label-color: var(--text-muted);
    --_end-text-color: var(--text-muted);
    display: grid;
    gap: var(--size-1) 0;
    position: relative;
    /* Field - the actual input with a border around it */
    .ui-field {
    background-color: var(--_bg-color);
    border: var(--field-border-width) solid var(--_border-color);
    border-radius: var(--field-border-radius);
    display: grid;
    grid-column: 1/-1;
    grid-row: 2;
    grid-template-columns: auto 1fr auto;
    grid-template-areas:
    "header header header"
    "prefix input suffix"
    "footer footer footer";
    min-block-size: var(--_height);
    transition: border-color calc(0.2s * var(--_motion))
    cubic-bezier(0.4, 0, 0.2, 1);
    }
    :where(.ui-field) :where(input, textarea, select) {
    background: transparent;
    border: 0;
    color: var(--text-primary);
    font-family: var(--font-sans);
    font-size: var(--font-size-1);
    grid-area: input;
    inline-size: 100%;
    line-height: var(--font-lineheight-1);
    min-inline-size: 0;
    padding: var(--_field-padding-block) var(--_field-padding-inline);
    &:focus,
    &:focus-visible {
    outline: 0;
    }
    }
    /* Affixes */
    .ui-prefix,
    .ui-suffix {
    align-items: center;
    color: var(--_label-color);
    display: inline-flex;
    padding-inline: var(--_field-padding-inline);
    white-space: nowrap;
    }
    .ui-prefix {
    grid-area: prefix;
    }
    .ui-suffix {
    grid-area: suffix;
    }
    .ui-header,
    .ui-footer {
    align-items: center;
    color: var(--_label-color);
    display: flex;
    font-size: var(--font-size-0);
    gap: var(--size-2);
    padding: var(--size-1) var(--_field-padding-inline);
    }
    .ui-header {
    border-block-end: 1px solid var(--_border-color);
    grid-area: header;
    }
    .ui-footer {
    border-block-start: 1px solid var(--_border-color);
    grid-area: footer;
    }
    /* Remove padding on the input when affixes are next to it */
    .ui-field:has(> .ui-prefix) :where(input, textarea, select) {
    padding-inline-start: 0;
    }
    .ui-field:has(> .ui-suffix) :where(input, textarea, select) {
    padding-inline-end: 0;
    }
    /* Textarea - keep affix aligned with the first line */
    &.ui-textarea .ui-field {
    .ui-prefix,
    .ui-suffix {
    align-self: start;
    padding-block: var(--_field-padding-block);
    }
    }
    /* Required/Invalid */
    &:has(:invalid) {
    .ui-label:after {
    color: var(--red);
    content: "*";
    margin: -0.25em auto auto 0.25em;
    }
    }
    /* File */
    &:has(input[type="file"]) {
    cursor: pointer;
    input {
    align-self: flex-start;
    block-size: var(--_height);
    box-shadow: none;
    color: var(--text-primary);
    cursor: inherit;
    max-inline-size: 100%;
    padding: 0;
    transition: font-size 0.2s var(--ease-3);
    &::-webkit-file-upload-button,
    &::file-selector-button {
    background-color: var(--surface-tonal);
    block-size: calc(100% - var(--size-2) * 2);
    border: none;
    border-radius: var(--field-border-radius);
    cursor: pointer;
    margin-block-start: var(--size-2);
    margin-inline-end: 1ex;
    margin-inline-start: var(--size-2);
    }
    }
    /* Variants */
    &.ui-filled {
    input {
    &::-webkit-file-upload-button,
    &::file-selector-button {
    background-color: var(--surface-default);
    block-size: calc(100% - var(--size-2) * 2);
    border-radius: var(--field-border-radius);
    cursor: pointer;
    margin-block-start: var(--size-2);
    }
    }
    }
    /* Sizes */
    &.ui-small {
    input {
    font-size: var(--font-size-05);
    &::-webkit-file-upload-button,
    &::file-selector-button {
    block-size: calc(100% - var(--size-2));
    margin-block-start: var(--size-1);
    }
    }
    }
    }
    /* Autosuggest */
    &:has(input[list]) {
    .ui-label {
    /* Make sure chevron is visible */
    inline-size: calc(100% - var(--size-6));
    }
    }
    /* Select */
    &:has(select) {
    .ui-label {
    /* Make sure chevron is visible */
    inline-size: calc(100% - var(--size-6));
    }
    }
    /* Customizable Select */
    &:has(select button) {
    select {
    padding: 0;
    button {
    outline: 0;
    padding: var(--_field-padding-block) var(--size-8)
    var(--_field-padding-block) var(--_field-padding-inline);
    }
    }
    }
    /* Non-customizable Select */
    &:has(select):not(:has(button)) {
    select {
    padding: var(--_field-padding-block) var(--size-8)
    var(--_field-padding-block) var(--_field-padding-inline);
    }
    }
    /* Input - color */
    &:has(input[type="color"]) {
    .ui-field {
    block-size: var(--_height);
    inline-size: var(--_height);
    min-block-size: 0;
    overflow: hidden;
    }
    input {
    appearance: none;
    background: none;
    block-size: var(--_height);
    inline-size: var(--_height);
    overflow: hidden;
    padding: 0;
    &::-webkit-color-swatch {
    border: none;
    }
    &::-webkit-color-swatch-wrapper {
    padding: 0;
    }
    }
    }
    /* Element states */
    &:hover {
    &:not([data-invalid]) {
    .ui-field {
    border-color: var(--text-primary);
    }
    }
    }
    &:focus-within {
    .ui-field {
    border-color: var(--_accent-color);
    outline-offset: -2px;
    }
    }
    /* Label */
    .ui-label {
    color: var(--text-primary);
    font-size: var(--font-size-05);
    font-weight: 600;
    grid-column: 1/-1;
    grid-row: 1;
    padding-inline: 0 1ex;
    }
    /* End text */
    :where(.ui-end-text) {
    color: var(--_end-text-color);
    font-size: var(--font-size-0);
    grid-column: 1/-1;
    grid-row: 3;
    line-height: 1.5;
    }
    /* Auto-fit */
    &.ui-auto-fit {
    inline-size: auto;
    .ui-field {
    inline-size: auto;
    }
    :where(& input, & textarea) {
    field-sizing: content;
    inline-size: auto;
    min-inline-size: 25ch;
    }
    }
    /* Validation */
    &[data-invalid],
    &:has(:user-invalid) {
    --_accent-color: var(--color-9);
    --_border-color: var(--color-9);
    --_filled-border-color: var(--color-9);
    --_label-color: var(--color-9);
    --_end-text-color: var(--color-9);
    }
    /*
    * Variant: Filled
    */
    &.ui-filled {
    --_bg-color: var(--surface-tonal);
    &:not(:has([disabled], :has(input[type="color"]))) {
    /* Hover */
    &:hover {
    --_bg-color: light-dark(
    oklch(from var(--surface-tonal) calc(l * 0.93) c h),
    oklch(from var(--surface-tonal) calc(l * 1.1) c h)
    );
    }
    }
    }
    /* Disabled */
    &:where(:has([disabled])) {
    cursor: not-allowed;
    opacity: 0.64;
    user-select: none;
    &::before {
    display: none;
    }
    .ui-field {
    cursor: not-allowed;
    }
    :where(input, textarea, select) {
    cursor: not-allowed;
    * {
    pointer-events: none;
    }
    }
    .ui-label,
    .ui-start-text,
    .ui-end-text {
    cursor: not-allowed;
    }
    }
    /* Read-only */
    &:where(:has([readonly])) {
    &::before {
    display: none;
    }
    :where(input, textarea, select) {
    cursor: not-allowed;
    * {
    pointer-events: none;
    }
    }
    }
    /* Sizes */
    &.ui-small {
    --_field-padding-block: var(--size-2);
    --_height: var(--field-size-small);
    &:has(input[type="color"]) {
    .ui-label {
    line-height: 1.5;
    }
    }
    }
    /* Orientation */
    &.ui-spread {
    align-items: start;
    column-gap: var(--size-4);
    container-type: inline-size;
    grid-template-columns: 1fr auto;
    .ui-label {
    font-weight: 600;
    grid-column: 1;
    grid-row: 1;
    }
    .ui-start-text {
    color: var(--_end-text-color);
    font-size: var(--font-size-0);
    grid-column: 1;
    grid-row: 2;
    line-height: 1.5;
    }
    .ui-field {
    align-self: start;
    grid-column: 2;
    grid-row: 1 / span 2;
    }
    .ui-field:has(textarea) {
    grid-row: 1 / span 3;
    + .ui-end-text {
    grid-row: 4;
    }
    }
    :where(textarea) {
    min-inline-size: 30ch;
    }
    :where(.ui-end-text) {
    grid-column: 2;
    text-align: end;
    }
    /* Collapse to column on narrow containers */
    @container (width < 400px) {
    column-gap: 0;
    grid-template-columns: 1fr;
    .ui-label {
    grid-column: 1;
    grid-row: 1;
    }
    .ui-start-text {
    grid-column: 1;
    grid-row: 2;
    }
    .ui-field,
    .ui-field:has(textarea) {
    grid-column: 1;
    grid-row: 3;
    }
    :where(.ui-end-text) {
    grid-column: 1;
    grid-row: 4;
    text-align: start;
    }
    }
    }
    }
    }
    @layer components.extended {
    :where(.ui-textarea) {
    textarea {
    block-size: auto;
    field-sizing: content;
    min-block-size: calc(
    var(--_field-padding-block) * 2 + (var(--border-width) * 2) + 3lh
    );
    resize: vertical;
    }
    /* Size */
    &.ui-small {
    textarea {
    min-block-size: var(--size-9);
    }
    }
    /* Auto-fit */
    &.ui-auto-fit {
    textarea {
    resize: both;
    }
    }
    }
    }