【轉】觸發瀏覽器回流的屬性方法一覽表
轉載自 奇舞周刊 何文力
@TiffanysBear
下列的所有屬性、方法,在讀取或執行的同時,將會導致瀏覽器同步地計算樣式和布局。這種行為又叫做回流,也是常見的性能瓶頸。
元素類
元素測量
elem.offsetLeft, elem.offsetTop, elem.offsetWidth, elem.offsetHeight, elem.offsetParent
elem.clientLeft, elem.clientTop, elem.clientWidth, elem.clientHeight elem.getClientRects(), elem.getBoundingClientRect()
滾動相關
elem.scrollBy(), elem.scrollTo()
elem.scrollIntoView(), elem.scrollIntoViewIfNeeded()
elem.scrollWidth, elem.scrollHeight
elem.scrollLeft, elem.scrollTop
除了讀取,設置也會觸發
聚焦
elem.focus()
會觸發兩次強制布局
其他
elem.computedRole, elem.computedName
elem.innerText
getComputedStyle
window.getComputedStyle()
調用通常會導致樣式的重新計算,並且,當滿足下列條件時,會觸發強制布局:
元素屬於一顆影子樹中
出現下列任意一個媒體查詢時:
min-width, min-height, max-width, max-height, width, height
aspect-ratio, min-aspect-ratio, max-aspect-ratio
device-pixel-ratio, resolution, orientation , min-device-pixel-ratio, max-device-pixel-ratio
所獲取的屬性是下列之一時:
height, width
top, right, bottom, left
margin [-top, -right, -bottom, -left, 或簡寫形式]
僅在數值是定值時
padding [-top, -right, -bottom, -left, 或簡寫形式]
僅在數值是定值時
transform, transform-origin, perspective-origin
translate, rotate, scale
grid, grid-template, grid-template-columns, grid-template-rows
perspective-origin
window
window.scrollX, window.scrollY
window.innerHeight, window.innerWidth
window.getMatchedCSSRules()
僅會導致樣式重新計算
表單:
inputElem.focus()
inputElem.select(), textareaElem.select()
鼠標事件:
mouseEvt.layerX, mouseEvt.layerY, mouseEvt.offsetX, mouseEvt.offsetY document
doc.scrollingElement
僅會導致樣式重新計算
Range:
range.getClientRects(), range.getBoundingClientRect()
SVG
可以參見 Tony Gentilcore's 2011 Layout Triggering List
contenteditable
很多行為都會觸發,包括復制粘貼圖像進去
附錄
在文檔發生改變或布局、樣式失效時會導致回流的消耗。通常,這是因為DOM發生了改變(類的修改,節點的增加、刪除,甚至是添加一個偽類如 :focus);
如果需要強制布局,樣式首先會被重新計算。所以強制布局會導致這兩種操作的發生。它們所消耗的性能取決於當時的內容或者情況,但通常來說兩者所消耗的性能都是相似的;
一些簡單的解決辦法:
- 避免在 for 循環中強制布局以及更改DOM
- 使用開發工具分析產生影響的代碼
- 批量讀寫DOM(使用FastDOM或者其他的虛擬DOM實現)
上述數據在各個瀏覽器中的表現:
-
上面的數據是通過閱讀 Blink 源碼所得,對於 Chrome, Opera 以及大多數安卓瀏覽器來說是可用的
Tony Gentilcore's Layout Triggering List 的文章針對遇 2011 年的 WebKit 並且與上述數據基本一致 -
現代 WebKit 中出現強制布局的情況是基本上一致的 updateLayoutIgnorePendingStylesheets - GitHub search - WebKit/WebKit
-
Gecko 內核的回流請求通過 FrameNeedsReflow 進行 FrameNeedsReflow - mozilla-central search
-
對於 Edge / IE 沒有很好的數據支持,但是基本上都是應該一致的,因為這些返回值內容都已經由標准所限制。對於最終結果,可能由於優化方法不同而不同。
Chromium 源碼
- 強制布局(以及樣式的重新計算)UpdateStyleAndLayoutIgnorePendingStylesheets - Chromium Code Search
- 強制樣式重新計算UpdateStyleAndLayoutTreeIgnorePendingStylesheets - Chromium Code Search
CSS Triggers
CSS Triggers 提供了一個很好的資源,里面記載了關於設置或者改變一個CSS數值時,瀏覽器內需要做什么操作的信息。
更多關於強制布局的信息
- Avoiding layout thrashing — Web Fundamentals
- Fixing Layout thrashing in the real world | Matt Andrews
- Timeline demo: Diagnosing forced synchronous layouts - Google Chrome
- Preventing 'layout thrashing' | Wilson Page
- wilsonpage/fastdom
- Rendering: repaint, reflow/relayout, restyle / Stoyan
- We spent a week making Trello boards load extremely fast. Here’s how we did it. - Fog Creek Blog
- Minimizing browser reflow | PageSpeed Insights | Google Developers
- Optimizing Web Content in UIWebViews and Websites on iOS
- Accelerated Rendering in Chrome
- web performance for the curious
- Jank Free