That's a mouthful title alright !!
But this was a challenge which was organized at the end of a Web Performance Bootcamp held by team devkode (founder - Sunny Puri) on JavaScript Meetup (co-organizer NC Patro) platform. If you're interested in knowing my experience of the same, then here is the link but we will focus more on the challenge here.
Problem Statement :-
When you open and close the amazon.com sidebar, paint flashing occurs which can be eliminated via CSS modification. So you're required to identify those changes and submit the same.
If you're unfamiliar with terms like layout, paint and composition, I would recommend you to go through CRP link to get a know how so you can better relate with the solution ahead.
Alright, so how to first visualize this paint flashing stuff ?
To start with, let's go to amazon.com and there, we will take help of our age old friend DevTools :-
After opening the DevTools, lets do Ctrl/Command + Shift + P to open the Command Menu. Search for Show paint flashing rectangles and select that option.
Now if you try to interact with the left hamburger icon used to open/close the sidebar, you will see green flashing rectangles on the screen indicating paint pipeline is triggered. And it is this paint, we aim to eliminate.
Alright so now we visualize the problem and before I go on to explain the solution, you can also try arriving at the solution. Also, I want you to know that it took me 1.5 hours to identify the CSS modifications. You might take less or more time since that's all relative.
Did you try it ?
Yes/No ? (Drop in the comment section)
I identified two main elements that were responsible for this paint flashing :-
the CSS class
lock-position
onbody
tagthe sidebar element with id of
hmenu-container
body.lock-position
Consider the following CSS when sidebar is open :-
body.lock-position {
overflow: hidden;
}
This is used by Amazon to prevent the scroll of page content when the sidebar is open. Now if we go to css triggers to see the layout, paint and composition cost of the same, here is what we will find :-
Both overflow-x
and overflow-y
together combined are equivalent to overflow
CSS property and as we can see a change in this triggers the layout pipeline making it an expensive operation.
If we remove, the overflow:hidden
from body.lock-position
, you will notice that while closing the sidebar, there is no more paint flashing but while opening there still is (Obviously, now the when the sidebar is open, a user can scroll through page content but that was not a constraint). We will eliminate the leftover paint flashing next.
The result till now :-
#hmenu-container
Consider the following CSS when sidebar is closed :-
#hmenu-container {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
visibility: hidden;
z-index: 100000;
}
Consider the following CSS then sidebar is open:-
#hmenu-container.hmenu-visible {
visibility: visible;
}
You will notice that visibility
CSS property initially takes a value of hidden
and on click of hamburger icon changes to visible
. Now let's go to css triggers to know what part of layout, paint and composition does visibility
trigger :-
Now in the bootcamp, there was a certain section where it was talked about how transform
CSS property is used to perform UI changes on a separate layer via the compositor thread and will-change
CSS property let's the browser know beforehand how an element is expected to change so it can promote the element to a separate layer as an optimization.
Let's look at how transform
works from css triggers:-
Cool lets use the above for the final piece of our solution :-
#hmenu-container {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
will-change:transform;
transform: translateX(-100%);
z-index: 100000;
}
#hmenu-container.hmenu-visible {
transform: translateX(0);
}
To mimic sidebar being closed, we can add transform: translateX(-100%);
to #hmenu-container
which will shift the whole container to left by 100% of it's width.
And to mimic sidebar being open, we can add transform: translateX(0);
to #hmenu-container.hmenu-visible
which will show the whole container in current viewport.
Here is the final result :-
Note:- The above will work even without will-change:transform
since that's an additional optimization of promoting #hmenu-container
to another layer before the sidebar is made to open.
And that's it for the solution. This challenge was fun because it integrated what we learned at the bootcamp. Also I think the other participants who completed the challenge might have had other approaches. So if you figure out some other way, do share the same in the comments ๐.
P.S. - Btw if you're wondering about those slick looking keyboard keys support in markdown, check out this. Also the cover image is generated using this awesome web-app by Savio Martin.