You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/concepts/dom.mdx
+17-9Lines changed: 17 additions & 9 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -729,32 +729,36 @@ clone.id = 'new-unique-id'
729
729
When adding many elements, using a **[`DocumentFragment`](https://developer.mozilla.org/en-US/docs/Web/API/DocumentFragment)** is more efficient:
730
730
731
731
```javascript
732
-
// Bad: Multiple reflows
732
+
// Bad: Multiple DOM updates (potentially multiple reflows)
733
733
constul=document.querySelector('ul')
734
734
for (let i =0; i <1000; i++) {
735
735
constli=document.createElement('li')
736
736
li.textContent=`Item ${i}`
737
-
ul.appendChild(li) //Triggers reflow each time!
737
+
ul.appendChild(li) //Modifies live DOM each iteration
738
738
}
739
739
740
-
// Good: Single reflow
740
+
// Good: Single DOM update
741
741
constul=document.querySelector('ul')
742
742
constfragment=document.createDocumentFragment()
743
743
744
744
for (let i =0; i <1000; i++) {
745
745
constli=document.createElement('li')
746
746
li.textContent=`Item ${i}`
747
-
fragment.appendChild(li) // No reflow (fragment is detached)
747
+
fragment.appendChild(li) // No DOM update (fragment is detached)
748
748
}
749
749
750
-
ul.appendChild(fragment) // Single reflow!
750
+
ul.appendChild(fragment) // Single DOM update!
751
751
```
752
752
753
753
A `DocumentFragment` is a lightweight container that:
754
754
- Is not part of the DOM tree
755
755
- Has no parent
756
756
- When appended, only its **children** are inserted (the fragment itself disappears)
757
757
758
+
<Note>
759
+
**Modern browser optimization:** Browsers may batch consecutive DOM modifications and perform a single reflow. However, using DocumentFragment is still the recommended pattern because it's explicit, works consistently across all browsers, and avoids any risk of forced synchronous layouts if you read layout properties between writes.
//Best: Use a CSS class (cleanest and most maintainable)
1232
1236
element.classList.add('my-styles')
1233
1237
1234
1238
// Good: DocumentFragment for multiple elements
@@ -1241,6 +1245,10 @@ items.forEach(item => {
1241
1245
ul.appendChild(fragment) // Single DOM update
1242
1246
```
1243
1247
1248
+
<Tip>
1249
+
**Why batch?** While modern browsers often optimize consecutive style changes into a single reflow, this optimization breaks if you read a layout property (like `offsetWidth`) between writes. Batching explicitly avoids this risk and makes your intent clear.
1250
+
</Tip>
1251
+
1244
1252
### Avoid Layout Thrashing
1245
1253
1246
1254
**Layout thrashing** occurs when you alternate between reading and writing DOM properties:
@@ -2108,7 +2116,7 @@ input.value // "hello"
2108
2116
<Cardtitle="How to traverse the DOM in JavaScript"icon="newspaper"href="https://medium.com/javascript-in-plain-english/how-to-traverse-the-dom-in-javascript-d6555c335b4e">
2109
2117
Covers every traversal method with console output screenshots. Useful reference when you forget which property to use for siblings vs children.
2110
2118
</Card>
2111
-
<Cardtitle="Render Tree Construction"icon="newspaper"href="https://developers.google.com/web/fundamentals/performance/critical-rendering-path/render-tree-construction">
2119
+
<Cardtitle="Render Tree Construction"icon="newspaper"href="https://web.dev/articles/critical-rendering-path/render-tree-construction">
2112
2120
Google's official explanation of the Critical Rendering Path. Essential reading if you want to understand why some DOM operations are slow.
2113
2121
</Card>
2114
2122
<Cardtitle="What, exactly, is the DOM?"icon="newspaper"href="https://bitsofco.de/what-exactly-is-the-dom/">
0 commit comments