Default

Basic label paired with an input. Click the label to focus the input.

<label class="label" for="email">Email</label>
<input class="input" type="email" id="email" placeholder="you@example.com">

Required

Required indicator using a red asterisk.

<label class="label" for="name">
  Name <span aria-hidden="true" class="text-destructive">*</span>
</label>
<input class="input" type="text" id="name" required>

Optional hint

Hint text indicating the field is optional.

<label class="label" for="bio">
  Bio <span class="label-hint">(optional)</span>
</label>

Disabled

Dimmed label for disabled fields. The label auto-detects the disabled input via :has() — no data-disabled attribute needed.

<label class="label" for="disabled">Disabled field</label>
<input class="input" type="text" id="disabled" disabled>

With Checkbox

Inline label paired with a checkbox control.

<div class="checkbox-item">
  <input class="checkbox" type="checkbox" id="terms">
  <label class="label" for="terms" style="margin:0;">Accept terms and conditions</label>
</div>

With Switch

Inline label paired with a switch control.

<div class="switch-item">
  <input class="switch" type="checkbox" role="switch" id="airplane">
  <label class="label" for="airplane" style="margin:0;">Airplane Mode</label>
</div>

Form Field

Label composed with an input and description text, as used in forms.

This is your public display name.

<div>
  <label class="label" for="username">Username</label>
  <input class="input" type="text" id="username" placeholder="shadcn">
  <p class="field-description">This is your public display name.</p>
</div>

CSS view file

/* -- Label component -------------------------------------------- */

@layer components {
  .label {
    font-size: 0.875rem;
    font-weight: 500;
    font-family: var(--font-sans);
    line-height: 1;
    color: var(--foreground);
    display: block;
    margin-bottom: 0.375rem;
    cursor: default;

    /* Disabled — explicit attribute */
    &[data-disabled] {
      opacity: 0.7;
      cursor: not-allowed;
    }

    /* Disabled — auto-detect via adjacent disabled control */
    &:has(+ :disabled),
    &:has(+ [data-disabled]) {
      opacity: 0.7;
      cursor: not-allowed;
    }
  }

  /* -- Hint text (optional, required indicators) ----------- */
  .label-hint {
    font-weight: 400;
    font-size: 0.8125rem;
    color: var(--muted-foreground);
  }

  /* -- Accessibility ---------------------------------------- */
  @media (prefers-contrast: more) {
    .label[data-disabled],
    .label:has(+ :disabled),
    .label:has(+ [data-disabled]) {
      opacity: 0.85;
    }
  }

  @media (forced-colors: active) {
    .label {
      color: LinkText;
    }

    .label[data-disabled],
    .label:has(+ :disabled),
    .label:has(+ [data-disabled]) {
      opacity: 1;
      color: GrayText;
    }
  }
}