Home / Snippets / Color /

min-content sizing for buttons

Set width: min-content on a button to shrink it to exactly fit its label text — useful for inline button groups where labels vary in length.

Buttons with width: min-content — each hugs its label
Widely Supported
layoutno-js

Quick implementation

/* Button sized to its label */
.btn-min {
  width: min-content;
  white-space: nowrap; /* prevent label from wrapping */
  padding: 0.5rem 1rem;
  border-radius: var(--radius);
  border: 1px solid oklch(0.52 0.22 265);
  background: oklch(0.52 0.22 265 / 0.15);
  color: oklch(0.72 0.19 265);
  cursor: pointer;
  font: inherit;
  font-weight: 600;
}

/* In a flex row, prevent flex from shrinking the button */
.btn-group {
  display: flex;
  gap: 0.75rem;
  align-items: center;
}

.btn-group .btn-min {
  flex-shrink: 0;
}

Prompt this to your LLM

Includes role, constraints, two framework variants, and edge cases to handle.

You are a senior frontend engineer building compact button groups for a
design system.

Goal: Use width: min-content on buttons so each button shrinks to exactly
fit its label — no fixed widths, no unwanted stretching in flex or grid.

Technical constraints:
- Set width: min-content on the button element.
- Add white-space: nowrap to prevent the label from wrapping, which
  would produce a very narrow tall button.
- Add flex-shrink: 0 when the button is inside a flex container so
  flex cannot compress it below its min-content width.
- Use oklch() for any color values — no hex or rgba.
- Handle very long label text gracefully: if a label is excessively
  long, apply max-width and text-overflow: ellipsis as a safety net.

Framework variant (pick one):
A) Vanilla CSS — .btn-min utility class and .btn-group flex wrapper,
   applicable to any button or anchor element.
B) React component — Button component that accepts label, onClick, and
   variant props; sizes to min-content by default and accepts a
   fullWidth boolean prop to opt into 100% width instead.

Edge cases to handle:
- Very short labels (e.g. "OK") may produce a button narrower than the
  44px WCAG touch target — add min-width: 2.75rem as a floor.
- In CSS grid, buttons stretch to fill cells by default — use
  align-self: start or justify-self: start as an alternative to
  min-content for grid children.
- For RTL layouts, the min-content calculation is the same; no
  directional adjustment is needed since the width is content-based.
- When the label is dynamic and may be empty, ensure the button has
  a minimum visible width so it does not collapse to zero.

Return CSS only (or a React component if variant B).

What min-content sizing means

The min-content keyword resolves to the smallest width at which the element's content avoids overflow. For a button with a text label, that is the width of the label text plus horizontal padding — assuming no line breaks are allowed. This is why white-space: nowrap must accompany width: min-content on buttons: without it, the browser is free to break the label at any space character, producing a very narrow, very tall button.

With white-space: nowrap in place, min-content equals the full single-line width of the label. Each button in a group sizes independently to its own label, so "Save" is narrower than "View details" — no shared fixed width required. This makes button groups self-organizing: add or rename a button and the layout adjusts automatically.

Use cases for button sizing

The most common use case is an inline action group — Save / Cancel, Accept / Decline, Edit / Delete — where each button should wrap its own label without any of them growing to match the widest sibling. This is distinct from a form submit button that should span the full width of its form; those buttons want width: 100%, not min-content.

Another common case is a button inside a card or list item. When the card is inside a grid, grid children default to align-self: stretch; justify-self: stretch, which would otherwise stretch the button to fill the cell. Setting width: min-content on the button overrides this, keeping it compact regardless of the card's width. Alternatively, align-self: start on the button achieves the same visual result without the min-content keyword.

For toolbars and nav bars where every button should have an equal width, min-content is the wrong tool — use a fixed width or min-width instead to align button edges. Reserve min-content for cases where you explicitly want each button sized independently.

Combining with fit-content

The fit-content keyword is a middle ground between min-content and max-content. It allows an element to grow up to its available space but caps it at the element's intrinsic preferred width. For buttons, fit-content behaves the same as min-content in most cases because buttons do not have long runs of unwrapped text that would make the preferred width exceed the available space.

Where fit-content differs is when the button label is genuinely long. With width: min-content; white-space: nowrap, the button will overflow its container if the label is longer than the container. With width: fit-content; white-space: nowrap, the same overflow can occur. For buttons with potentially long dynamic labels, combine width: min-content with a max-width cap and text-overflow: ellipsis to prevent overflow while still sizing tightly for short labels.

Browser support and fallbacks

The min-content keyword for width is part of the CSS Intrinsic and Extrinsic Sizing specification and is in Baseline Widely Available. It is supported in all modern browsers: Chrome, Firefox, Safari, and Edge. No vendor prefixes are required.

For older browsers that do not recognize width: min-content, the declaration is ignored and the button falls back to its default sizing — typically auto, which sizes to content in inline-block and to the flex or grid cell in flex and grid layouts. This fallback is usually acceptable: the layout degrades gracefully to buttons that may be slightly wider, without any broken UI.