As mentioned in the topic related to Pierre's box-shadow answer, drawing is expensive. Explaining why it is expensive would require a deep understanding of how rendering works, and I donβt have enough knowledge to fully explain it. But this answer tries to explain why the whole page is redrawn and various possible methods to avoid this.
According to the CSS triggers website :
Changing the shadow of the shadows does not cause any geometry changes, which is good. But since this is a visual property, it will trigger drawing . Painting is usually an extremely expensive operation , so you must be careful.
As soon as all the pixels are colored, the page will be arranged.
Why is the whole page redrawn every time?
The following articles explain how the picture really works at a high level:
Based on these articles, we see that each node in the DOM tree that creates visual output is considered as a RenderObject and each RenderObject is part of the RenderLayer directly or indirectly. Whenever a change occurs, the renderer (or rendering object) invalidates its rectangle (or RenderLayer) on the screen and starts the redraw.
In this case, it seems that the whole page is redrawn because the #test element #test not guarantee the creation of a separate RenderLayer (based on the criteria mentioned in the Chromium Project article) and therefore becomes part of the root rendering layer. Since this is part of the root rendering layer, the entire page is redrawn every time repainting is required.
the following fragment proves that the above statement is true . Here I added the #cover element (with positioning) to enclose the #test element. Now, since the #cover element has explicit positioning, it creates an extra layer above the root layer, and #test becomes part of this intermediate layer. Now we see that the box-shadow transition redraws only this intermediate layer, and not the entire page.
html, body { height: 100%; } #cover { position: relative; } #test { background: red; height: 100px; width: 200px; transition: box-shadow 0.5s; } #test:hover { box-shadow: 0 0 3px 3px rgba(0, 0, 0, 0.3); }
<div id=cover> <div id=test></div> </div>
What's the solution?
There are various CSS properties that can be used to solve this problem, but they all seem to point to the same point at a high level, that is, to create a separate rendering layer for the #test element.
Below are a few possible options for creating a separate rendering layer for the #test element:
Adding explicit position properties is the same parameter described in Pierre's answer, but absolute positioning is not the only option. Even relative positioning will solve it.
html, body { height: 100%; } #test { position: relative; background: red; height: 100px; width: 200px; transition: box-shadow 0.5s; } #test:hover { box-shadow: 0 0 3px 3px rgba(0, 0, 0, 0.3); }
<div id=test></div>
Adding transparency (opacity) - Browsers seem to consider even opacity: 0.99 as adding transparency, and this is very useful because adding this makes no visual difference.
html, body { height: 100%; } #test { background: red; height: 100px; width: 200px; opacity: 0.99; transition: box-shadow 0.5s; } #test:hover { box-shadow: 0 0 3px 3px rgba(0, 0, 0, 0.3); }
<div id=test></div>
Adding a dummy CSS filter - we could add filter: blur(0px) as it did nothing.
html, body { height: 100%; } #test { background: red; height: 100px; width: 200px; -webkit-filter: blur(0px); filter: blur(0px); transition: box-shadow 0.5s; } #test:hover { box-shadow: 0 0 3px 3px rgba(0, 0, 0, 0.3); }
<div id=test></div>