Firefox DevTools didn’t answer my question, so I tried poking at Claude, then ChatGPT, and by the time I was screen sharing with Gemini 2.0 Flash and arguing out loud with it about the CSS Natalie overheard and took pity on me and stepped in to help.
Her suspicion was that this had something to do with the <dialog> element. I got Claude 3.7 Sonnet to rewrite the code to use a div instead of a dialog and the mysterious gap vanished, which was a strong hint that she was right.
I was using Firefox. Natalie pointed out that Chrome DevTools display default browser styles for elements, so we switched to that and…
Chrome was applying these default styles, including one for max-height:
1
dialog:-internal-dialog-in-top-layer {
2
position: fixed;
3
inset-block-start: 0px;
4
inset-block-end: 0px;
5
max-width: calc(100%-2em-6px);
6
max-height: calc(100%-2em-6px);
7
user-select: text;
8
visibility: visible;
9
overflow: auto;
10
}
The mysterious gap was entirely explained by that max-height: calc(100% - 2em - 6px); rule.
Adding max-height: none to my CSS (or max-height: 100vh) fixed the bug!
That commit landed in November 2020, and those linked issue threads have all sorts of details about how this change came about.
I also found out today that the HTML Living Standard is very much a living standard - the whatwg/html repo has had 12,318 commits, the most recent of which was less than 24 hours ago.
Thanks to uallo on Hacker News I learned Firefox can show browser styles in the inspector, but the option is turned off by default:
I imagine it is off by default because it adds quite a lot of information:
And thanks to that I found html.css in the Firefox source code repository, which lists all of the default styles used in thet browser.
Here’s the full commit history for that html.css stylesheet on the official GitHub mirror.
Update 2: Some backstory on those default user styles#
Chromium engineer Ian Kilpatrick dropped a fascinating comment on Hacker News explaining the backstory for the max-height default rule:
There’s quite a bit of history here, but the abbreviated version is that the dialog element was originally added as a replacement for window.alert(), and there were a libraries polyfilling dialog and being surprisingly widely used.
The mechanism which dialog was originally positioned was relatively complex, and slightly hacky (magic values for the insets).
Changing the behaviour basically meant that we had to add “overflow”, and some form of “max-height”/“max-width” to ensure that the content within the dialog was actually reachable.
The problem is that no browser had (and still has) shipped the “stretch” keyword. (Blink likely will “soon”)
However this was pushed back against as this had to go in a specification - and nobody implemented it (“-webit-fill-available” would have been an acceptable substitute in Blink but other browsers didn’t have this working the same yet).
Hence the calc() variant. (Primarily because of “box-sizing” being the default, and pre-existing border/padding styles on dialog that we didn’t want to touch). […]
Styling an HTML dialog modal to take the full height of the viewport