Skip to content

Commit 7344846

Browse files
authored
Improve "Scroll lock" scrollbar width for Dialog component (#1457)
* improve scroll lock, scrollbarWidth The idea is as follow: If you currently have a scrollbar, and you open a Dialog then we enable a "Scroll lock" so that you can't scroll in the background behind the modal. We can achieve this by adding a `overflow: hidden;` to the `html`. The issue is that by doing this, we lose the scrollbar and therefore the page will jump to right because now there is a bit more room. To account for this, we set a `padding-right` on the `html` of the scrollbarWidth in pixels. This counteracts the visual jump you would see. The issue with this approach is that there could *still* be a scrollbar once we add the `overflow: hidden`. This can happen if you use new css features like the `scrollbar-gutter: stable;`. To take this into account, we will measure the scrollbar again after we set the `overflow: hidden`. Now we will only apply that counteracting offset if there would actually be a jump by measuring the before and after widths and applying the diff if there is one. * update changelog
1 parent 2390615 commit 7344846

File tree

3 files changed

+16
-6
lines changed

3 files changed

+16
-6
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1414
- Improve `FocusTrap` behaviour ([#1432](https://github.com/tailwindlabs/headlessui/pull/1432))
1515
- Simplify `Popover` Tab logic by using sentinel nodes instead of keydown event interception ([#1440](https://github.com/tailwindlabs/headlessui/pull/1440))
1616
- Ensure the `PopoverPanel` is clickable without closing the `Popover` ([#1443](https://github.com/tailwindlabs/headlessui/pull/1443))
17+
- Improve "Scroll lock" scrollbar width for `Dialog` component ([#1457](https://github.com/tailwindlabs/headlessui/pull/1457))
1718

1819
## [Unreleased - @headlessui/react]
1920

@@ -24,6 +25,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2425
- Improve `FocusTrap` behaviour ([#1432](https://github.com/tailwindlabs/headlessui/pull/1432))
2526
- Simplify `Popover` Tab logic by using sentinel nodes instead of keydown event interception ([#1440](https://github.com/tailwindlabs/headlessui/pull/1440))
2627
- Ensure the `Popover.Panel` is clickable without closing the `Popover` ([#1443](https://github.com/tailwindlabs/headlessui/pull/1443))
28+
- Improve "Scroll lock" scrollbar width for `Dialog` component ([#1457](https://github.com/tailwindlabs/headlessui/pull/1457))
2729

2830
## [@headlessui/react@1.6.1] - 2022-05-03
2931

packages/@headlessui-react/src/components/dialog/dialog.tsx

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -255,10 +255,14 @@ let DialogRoot = forwardRefWithAs(function Dialog<
255255
let overflow = documentElement.style.overflow
256256
let paddingRight = documentElement.style.paddingRight
257257

258-
let scrollbarWidth = ownerWindow.innerWidth - documentElement.clientWidth
259-
258+
let scrollbarWidthBefore = ownerWindow.innerWidth - documentElement.clientWidth
260259
documentElement.style.overflow = 'hidden'
261-
documentElement.style.paddingRight = `${scrollbarWidth}px`
260+
261+
if (scrollbarWidthBefore > 0) {
262+
let scrollbarWidthAfter = documentElement.clientWidth - documentElement.offsetWidth
263+
let scrollbarWidth = scrollbarWidthBefore - scrollbarWidthAfter
264+
documentElement.style.paddingRight = `${scrollbarWidth}px`
265+
}
262266

263267
return () => {
264268
documentElement.style.overflow = overflow

packages/@headlessui-vue/src/components/dialog/dialog.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -225,10 +225,14 @@ export let Dialog = defineComponent({
225225
let overflow = documentElement.style.overflow
226226
let paddingRight = documentElement.style.paddingRight
227227

228-
let scrollbarWidth = ownerWindow.innerWidth - documentElement.clientWidth
229-
228+
let scrollbarWidthBefore = ownerWindow.innerWidth - documentElement.clientWidth
230229
documentElement.style.overflow = 'hidden'
231-
documentElement.style.paddingRight = `${scrollbarWidth}px`
230+
231+
if (scrollbarWidthBefore > 0) {
232+
let scrollbarWidthAfter = documentElement.clientWidth - documentElement.offsetWidth
233+
let scrollbarWidth = scrollbarWidthBefore - scrollbarWidthAfter
234+
documentElement.style.paddingRight = `${scrollbarWidth}px`
235+
}
232236

233237
onInvalidate(() => {
234238
documentElement.style.overflow = overflow

0 commit comments

Comments
 (0)