microsoft / microsoft/fluentui
[Bug]: placeholder layout shift during SSR hydration in fluent-dropdown
@chrisdholt is already working on this.
Since Sep 15, 2026.
- Dominant language
- TypeScript
- Stars
- 20.3k
- Forks
- 2.9k
- Avg merge
- 2d 9h
- Merged PRs (30d)
- 46
Description
🐛 Bug Report
A server-rendered fluent-dropdown with a placeholder renders an empty control before the custom element upgrades. Hydration inserts the control button and placeholder text, causing a visible layout shift.
💻 Repro or Code Sample
- Server-render the dropdown using the package's SSR pipeline.
- Delay the client-side component definition.
- Compare the dropdown before and after hydration.
<fluent-dropdown placeholder="Select a fruit">
<fluent-listbox>
<fluent-option value="apple">Apple</fluent-option>
<fluent-option value="banana">Banana</fluent-option>
</fluent-listbox>
</fluent-dropdown>
<script type="module">
setTimeout(
() => import("@fluentui/web-components/dropdown/define.js"),
2000,
);
</script>
Before the definition loads, the control has no placeholder. Once the component upgrades, the placeholder and default control styling appear and its bounds change.
🤔 Expected Behavior
The server-rendered dropdown should display its placeholder with the same dimensions and styling as the hydrated control. Hydration should not produce a layout shift or visible change.
😯 Current Behavior
The SSR control slot has no fallback content. The internal button is created during component initialization, so the placeholder remains absent while the element is undefined.
Hydration inserts the button and placeholder text and applies the default outline styling. The pre-hydration and post-hydration screenshots and bounding boxes differ, and Chromium records a layout-shift event without recent user input.
💁 Possible Solution
Render an aria-hidden placeholder as fallback content in the control slot, then style it to match the generated control. Pre-definition CSS should also represent the default placeholder color and outline appearance.
I have a local fix and can submit it.
🔦 Context
This affects server-rendered applications that defer or stream client JavaScript. Users see an empty dropdown change size or appearance when hydration completes, which contributes to cumulative layout shift.
🌍 Your Environment
- OS & Device: macOS on Mac
- Browser: Chromium
- Version:
@fluentui/web-components@3.1.2
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.