What causes a reflow, and why is it expensive?
A reflow is the browser recalculating the position and size of every element on the page. It is expensive because the layout of the page is interdependent: change the width of one element and the browser may have to work out new positions for its siblings, its children and everything that follows it in the flow.
The main triggers are changes that affect geometry. Setting a width, a height, a margin, a padding, a border or a font size on an element can all force a reflow. Changing the display property between block and flex, adding or removing an element from the flow, and scrolling can do it as well. The browser also reflows when the content changes in a way that alters the size, such as when a web font finishes loading and replaces a fallback font with different metrics.
The part that surprises people is that a reflow can be triggered by reading, not just by writing. Asking for a layout property such as offsetHeight, offsetWidth, scrollTop or the result of getBoundingClientRect forces the browser to flush any pending style and layout work and compute the answer right now, synchronously. If that read happens in the middle of a batch of writes, the browser has to do the work twice, once for the writes and again for the read.
That repeated flush is called layout thrashing, and it is the single most common cause of a slow page in hand-written interface code.