Description
In dialog_helper.ts (L88–L91), the connectedCallback of DialogHelperElement reads body.clientWidth and immediately writes to body.style, forcing a synchronous layout/reflow:
this.ownerDocument.body.style.setProperty(
'--dialog-scrollgutter',
`${window.innerWidth - this.ownerDocument.body.clientWidth}px`,
)
Problem
body.clientWidth is a layout-dependent property. Reading it forces the browser to synchronously flush any pending style/layout changes to return an accurate value.
- This runs in
connectedCallback, which is invoked during HTML parsing/page load — a performance-critical phase.
- Every
<dialog-helper> element on the page triggers this, so pages with multiple dialogs pay the cost multiple times.
- This can negatively impact Core Web Vitals (LCP, INP) and overall page load performance.
Suggested fix
Defer the read/write to a requestAnimationFrame callback to avoid blocking initial render:
requestAnimationFrame(() => {
this.ownerDocument.body.style.setProperty(
'--dialog-scrollgutter',
`${window.innerWidth - this.ownerDocument.body.clientWidth}px`,
)
})
Alternatively, consider whether this can be solved purely in CSS (e.g., using scrollbar-gutter: stable where supported), eliminating the JavaScript measurement entirely.
Additional context
- It may also be worth deduplicating this work — since
--dialog-scrollgutter is set on document.body, only one <dialog-helper> needs to compute it, not every instance.
- The
click event listener registered on document at L86 also lacks deduplication and could be registered multiple times if multiple <dialog-helper> elements exist.
Description
In
dialog_helper.ts(L88–L91), theconnectedCallbackofDialogHelperElementreadsbody.clientWidthand immediately writes tobody.style, forcing a synchronous layout/reflow:Problem
body.clientWidthis a layout-dependent property. Reading it forces the browser to synchronously flush any pending style/layout changes to return an accurate value.connectedCallback, which is invoked during HTML parsing/page load — a performance-critical phase.<dialog-helper>element on the page triggers this, so pages with multiple dialogs pay the cost multiple times.Suggested fix
Defer the read/write to a
requestAnimationFramecallback to avoid blocking initial render:Alternatively, consider whether this can be solved purely in CSS (e.g., using
scrollbar-gutter: stablewhere supported), eliminating the JavaScript measurement entirely.Additional context
--dialog-scrollgutteris set ondocument.body, only one<dialog-helper>needs to compute it, not every instance.clickevent listener registered ondocumentat L86 also lacks deduplication and could be registered multiple times if multiple<dialog-helper>elements exist.