Icon Inputs

.group-input-icon is a positioning wrapper that places content inside an input through two named slots: .input-slot-start on the left and .input-slot-end on the right. The input's padding adjusts automatically via CSS custom properties so the content inside the field never overlaps the slot content.

Sizing the Slots

The input's padding is not measured automatically — it is controlled by two CSS custom properties that you set on .group-input-icon. Each defaults to 2.5rem, which fits a single icon or a single small button. As soon as a slot holds more than one child, or a wider element like a labelled button, you must set the corresponding variable yourself so the input's text never runs under the slot.

PropertyApplies toWhat it controls
--input-slot-start.input-slot-startLeft padding added to .form-input
--input-slot-width.input-slot-startWidth of the start slot box itself (defaults to 2.5rem if unset)
--input-slot-end.input-slot-endRight padding added to .form-input

There is no --input-slot-end-width — the end slot sizes itself to its content and is right-aligned with 0.5rem from the edge, so only the input's padding needs to be told how much room to leave.

Reference values

Use these as a starting point, then adjust to your actual button/icon sizes and label lengths.

Slot contentStart variableEnd variable
Single icon (16–18px)2.5rem (default)2.5rem (default)
Single icon-only button2.75rem2.75rem
Single button with text labelwidth of text + 1.5remwidth of text + 1.5rem
Badge / unit label (e.g. USD)width of label + 1.25rem
Two icon-only buttons (is-small, default gap)4.5rem
Two buttons, one with a text label (e.g. ✕ + "Go")6rem
Three or more actionsmeasure and set explicitly; consider moving actions outside the input

If a value doesn't feel exact for your button size or font, nudge it up or down in 0.25rem steps until the input text clears the slot with a small margin — there's no need to match the table exactly.

Start Icon

The start slot is ideal for context icons: search, email, user, location, and similar. Its content is pointer-events–none by default so it does not intercept clicks on the input.

<div class="group-input-icon">
  <span class="input-slot-start">
    <svg width="18" height="18" viewBox="0 0 24 24" fill="none" aria-hidden="true">
      <path d="M21 21l-4.3-4.3" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
      <circle cx="11" cy="11" r="7" stroke="currentColor" stroke-width="2"/>
    </svg>
  </span>
  <input class="form-input" type="search" placeholder="Search products">
</div>

Text Symbol in Start Slot

You can use plain text or symbols instead of SVG — useful for currency, unit, or at-sign patterns where a small SVG would be overkill.

<div class="group-input-icon">
  <span class="input-slot-start">@</span>
  <input class="form-input" type="text" placeholder="username">
</div>
@

End Icon Button

The end slot is commonly used for action buttons: password toggle, clear, copy, submit. Children that are button, a, [role="button"], or .is-clickable automatically receive pointer-events: auto so they are interactive.

Always provide an aria-label on icon-only buttons inside the end slot.

<div class="group-input-icon">
  <input class="form-input" type="password" placeholder="Password">
  <span class="input-slot-end">
    <button class="button is-light-outline is-small is-icon" type="button" aria-label="Show password">
      <svg width="16" height="16" viewBox="0 0 24 24" fill="none" aria-hidden="true">
        <path d="M2 12s3.5-6 10-6s10 6 10 6s-3.5 6-10 6S2 12 2 12z" stroke="currentColor" stroke-width="2"/>
        <circle cx="12" cy="12" r="3" stroke="currentColor" stroke-width="2"/>
      </svg>
    </button>
  </span>
</div>

End Slot with Badge

Non-interactive content like a badge or unit label can also sit in the end slot.

<div class="group-input-icon">
  <input class="form-input" type="number" placeholder="Amount">
  <span class="input-slot-end">
    <span class="badge is-light">USD</span>
  </span>
</div>
USD

Start and End Together

Both slots can be used simultaneously. Common for amount inputs, coupon fields, and search bars with a clear button.

<div class="group-input-icon">
  <span class="input-slot-start">$</span>
  <input class="form-input" type="number" placeholder="0.00">
  <span class="input-slot-end">
    <span class="badge is-light">USD</span>
  </span>
</div>
$USD

Multiple Actions in End Slot

The end slot accepts multiple children. They render inline with a small gap between them. Common for search inputs with a clear and a submit button.

<div class="group-input-icon" style="--input-slot-end: 6rem">
  <span class="input-slot-start">
    <svg width="16" height="16" viewBox="0 0 24 24" fill="none" aria-hidden="true">
      <path d="M21 21l-4.3-4.3" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
      <circle cx="11" cy="11" r="7" stroke="currentColor" stroke-width="2"/>
    </svg>
  </span>
  <input class="form-input" type="search" placeholder="Search">
  <span class="input-slot-end">
    <button class="button is-light-outline is-small" type="reset" aria-label="Clear">✕</button>
    <button class="button is-primary is-small" type="submit">Go</button>
  </span>
</div>

Note the --input-slot-end: 6rem set inline on the wrapper above — see Sizing the Slots for why this is required whenever the end slot holds more than one action.

FrontAlign