From 54a40bf1cf7509f3372ffe20f0d82662099c40ad Mon Sep 17 00:00:00 2001 From: Francesco Manicardi Date: Thu, 13 Aug 2026 14:05:25 +0200 Subject: [PATCH] fix(material/dialog): reserve room for touch targets in scrollable content `mat-dialog-content` scrolls, and its block-end padding is zero when the dialog has an actions row. Buttons, checkboxes and radios center a 48px touch target on a 40px control, and slide toggles center one on a 32px switch, so the target overhangs the control by 4-8px. An overhanging target at the end of the content is scrollable overflow, so a dialog whose content ends in one of those controls paints a scrollbar over content that fits. Reserve the overhang in the block-end padding instead. This keeps the touch targets at their accessible size, which the alternatives do not: disabling them (`touch-target-display: none`) shrinks the tap area, and anchoring them so they only overhang the block-start edge still left 4px of overflow in WebKit in local testing. Verified with a stock Material app in Chromium, Firefox and WebKit. A dialog with a trailing checkbox, radio, slide toggle or button goes from 4px, 4px, 8px and 4px of scrollable overflow respectively to 0 in all three engines. Dialogs with actions grow by 8px, which is the trade-off for not touching the tap areas. Fixes #29164. --- src/material/dialog/_m3-dialog.scss | 4 +++- src/material/dialog/dialog.scss | 9 ++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/material/dialog/_m3-dialog.scss b/src/material/dialog/_m3-dialog.scss index d9b924c2f8f3..c6575df436b0 100644 --- a/src/material/dialog/_m3-dialog.scss +++ b/src/material/dialog/_m3-dialog.scss @@ -23,7 +23,9 @@ dialog-container-small-max-width: calc(100vw - 32px), dialog-content-padding: 20px 24px, dialog-headline-padding: 6px 24px 13px, - dialog-with-actions-content-padding: 20px 24px 0, + // The block-end value reserves room for the touch targets of any controls at the end of + // the content, which would otherwise be scrollable overflow. See dialog.scss. + dialog-with-actions-content-padding: 20px 24px 8px, ), color: ( dialog-container-color: map.get($system, surface), diff --git a/src/material/dialog/dialog.scss b/src/material/dialog/dialog.scss index a5a58edf73de..ea13623af613 100644 --- a/src/material/dialog/dialog.scss +++ b/src/material/dialog/dialog.scss @@ -191,8 +191,15 @@ $fallbacks: m3-dialog.get-tokens(); // Note: we can achieve this with a `:has` selector, but it results in an // increased specificity which breaks a lot of internal clients. + // + // The block-end padding reserves room for the touch targets of the controls the content may + // contain. Buttons, checkboxes and radios center a 48px touch target on a 40px control and + // slide toggles center one on a 32px switch, so the target overhangs the control by up to + // 8px. Since this element scrolls, an overhanging target at the end of the content is + // scrollable overflow, and the dialog shows a scrollbar over content that fits. Reserving + // the overhang fixes it without shrinking the targets below their accessible size. .mat-mdc-dialog-container-with-actions & { - padding: token-utils.slot(dialog-with-actions-content-padding, $fallbacks, 20px 24px 0); + padding: token-utils.slot(dialog-with-actions-content-padding, $fallbacks, 20px 24px 8px); } .mat-mdc-dialog-container .mat-mdc-dialog-title + & {