Reputation: 1163
I am trying to add hundreds of little "squares"/shapes on a page using JS. However, whether using SVG or divs, the page load is very slow. Is there a more efficient way to create multiple shapes on a page without slowing down the page load?
Here is an example in JSFiddle, which has both svg and div examples
Here is the JS:
var num = 700
for (i=0; i < num; i++){
let el = '<div class="els"></div>';
let elSVG = '<svg class="els"></svg>';
let container = document.getElementById("test");
container.innerHTML = container.innerHTML + elSVG
}
Upvotes: 2
Views: 196
Reputation: 48610
Instead of concatenating HTML text to the innerHTML
each time, append
an <svg>
element. Also, you should only query for #test
(aka container
) once; outside of your loop.
const
container = document.getElementById('test'),
num = 700;
const createSvg = () => {
const svg = document.createElement('SVG');
svg.classList.add('els');
return svg;
};
for (let i = 0; i < num; i++) {
container.append(createSvg());
}
body {
background-color: #111
}
.els {
display: inline-block;
width: 10px;
height: 10px;
margin-right: 16px;
background-color: #EEE;
}
<div id="test"></div>
Update: As Danny mentioned, you could append all the SVG elements to a DocumentFragment
and then append said fragment to the container afterwards.
const fragment = new DocumentFragment();
for (let i = 0; i < num; i++) {
fragment.append(createSvg());
}
container.append(fragment);
Upvotes: 4
Reputation: 21173
You will always slow page load, it can not be done without slowing down.
But you can be smart in creating content.
innerHTML and append will trigger Browser reflow/repaint for every insertion
Use a DocumentFragment to built all HTML in memory, then inject the DocumentFragment once.
https://developer.mozilla.org/en-US/docs/Web/API/DocumentFragment
You might also want to look into <template>
,
a cloned template parses the HTML only once
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/template
<style>
body {
background-color: black
}
.els {
height: 2px;
width: 1px;
background-color: white;
margin-right: 1px;
display: inline-block;
}
</style>
<div id="$Container">
</div>
<script>
console.time();
let fragment = new DocumentFragment();
let num = 4 * 700;
for (i = 0; i < num; i++) {
let el = document.createElement("div");
el.classList.add("els");
el.appendChild(document.createElement("svg"))
.classList.add("els");
fragment.append(el);
}
$Container.append(fragment);
console.timeEnd();
</script>
Upvotes: 1