In the current trend, the website động
is the preferred lot. That is, the user can manipulate on it instead of just receiving information as plain text
lines as before.
Programmers also try hard to create eye-catching, easy-to-use interfaces for user actions. For example, a few pages instead of listing out the headlines in dry text
, they create drag and drop interfaces for users. Just like they use real-world tools – Trello is a prime example.
However, to make those changes, programmers often manipulate the DOM
a lot, the browser must constantly reflow to recalculate the size and relocate the position . Understanding the reflow will help optimize the process of rendering a website to users so it is smoother.
1. Reflow
To find out what reflow
is, let’s take a look at the following example: What happens when you try to change the height of an element tag.
Changing the height of the element
does not affect the structure of the DOM
tree. However, its size needs to be recalculated.
After the process of recalculating the height. Subsequent processes such as a new repaint
are performed before displaying the browser.
So what is reflow?
Reflow is a collection of processes that the browser recalculates and relocates elements on the web page.
2. Why limit reflow?
However, because the reflow process takes place synchronously, that is, when the reflow is not finished. Then other processes just wait there. Therefore, we need to minimize reflow so that the process of displaying on webpage will be faster.
In fact, there are many cases of reflow that take too long to lead to a tab crash .
Here are some limitations that reflow brings:
- CPU consumption
- It takes more time to process meaningful paint
- It takes more time to process contentful paint
The following are the events leading to the activation of the reflow process.
Getting box metrics
elem.offsetLeft
,elem.offsetTop
,elem.offsetWidth
, elem.offsetHeight,elem.offsetParent
elem.clientLeft
,elem.clientTop
,elem.clientWidth
,elem.clientHeight
*elem.getClientRects()
,elem.getBoundingClientRect()
Scroll stuff
elem.scrollBy()
,elem.scrollTo()
elem.scrollIntoView()
,elem.scrollIntoViewIfNeeded()
elem.scrollWidth
,elem.scrollHeight
elem.scrollLeft
,elem.scrollTop also
Setting focus
elem.focus()
Getting window dimensions
window.scrollX
,window.scrollY
window.innerHeight
,window.innerWidth
window.visualViewport.height
/width
/offsetTop
/offsetLeft
document
document.scrollingElement
document.elementFromPoint
Mouse events: Reading offset data
mouseEvt.layerX
,mouseEvt.layerY
,mouseEvt.offsetX
,mouseEvt.offsetY
Forms: Setting selection + focus
inputElem.focus()
inputElem.select()
,textareaElem.select()
….
Find out more at: What forces layout / reflow
3. Limited in any way
As we said earlier, it is important to change the elements to create a vibrant website .
Therefore, in the process of changing the interface or interfering with the properties of the elements, the reflow
is limited as possible.
Minimize triggers reflow when interfering with the properties of elements
3.1 Batch change
The first technique is that when changing a series of elements, delete them from the DOM
, then proceed to change the properties and then add them back to the DOM
.
For example as follows
1 2 3 4 5 6 7 8 | <span class="token keyword">var</span> element <span class="token operator">=</span> document <span class="token punctuation">.</span> <span class="token function">getElementById</span> <span class="token punctuation">(</span> <span class="token string">'example-element'</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">var</span> parentElement <span class="token operator">=</span> element <span class="token punctuation">.</span> parentElement <span class="token punctuation">;</span> <span class="token keyword">var</span> removedElement <span class="token operator">=</span> parentElement <span class="token punctuation">.</span> <span class="token function">removeChild</span> <span class="token punctuation">(</span> element <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">// triggers reflow</span> removedElement <span class="token punctuation">.</span> style <span class="token punctuation">.</span> opacity <span class="token operator">=</span> <span class="token string">'0.5'</span> <span class="token punctuation">;</span> removedElement <span class="token punctuation">.</span> style <span class="token punctuation">.</span> padding <span class="token operator">=</span> <span class="token string">'20px 10px'</span> <span class="token punctuation">;</span> removedElement <span class="token punctuation">.</span> style <span class="token punctuation">.</span> width <span class="token operator">=</span> <span class="token string">'200px'</span> <span class="token punctuation">;</span> parentElement <span class="token punctuation">.</span> <span class="token function">appendChild</span> <span class="token punctuation">(</span> removedElement <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">// triggers reflow</span> |
Here, if we didn’t remove the parentElement
element, we would take 3 more reflows for the style to change opacity
, padding
, width
.
But because we deleted them later to proceed to the style
, we saved the reflow
process.
Note that this method actually has to activate the reflow twice, so depending on the complexity of the processing process, you should choose, if you only need to change one padding attribute (i.e. (trigger trigger reflow) then there is no reason to remove the element and then add again
In addition, you should group the sentences to read and write the DOM together . Avoid reading sporadic records .
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <span class="token comment">// Tối ưu</span> <span class="token keyword">var</span> w <span class="token operator">=</span> element <span class="token punctuation">.</span> clientWidth <span class="token operator">+</span> <span class="token number">50</span> <span class="token punctuation">;</span> <span class="token keyword">var</span> w2 <span class="token operator">=</span> element <span class="token punctuation">.</span> clientWidth <span class="token operator">+</span> <span class="token number">100</span> <span class="token punctuation">;</span> element <span class="token punctuation">.</span> style <span class="token punctuation">.</span> width <span class="token operator">=</span> w <span class="token operator">+</span> <span class="token string">'px'</span> <span class="token punctuation">;</span> element <span class="token punctuation">.</span> style <span class="token punctuation">.</span> width <span class="token operator">=</span> w2 <span class="token operator">+</span> <span class="token string">'px'</span> <span class="token punctuation">;</span> <span class="token comment">// Chưa tối ưu</span> <span class="token keyword">var</span> w <span class="token operator">=</span> element <span class="token punctuation">.</span> clientWidth <span class="token operator">+</span> <span class="token number">50</span> <span class="token punctuation">;</span> element <span class="token punctuation">.</span> style <span class="token punctuation">.</span> width <span class="token operator">=</span> w <span class="token operator">+</span> <span class="token string">'px'</span> <span class="token punctuation">;</span> <span class="token keyword">var</span> w2 <span class="token operator">=</span> element <span class="token punctuation">.</span> clientWidth <span class="token operator">+</span> <span class="token number">50</span> <span class="token punctuation">;</span> element <span class="token punctuation">.</span> style <span class="token punctuation">.</span> width <span class="token operator">=</span> w2 <span class="token operator">+</span> <span class="token string">'px'</span> <span class="token punctuation">;</span> |
3.2 Avoid reflow in the loop
Check loops in your code to make sure that trigger reflows like element.offsetWidth
leave the loop by using them as a variable.
Not optimal
1 2 3 4 5 6 7 8 | <span class="token keyword">var</span> list <span class="token operator">=</span> document <span class="token punctuation">.</span> <span class="token function">getElementById</span> <span class="token punctuation">(</span> <span class="token string">'list'</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">var</span> listItems <span class="token operator">=</span> Array <span class="token punctuation">.</span> <span class="token keyword">from</span> <span class="token punctuation">(</span> list <span class="token punctuation">.</span> children <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">for</span> <span class="token punctuation">(</span> <span class="token keyword">var</span> i <span class="token operator">=</span> <span class="token number">0</span> <span class="token punctuation">;</span> i <span class="token operator"><</span> listItems <span class="token punctuation">.</span> length <span class="token punctuation">;</span> i <span class="token operator">++</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">var</span> listParentHeight <span class="token operator">=</span> list <span class="token punctuation">.</span> parentElement <span class="token punctuation">.</span> offsetHeight <span class="token punctuation">;</span> <span class="token comment">// Lặp lại reflow</span> listItems <span class="token punctuation">[</span> i <span class="token punctuation">]</span> <span class="token punctuation">.</span> style <span class="token punctuation">.</span> marginTop <span class="token operator">=</span> Math <span class="token punctuation">.</span> <span class="token function">floor</span> <span class="token punctuation">(</span> listParentHeight <span class="token operator">/</span> listItems <span class="token punctuation">.</span> length <span class="token operator">-</span> <span class="token number">10</span> <span class="token punctuation">)</span> <span class="token operator">+</span> <span class="token string">'px'</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> |
Optimal
1 2 3 4 5 6 7 | <span class="token keyword">var</span> list <span class="token operator">=</span> document <span class="token punctuation">.</span> <span class="token function">getElementById</span> <span class="token punctuation">(</span> <span class="token string">'list'</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">var</span> listItems <span class="token operator">=</span> Array <span class="token punctuation">.</span> <span class="token keyword">from</span> <span class="token punctuation">(</span> list <span class="token punctuation">.</span> children <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">var</span> listParentHeight <span class="token operator">=</span> list <span class="token punctuation">.</span> parentElement <span class="token punctuation">.</span> offsetHeight <span class="token punctuation">;</span> <span class="token comment">// Đặt ngoài vòng lặp </span> <span class="token keyword">for</span> <span class="token punctuation">(</span> <span class="token keyword">var</span> i <span class="token operator">=</span> <span class="token number">0</span> <span class="token punctuation">;</span> i <span class="token operator"><</span> listItems <span class="token punctuation">.</span> length <span class="token punctuation">;</span> i <span class="token operator">++</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> listItems <span class="token punctuation">[</span> i <span class="token punctuation">]</span> <span class="token punctuation">.</span> style <span class="token punctuation">.</span> marginTop <span class="token operator">=</span> Math <span class="token punctuation">.</span> <span class="token function">floor</span> <span class="token punctuation">(</span> listParentHeight <span class="token operator">/</span> listItems <span class="token punctuation">.</span> length <span class="token operator">-</span> <span class="token number">10</span> <span class="token punctuation">)</span> <span class="token operator">+</span> <span class="token string">'px'</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> |
3.3 Use visibility instead of display
In some cases where elements need to be hidden / visible , the visibility: hidden
and visibility: visible
attributes should be used instead of display: none
and display: block
.
When using visibility: hidden
to hide, the element
still takes up space in the structure of the DOM
tree. That is, changing the element size will not take place like using the display
property.
So in those cases, you don’t have to remove the element from the DOM
. Use visibility: hidden
to avoid trigger reflow
3.4 Use cssText to style
In some cases, the style
of the elements must be changed. Try to implement them in a single visit. cssText can help you with this. Create a change of multiple attributes in a triggers reflow
.
Not optimal
1 2 3 | element <span class="token punctuation">.</span> style <span class="token punctuation">.</span> left <span class="token operator">=</span> left <span class="token punctuation">;</span> <span class="token comment">// triggers reflow</span> element <span class="token punctuation">.</span> style <span class="token punctuation">.</span> top <span class="token operator">=</span> top <span class="token punctuation">;</span> <span class="token comment">// triggers reflow</span> |
Optimal
1 2 | element <span class="token punctuation">.</span> style <span class="token punctuation">.</span> cssText <span class="token operator">+=</span> <span class="token string">"left: "</span> <span class="token operator">+</span> left <span class="token operator">+</span> <span class="token string">"px; top: "</span> <span class="token operator">+</span> top <span class="token operator">+</span> <span class="token string">"px;"</span> <span class="token punctuation">;</span> <span class="token comment">// triggers reflow once</span> |
4. Summary
Above I have introduced some methods to limit triggers reflow
and still achieve the purpose of changing the interface . There are also some other methods like
- Minimize
CSS
rules, remove them when not needed. - Reducing the depth of the
DOM
tree, Avoiding the changes of thenode cha
entails a series of changes of thenode con
. - Use flex box
- Use
textContent
instead ofinnerText
.
Refer:
- Optimize browser rendering: Flow
- How does browser work step by step in 2019 – optimization in the interaction stage (part 5)
- Minimizing browser reflow
- Web Performance: Minimizing DOM Reflow / Layout Shift
Thank you for watching the article, if you find it useful, don’t forget to upvote yourself. See you in the next posts.