Skip to content

[UI] Combobox/Select/Drawer item text overflows the popup — grid track 1fr cannot shrink #839

Description

@mikamootz

Problem

Long option labels are painted outside the popup background instead of being contained by it. A consumer that adds truncate to the item content gets the same overflow rather than an ellipsis, so there is no way to opt out from the outside.

This is easy to miss with English demo labels and shows up immediately with longer ones (German compounds hit it constantly).

Root Cause

ComboboxItem sizes its content column with grid-cols-[1rem_1fr] (combobox.tsx#L213). 1fr resolves to minmax(auto, 1fr), so the track cannot shrink below the item's min-content width.

The popup frame is clamped — max-w-(--available-width) min-w-(--anchor-width) — but the track inside it is not. When the content is wider than the frame, the frame stops growing and the text keeps going, so it renders next to the background rather than inside it.

Reproduction

Self-contained, no JS framework needed — the frame is pinned at 220px and the positioner variables are hardcoded:

<style>
  .frame { position: relative; display: flex; width: 220px; max-width: 220px;
           border: 1px solid #d4d4d8; border-radius: 8px; background: #fff; }
  .list  { display: flex; flex: 1 1 0%; flex-direction: column; padding: 4px; }
  .item  { display: grid; grid-template-columns: 1rem 1fr; align-items: center;
           gap: 8px; padding: 4px 16px 4px 8px; }
  .body  { grid-column-start: 2; }
</style>

<div class="frame">
  <div class="list">
    <div class="item"><span></span><span class="body">Gefahrgutbeauftragtenbescheinigung</span></div>
  </div>
</div>

Measured in the browser, frame width 222px including the border:

Item Text width Painted outside the frame Ellipsised
as shipped, single long word 243px yes no
as shipped, consumer adds truncate 313px yes no
with minmax(0, 1fr) 164px no yes

The second row is the one that surprised us: adding truncate to the item content does not help, because the track's auto minimum still reserves the full min-content width.

Solution

Give the content track an explicit zero minimum:

- grid-cols-[1rem_1fr]
+ grid-cols-[1rem_minmax(0,1fr)]

No other change is needed — the consumer's truncate then behaves as expected, and items without it wrap instead of overflowing.

Same pattern elsewhere

The identical track appears in three more item components:

Environment: @base-ui/react 1.6, Tailwind 4.1.5.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions