Each time an element of the DOM changes, the browser will have to recalculate elements and styles and also it might have to re-flow the page. The following is the typical workflow:
Recalculate Style → Layout → Paint
The Chrome Rendering Tab can be used to debug rendering issues such as scrolling performance issues, painting issues due to dynamic content and much more. This tab is usually not available by default, but it can be activated by selecting ‘Developer tools’ > ‘More tools’ > ‘Rendering’.
The first JavaScript example shows how Chrome can highlight areas of the screen that need to be repainted when the DOM changes. For this example to work, the ‘Paint flashing’ checkbox in the ‘Rendering’ tab has to be activated. The reader will need to create a simple HTML file with two DIV sections with the correct IDs:
function getTheTime() {
setInterval(() => {
document.getElementById('clock').innerHTML = (new Date).getHours() + ":" + (new Date).getMinutes() + ":" + (new Date).getSeconds();
}, 1000);
}
const textAppend = document.getElementById('textToAppend');
for(let i = 0; i < 1000; i++) {
const t = document.createElement('P');
t.textContent = `Index is ${i}`;
textAppend.appendChild(t);
}
The second JavaScript example shows how the browser scrollbar is also part of the rendering surface and might need to be repainted too. For this example to work, the ‘Paint flashing’ checkbox in the ‘Rendering’ tab has to be activated. The reader will need to create a simple HTML file with two DIV sections with the correct IDs:
function getTheTime() {
setInterval(() => {
document.getElementById('clock').innerHTML = (new Date).getHours() + ":" + (new Date).getMinutes() + ":" + (new Date).getSeconds();
}, 1000);
}
const flashScroll = document.getElementById('flashScroll');
let c = 0;
const append = function() {
if(c >= 1000) {
return clearInterval(append);
}
const mytext = document.createElement('P');
mytext.textContent = new Date().getDate() + '/' + new Date().getMonth() + '/' + new Date().getFullYear();
flashScroll.appendChild(mytext);
c++;
};
setInterval(append, 1000);
The third JavaScript example shows how adding one element to the DOM might cause all elements to be repainted, should their positions or properties be modified. For this example to work, the ‘Paint flashing’ checkbox in the ‘Rendering’ tab has to be activated. The reader will need to create a simple HTML file with two DIV sections with the correct IDs:
const flashScroll = document.getElementById('flashScroll');
let c = 0;
const append = function() {
if(c >= 1000) {
return clearInterval(append);
}
const mytext = document.createElement('P');
mytext.textContent = new Date().getDate() + '/' + new Date().getMonth() + '/' + new Date().getFullYear();
flashScroll.appendChild(mytext);
c++;
}
setInterval(append, 1000);
setTimeout(() => {
const prependContent = document.createElement('P');
prependContent.textContent = '###BEGINNING OF THE PAGE###';
document.body.prepend(prependContent);
}, 3000);
The fourth JavaScript example shows the difference between DOM and canvas. Canvas can repaint just those areas of the screen that change, without affecting the whole page, which might result in better performances. For this example to work, the ‘Paint flashing’ checkbox in the ‘Rendering’ tab has to be activated. Also, in the HTML page, the tag CANVAS is to be used instead of the usual DIV:
function startTime() {
setInterval(() => {
document.getElementById('clock').innerHTML = (new Date).getHours() + ":" + (new Date).getMinutes() + ":" + (new Date).getSeconds();
}, 1000);
}
const myCanvas = document.getElementById('geometry');
const context = myCanvas.getContext('2d');
context.beginPath();
context.arc(100, 75, 50, 0, 2 * Math.PI);
context.fillStyle = 'green';
context.fill();
context.beginPath();
context.arc(150, 75, 50, 0, 2 * Math.PI);
context.fillStyle = 'red';
context.fill();
context.beginPath();
context.arc(200, 75, 50, 0, 2 * Math.PI);
context.fillStyle = 'blue';
context.fill();
setTimeout(() => {
context.beginPath();
context.arc(200, 75, 50, 0, 2 * Math.PI);
context.fillStyle = 'grey';
context.fill();
}, 3000);
setTimeout(() => {
context.beginPath();
context.arc(150, 75, 25, 0, 2 * Math.PI);
context.fillStyle = 'blue';
context.fill();
}, 5000);
Although usually canvas performances are great, they might not be the perfect solution for all websites as canvas might require large amount of code to work. Also, canvas might not perform very well when managing large objects. On the other hand, DOM is easily manageable via CSS, redrawing DOM frames is automatically done by the browser. DOM is not designed for complex graphics and animations!