Yeah - this was arguably mostly my fault (sorry!).
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:auto", and some form of "max-height"/"max-width" to ensure that the content within the dialog was actually reachable.
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:content-box" being the default, and pre-existing border/padding styles on dialog that we didn't want to touch).
One thing to keep in mind is that any changes that changes web behaviour is under some time pressure. If you leave something too long, sites will start relying on the previous behaviour - so it would have been arguably worse not to have done anything.
It may still be possible to change to the stretch variant, however likely some sites are relying on the extra "space" around dialogs now, and would be mad if we changed it again. This might still be a net-positive however given how much this confuses web-developers (future looking cost), vs. the pain (cost) of breaking existing sites.
I wonder, do you think "hidden" behaviors like this discourage lazier devs from using HTML standards and just use divs for everything and reimplement default functionality with 3rd party UI libs?
Seems like a good example of depending on LLMs too much. After the first bad output the next step should have been to open inspector, not to try three more LLMs.
Browser vendors put a lot of surprising, and very poorly documented, defaults into user agent stylesheets, and they can trip you up at the most basic level, and the styling is poorly exposed in most web inspector tooling.
I ran into a nasty one with Safari’s date picker—had to go down a lot of rabbit holes to figure out I needed to finesse the `::-webkit-date-and-time-value` CSS to get an input field styled correctly.
I've found that the "Computed Styles" section catches most weirdness quite easily. Remove your own styles, view Computed and you'll see "User agent style sheet" as the source.
Even if you don't look at the computed styles, the user agent styles are shown in the default element style view, at least in Firefox. There, you can see all of the applied styles as a stack, so you can see which styles have been applied first, which ones have been overridden, etc.
This is a good place to look if you're trying to figure out why an element is behaving weirdly, because it shows all the styles and exactly how they override each other, as well as the source of each style.
Something I discovered while changing the thumb track of a range slider just the other day, is if you add padding-top to the thumb, it will also add padding to the bottom.
Even better, you have to set its appearance to none for chromium before you're able to style it in any capacity, which probably makes sense to somebody but not to me.
I'd looked in the inspector after the first time I saw the gap (just added a note about that to the document) - my problem was that I didn't realize Firefox doesn't show you the default user agent styles, while Chrome does.
That's how <b> tags are made bold etc. There's a css file that's basically loaded before everything else to apply those default styles. Here's WebKit/Safari's for example:
Thanks! I had no idea. I have an issue with a large gap on mobile I should dig into. Maybe this will help me figure out how to fix it. Also just a neat fact to know regardless
> The spec lives in GitHub in a 7MB source file which is too large to view through the GitHub web interface
It's a bit offtopic, but think about it: cannot view the doc despite its size is only 7Mb ~ about 0.04 percent of a typical computer's memory (16Gb). We can open and view PDFs much bigger and search there without an issue in browser. We can view movies worth half of the memory.
But it's surprisingly not possible to view a 7Mb text file in the professional tool for working with textual source code called github. Shame. And sad.
The file is 142k lines line that GitHub would have to turn into HTML and the browser would have to render immediately.
The browser is perfectly able to render the raw file (you can try it yourself) but everything that goes with it would be asking a bit much, particularly because the intent of the author was to blame the file, therefore adding yet more information/elements to the page.
While browsers nor GitHub are beacons of performance, I don’t think it's fair in this case.
PDFs can be rendered page by page and each page is self-contained. Same with videos, where you read the index and jump to the key frame you're onto, reading data in a highly optimized and parallelized way (often down to the chip). With HTML you must render every letter that comes before line 100000 before rendering line 100000
> The file is 142k lines line that GitHub would have to turn into HTML and the browser would have to render immediately.
GitHub's new, React-based code viewer aggressively virtualizes the rendered text. Only the lines visible in the viewport, together with 10-20 lines around the viewport, will be rendered. This is why search is broken when using the native browser search (not all text is rendered).
As another comment pointed out, VS Code is capable of opening such large files with syntax highlighting, minimap, etc. VS Code is also employing some form of virtualization. It's unclear why GitHub's file viewer refuses to show files larger than a megabyte or so.
GitHub does not load VS Code on a page load, so you can't expect it to have the same performance. Evidently they themselves know it can't handle that file efficiently.
> GitHub's new, React-based code viewer aggressively virtualizes the rendered text. Only the lines visible in the viewport, together with 10-20 lines around the viewport, will be rendered.
I'm sad that the No-React forces within GitHub (presumably) eventually lost that battle. There's React all over GitHub now and it's resulting in so many weird glitches like this.
The file viewer is especially strange. Scrolling is janky on iOS (presumably they are trying to control scroll position and this interferes with Safari's scroll bar). Last time I looked into the file viewer, I believe it was rendered as a web component with its own shadow DOM and a react root inside.
Although off-topic for this thread, one minor annoyance is how the "improved" Issues interface no longer displays pagination controls until several megabytes of JavaScript finish loading. Meanwhile the Pull Request page, one of the oldest parts of the GitHub interface, is capable of displaying pagination controls before JavaScript loads, and it's interactive (i.e. clicking on pagination buttons will work as expected, even without JavaScript).
Want to note that web-based UI doesn't have to be this way. In the case of rendering text with syntax highlighting, VS Code shows that it can be done in a performant manner. As for functionality without JavaScript, embracing standard web APIs, etc., that is exactly what frameworks like React Router (formerly Remix) are designed for.
I'm not surprised to learn anything because I worked at GitHub before.
GitHub is not VS Code. GitHub is a Ruby on Rails website with some React sprinkled on. You can't expect the same performance optimization from a website that a whole IDE has.
This is also one of the use-cases I built the Tachi Code browser extension for. It injects a monaco-based editor into the current page when it detects you're viewing a raw file (i.e., the page's rendered body contains nothing other than a <pre> tag).
The fundamental difference is a dialog isn’t forced to be addressed by the user at any time, and lacks the alert dialog[0] role, at least I don’t see any of this in the example code.
I know this seems like pedantic criticism however my hope is to spread some information about the (very real) differences between a dialog and a modal, even though the dialog API doesn’t do a good enough job distinguishing this
[0]: The alertdialog role is to be used on modal alert dialogs that interrupt a user's workflow to communicate an important message and require a response
My goal here is absolutely to use the dialog element as a modal - I thought that was what it was for, and that using it in this way has significant accessibility benefits.
It is what the element is for. It can be used for both a dialog or modal UI widget. And it can significantly streamline accessibility.
MDN has a good overview of the aria attributes associated with modal[0][1] and some more explainer on the dialog API[2]
The long and short of it though is modal dialog is generally expected to halt user progression until dealt, where as a non modal dialog does not halt user progression and can be safely ignored from a user perspective.
The differences are definitely subtle. It’s also why the dialog element has .show and .showModal as an API, they aren’t synonymous, they actually set different contexts implicitly for accessibility reasons.
This is in part some of the criticism that people have of the dialog element, FWIW. There was a debate prior to its introduction to break these two UI patterns into separate elements, one being <dialog> and the other being <modal> so their semantics could be obvious and more easily preserved.
I believe the additional complexity wasn’t worth the cost but it does leave this confusing situation about modal vs dialog around.
To the create of the committee though it does go a long way in addressing both concerns, even at the cost of “obviousness”
So for the https://tools.simonwillison.net/side-panel-dialog example - where clicking on an item opens up a "details" view in a side panel, which can then be dismissed - is the way I'm using dialog appropriate? If not, how should I use it instead?
It looks to me like you’re using the dialog API well enough, but your background content isn’t inert, I can still scroll it, and if I wasn’t on mobile I’d see if tab would break the modal sandbox, as I suspect it might.
You should try using this with a screen reader if you’re able, that’ll let you know where you may need further improvement.
Right now the behavior on the page is that of a dialog and you’re using the (correct if you want a modal) modal API, that will cause issues for users
You should also use the autofocus attribute if you want the modal to focus on something other than the close icon in the corner upon opening
> 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.
I understand their mission of capturing the messy real-world usages of web technologies and distilling them into a standard, paving the cowpaths etc etc.
But I don't see how anything can be called a standard that updates daily.
In the year 2525, if man is still alive, he may find he has a web page from an unknown time period. To read it, all he'll need to do is reimplement all standards for the previous 500 years. Version numbers wouldn't make this easier at all, somehow.
And after all their efforts to get the unknown markup into an document form, they'll convert it's contents into the dominant information format of the 26th century: PDF.
To see all commits that have touched lines 120-150 in filename.txt, and see those lines. Gives a view into a subset of lines but won't help if the code in question moved out of the line range.
In Jetbrains you select a line of code and say "show history for selection" and it parses all that for you and just gives you a history of commits affecting that specific line. It's got a built in commit browser and visual diff tool.
Not sure about a GUI way of doing this, but in the CLI, I use `git log --patch [path]` all the time. It will show you the history of diffs for that one file.
the article notes some accessibility issues, those have been resolved.
on edit: misread title as take full size of the viewport, and not full height. So not necessarily applicable but keep it up as I think it is sort of an interesting Modal strategy.
Yeah - this was arguably mostly my fault (sorry!).
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:auto", and some form of "max-height"/"max-width" to ensure that the content within the dialog was actually reachable.
The better solution to this was to add "max-height:stretch", "max-width:stretch". You can see the discussion for this here: https://github.com/whatwg/html/pull/5936#discussion_r5136422...
The problem is that no browser had (and still has) shipped the "stretch" keyword. (Blink likely will "soon" - https://groups.google.com/a/chromium.org/g/blink-dev/c/SiZ2n... )
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:content-box" being the default, and pre-existing border/padding styles on dialog that we didn't want to touch).
One thing to keep in mind is that any changes that changes web behaviour is under some time pressure. If you leave something too long, sites will start relying on the previous behaviour - so it would have been arguably worse not to have done anything.
It may still be possible to change to the stretch variant, however likely some sites are relying on the extra "space" around dialogs now, and would be mad if we changed it again. This might still be a net-positive however given how much this confuses web-developers (future looking cost), vs. the pain (cost) of breaking existing sites.
Sorry!
Thanks for the details!
I wonder, do you think "hidden" behaviors like this discourage lazier devs from using HTML standards and just use divs for everything and reimplement default functionality with 3rd party UI libs?
A fair few will also just reset all css to avoid having to deal with different browsers opinionated stylings.
Whoa, thanks for the detailed backstory!
Seems like a good example of depending on LLMs too much. After the first bad output the next step should have been to open inspector, not to try three more LLMs.
No, this is one of those bizarre “wait, really, they put that in the default stylesheet” problems.
There is a lot of weirdness lurking in the default user agent stylesheet…especially in Safari: https://blog.jim-nielsen.com/2021/things-i-learned-reading-w...
Browser vendors put a lot of surprising, and very poorly documented, defaults into user agent stylesheets, and they can trip you up at the most basic level, and the styling is poorly exposed in most web inspector tooling.
I ran into a nasty one with Safari’s date picker—had to go down a lot of rabbit holes to figure out I needed to finesse the `::-webkit-date-and-time-value` CSS to get an input field styled correctly.
I've found that the "Computed Styles" section catches most weirdness quite easily. Remove your own styles, view Computed and you'll see "User agent style sheet" as the source.
Even if you don't look at the computed styles, the user agent styles are shown in the default element style view, at least in Firefox. There, you can see all of the applied styles as a stack, so you can see which styles have been applied first, which ones have been overridden, etc.
This is a good place to look if you're trying to figure out why an element is behaving weirdly, because it shows all the styles and exactly how they override each other, as well as the source of each style.
Something I discovered while changing the thumb track of a range slider just the other day, is if you add padding-top to the thumb, it will also add padding to the bottom.
Even better, you have to set its appearance to none for chromium before you're able to style it in any capacity, which probably makes sense to somebody but not to me.
I don’t think those 2 problems are mutually exclusive.
I'd looked in the inspector after the first time I saw the gap (just added a note about that to the document) - my problem was that I didn't realize Firefox doesn't show you the default user agent styles, while Chrome does.
In FF DevTools, open settings, under "Inspector" check the box for "Show Browser Styles." It clutters the window up some, but I've gotten used to it.
So things can be styled based on the user agent? Besides the obvious difference between mobile and desktop.
That's how <b> tags are made bold etc. There's a css file that's basically loaded before everything else to apply those default styles. Here's WebKit/Safari's for example:
https://github.com/WebKit/WebKit/blob/main/Source/WebCore/cs...
Try turning on user agent styles & user agent shadow dom in your dev tools settings.
Yeah, that's why I thought this was worth writing up as a TIL.
Thanks! I had no idea. I have an issue with a large gap on mobile I should dig into. Maybe this will help me figure out how to fix it. Also just a neat fact to know regardless
At that point in the article, I thought Natalie was some new LLM I hadn't heard about.
Seriously. This would have been trivial with a few second look in inspector.
If your only tool is a hammer then everything looks like a nail.
You are the nail in this metaphor, asking for different hammers to hit you.
> The spec lives in GitHub in a 7MB source file which is too large to view through the GitHub web interface
It's a bit offtopic, but think about it: cannot view the doc despite its size is only 7Mb ~ about 0.04 percent of a typical computer's memory (16Gb). We can open and view PDFs much bigger and search there without an issue in browser. We can view movies worth half of the memory.
But it's surprisingly not possible to view a 7Mb text file in the professional tool for working with textual source code called github. Shame. And sad.
The file is 142k lines line that GitHub would have to turn into HTML and the browser would have to render immediately.
The browser is perfectly able to render the raw file (you can try it yourself) but everything that goes with it would be asking a bit much, particularly because the intent of the author was to blame the file, therefore adding yet more information/elements to the page.
While browsers nor GitHub are beacons of performance, I don’t think it's fair in this case.
PDFs can be rendered page by page and each page is self-contained. Same with videos, where you read the index and jump to the key frame you're onto, reading data in a highly optimized and parallelized way (often down to the chip). With HTML you must render every letter that comes before line 100000 before rendering line 100000
> The file is 142k lines line that GitHub would have to turn into HTML and the browser would have to render immediately.
GitHub's new, React-based code viewer aggressively virtualizes the rendered text. Only the lines visible in the viewport, together with 10-20 lines around the viewport, will be rendered. This is why search is broken when using the native browser search (not all text is rendered).
As another comment pointed out, VS Code is capable of opening such large files with syntax highlighting, minimap, etc. VS Code is also employing some form of virtualization. It's unclear why GitHub's file viewer refuses to show files larger than a megabyte or so.
GitHub does not load VS Code on a page load, so you can't expect it to have the same performance. Evidently they themselves know it can't handle that file efficiently.
> GitHub's new, React-based code viewer aggressively virtualizes the rendered text. Only the lines visible in the viewport, together with 10-20 lines around the viewport, will be rendered.
Then why is it so fucking slow all of the time?
I'm sad that the No-React forces within GitHub (presumably) eventually lost that battle. There's React all over GitHub now and it's resulting in so many weird glitches like this.
The file viewer is especially strange. Scrolling is janky on iOS (presumably they are trying to control scroll position and this interferes with Safari's scroll bar). Last time I looked into the file viewer, I believe it was rendered as a web component with its own shadow DOM and a react root inside.
Although off-topic for this thread, one minor annoyance is how the "improved" Issues interface no longer displays pagination controls until several megabytes of JavaScript finish loading. Meanwhile the Pull Request page, one of the oldest parts of the GitHub interface, is capable of displaying pagination controls before JavaScript loads, and it's interactive (i.e. clicking on pagination buttons will work as expected, even without JavaScript).
Want to note that web-based UI doesn't have to be this way. In the case of rendering text with syntax highlighting, VS Code shows that it can be done in a performant manner. As for functionality without JavaScript, embracing standard web APIs, etc., that is exactly what frameworks like React Router (formerly Remix) are designed for.
You might be surprised to learn that VS Code renders its viewport with HTML and it has no issues displaying this file.
I'm not surprised to learn anything because I worked at GitHub before.
GitHub is not VS Code. GitHub is a Ruby on Rails website with some React sprinkled on. You can't expect the same performance optimization from a website that a whole IDE has.
Indeed.
This is also one of the use-cases I built the Tachi Code browser extension for. It injects a monaco-based editor into the current page when it detects you're viewing a raw file (i.e., the page's rendered body contains nothing other than a <pre> tag).
Tachi Code for Chrome: https://chromewebstore.google.com/detail/tachi-code/acoecgia...
Tachi Code for Firefox: https://addons.mozilla.org/en-US/firefox/addon/tachi-code/
7mb is a LOT of text. More than most epic fantasy novels.
While surely the text fits, it’s all the stuff around it like rendering and layout that take the memory.
> I was using Firefox. Natalie pointed out that Chrome DevTools display default browser styles for elements [...]
So does Firefox. Enable "Show Browser Styles" in the developer tools settings.
Thanks, that's useful - I added that to the document: https://til.simonwillison.net/css/dialog-full-height#user-co...
... which also lead me to the html.css stylesheet in the Firefox source code, a really useful reference: https://searchfox.org/mozilla-central/source/layout/style/re...
Here's a GitHub mirror with a commit log view showing changes over time: https://github.com/mozilla/gecko-dev/commits/master/layout/s...
- WHATWG https://html.spec.whatwg.org/multipage/rendering.html#render...
- Firefox https://hg.mozilla.org/mozilla-central/file/tip/layout/style...
- Chromium https://source.chromium.org/chromium/chromium/src/+/main:thi...
- Webkit https://github.com/WebKit/WebKit/blob/main/Source/WebCore/cs...
What you built is a dialog, not a modal.
The fundamental difference is a dialog isn’t forced to be addressed by the user at any time, and lacks the alert dialog[0] role, at least I don’t see any of this in the example code.
I know this seems like pedantic criticism however my hope is to spread some information about the (very real) differences between a dialog and a modal, even though the dialog API doesn’t do a good enough job distinguishing this
[0]: The alertdialog role is to be used on modal alert dialogs that interrupt a user's workflow to communicate an important message and require a response
Please tell me more!
My goal here is absolutely to use the dialog element as a modal - I thought that was what it was for, and that using it in this way has significant accessibility benefits.
It is what the element is for. It can be used for both a dialog or modal UI widget. And it can significantly streamline accessibility.
MDN has a good overview of the aria attributes associated with modal[0][1] and some more explainer on the dialog API[2]
The long and short of it though is modal dialog is generally expected to halt user progression until dealt, where as a non modal dialog does not halt user progression and can be safely ignored from a user perspective.
The differences are definitely subtle. It’s also why the dialog element has .show and .showModal as an API, they aren’t synonymous, they actually set different contexts implicitly for accessibility reasons.
This is in part some of the criticism that people have of the dialog element, FWIW. There was a debate prior to its introduction to break these two UI patterns into separate elements, one being <dialog> and the other being <modal> so their semantics could be obvious and more easily preserved.
I believe the additional complexity wasn’t worth the cost but it does leave this confusing situation about modal vs dialog around.
To the create of the committee though it does go a long way in addressing both concerns, even at the cost of “obviousness”
[0]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/A...
[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/A...
[2]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/di...
So for the https://tools.simonwillison.net/side-panel-dialog example - where clicking on an item opens up a "details" view in a side panel, which can then be dismissed - is the way I'm using dialog appropriate? If not, how should I use it instead?
Code is here: https://github.com/simonw/tools/blob/main/side-panel-dialog....
Key code is that when you click an item it effectively does this:
I think this is a modal, because it's meant to entirely take focus from the rest of the page (until you dismiss the side panel).It looks to me like you’re using the dialog API well enough, but your background content isn’t inert, I can still scroll it, and if I wasn’t on mobile I’d see if tab would break the modal sandbox, as I suspect it might.
You should try using this with a screen reader if you’re able, that’ll let you know where you may need further improvement.
Right now the behavior on the page is that of a dialog and you’re using the (correct if you want a modal) modal API, that will cause issues for users
You should also use the autofocus attribute if you want the modal to focus on something other than the close icon in the corner upon opening
I just added a toggle to https://tools.simonwillison.net/side-panel-dialog that switches between show() and showModal() to help me explore the differences.
For what it’s worth, the “normal” value of max-height is none, not inherit or 100vh.
Thanks, I applied that fix (to the document and the example code).
> 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.
I understand their mission of capturing the messy real-world usages of web technologies and distilling them into a standard, paving the cowpaths etc etc.
But I don't see how anything can be called a standard that updates daily.
Look at the actual commit.
https://github.com/whatwg/html/commit/85effead0a5df3742ebe29...
A document of this size will have typos, require clarification, get reorganized. It didn’t fundamentally change here.
In the year 2525, if man is still alive, he may find he has a web page from an unknown time period. To read it, all he'll need to do is reimplement all standards for the previous 500 years. Version numbers wouldn't make this easier at all, somehow.
It will still be served on IPv4 tho.
And after all their efforts to get the unknown markup into an document form, they'll convert it's contents into the dominant information format of the 26th century: PDF.
The 8px of body margin is one default style that always catches me off guard. Every time I build a layout I stub my toe on "why do I have overflow?".
Is there a git gui/extension/etc which makes exploring the git blame similar to what the author did easier? Here is what I find myself doing often:
- blame on file
- scroll to line 123, click on commit to see the change
- ok, that commit wasn’t the “meaningful change” I’m looking for
- click on parent commit
- browse files (for that sha)
- go to file
- click blame
- scroll to line 123 (or similar)
- repeat
Perhaps not exactly but you can run:
To see all commits that have touched lines 120-150 in filename.txt, and see those lines. Gives a view into a subset of lines but won't help if the code in question moved out of the line range.If I’m looking for code changes:
If it’s commit messages I’m interested in: Sometimes I want to know “all the commits that introduced a pattern”: This last one I use frequently enough that I wrote a little shell script for it, called "git-blep" (for "blame-grep")———
If there’s a function name that you’re logging, then you might get mileage from
Though that probably would not have worked in the original author’s case.In Jetbrains you select a line of code and say "show history for selection" and it parses all that for you and just gives you a history of commits affecting that specific line. It's got a built in commit browser and visual diff tool.
Link (not much info there): https://www.jetbrains.com/help/idea/investigate-changes.html...
Not sure about a GUI way of doing this, but in the CLI, I use `git log --patch [path]` all the time. It will show you the history of diffs for that one file.
The firefox/browser styles tip is greatly appreciated
The fullscreen api allows you to make any element fullscreen.
https://blog.logrocket.com/experimenting-with-fullscreen-api...
the article notes some accessibility issues, those have been resolved.
on edit: misread title as take full size of the viewport, and not full height. So not necessarily applicable but keep it up as I think it is sort of an interesting Modal strategy.
At this point I’m no longer shocked by shoddy poor defaults for elements or “user agent style” as they like to call it.