microsoft / microsoft/fluentui

[Bug]: placeholder layout shift during SSR hydration in fluent-dropdown

Open
#36,706 0 comments 0 reactions 2 assignees View on GitHub

@chrisdholt is already working on this.

Since Sep 15, 2026.

Area: SSR Component: Dropdown Fluent UI WC (v3) Type: Bug :bug: web-components
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

  1. Server-render the dropdown using the package's SSR pipeline.
  2. Delay the client-side component definition.
  3. 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.

Image

🤔 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.

Image

😯 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

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.