Missing sidebar during page load causes visual reshuffling of main content
For a brief second when loading a group page the sidebar appears to be empty or missing. As a result of this, the <main>
element is temporarily shifted to the right of the page before it's recalculated and repainted.
While not a big problem, it can be a little jarring during navigation.
It looks like the sidebar is initially set to display:none
, and then set back to block inside a width-based media query. That makes sense because desktop users need a sidebar while mobile users don't.
This is the generated CSS:
#sidebar {
display: none;
width: 300px;
min-width: 300px;
padding: 0.4rem; }
@media (min-width: 840px) {
#sidebar {
display: block;
grid-area: sidebar; } }
Disabling the display:block
rule will hide the sidebar like it does on load, which lets you see how it indents the main content to the right.
(Although maybe not obvious from this screenshot)
What's strange is that the sidebar should be getting set back to block almost immediately after it's removed for desktop users. I'm not seeing what's causing the weird rendering flash. My only guess is that the browser is trying to paint before it hits the media query, and then delays repainting for a brief moment for performance reasons.
I've tested in Chrome 75 and Firefox 67. The problem is fairly easy to reproduce in Chrome, but more intermittent in Firefox. Also I noticed that disabling the cache in Chrome dev tools seemed to make the problem go away. Possibly because it waits longer on the initial paint.
A look through the Performance tab may help show what's going on. I can identify two paints spaced far apart, but I'm not familiar enough with the tool to dive in deeper than that.
As for solutions, I'm still playing around. I tried using visibility:hidden
instead of display:none
because that doesn't reflow content, but it creates problems for mobile users.
Setting a minimum width on the element won't work because it's being removed completely. Setting a margin on <main>
might work, but sort of kills the elegance of grid.
My other idea was to simply move the media query above the display:none
rule. You do have to bump the specificity of the rule though, and unfortunately because we're using IDs instead of classes the only way to do that is using !important
here.
@media (min-width: 840px) {
#sidebar {
display: block !important;
grid-area: sidebar; } }
#sidebar {
display: none;
width: 300px;
min-width: 300px;
padding: 0.4rem; }
But it seems to get rid of the flash. I'm only seeing one major paint in the Performance tab now.
This seems like it might be really situational so I'd suggest running your own tests, and only implementing the fix if you can reproduce.