Question: Does touching the DOM trigger a reflow and repaint even if nothing changes?


Does touching the DOM trigger a reflow and repaint even if nothing changes?

Answers 1
Added at 2017-01-03 23:01

I am working on a small JavaScript template engine, and I have two possible approaches for dealing with updates to the DOM when the model changes:

  1. Check if the DOM update is really needed before doing it. This has the benefit of not risking unnecessary updates, but I am wasting space on keeping track of old values.

    if (oldValue !== newValue) {
        element.textContent = newValue;
  2. Just do it. This is obviously simpler, but I am afraid that I will be triggering repaints and reflows for no reason.

    element.textContent = newValue;

Note that I am also manipulating the DOM by calling setAttribute, addClass and removeClass, plus setting style[prop] = value.

So, my question is: Are modern browsers smart enough to notice that nothing actually changed, and therefore not run reflow or repaint, if you touch the DOM without actually changing anything?

nr: #1 dodano: 2017-01-03 23:01

Using the MutationObserver api you can detect DOM changes.

Here is an example you can use to see if a browser triggers the Dom Changed event, based on what you want.

You have here both a text('...') by jquery and an el.textContent (that doesn't use jquery).

$(document).ready(function() {
  $('#btn1').click(function() {
    console.log('text changed - jquery');
    $('#a1').text('text 1');
  $('#btn2').click(function() {
    console.log('text changed - textContent');
    $('#a1')[0].textContent  = $('#a1')[0].textContent 
  $('#btn3').click(function() {
    console.log('class changed');
    $('#a1').attr('class', 'cls' + Math.floor(Math.random() * 10));

var target = $('#a1')[0];

// create an observer instance
var observer = new MutationObserver(function(mutations) {
  var changed = false;
  mutations.forEach(function(mutation) {
    // You can check the actual changes here
  console.log('Dom Changed');

// configuration of the observer:
var config = { attributes: true, childList: true, characterData: true };

// pass in the target node, as well as the observer options
observer.observe(target, config);
.cls1 {
  border: 1px solid red;
.cls2 {
  border: 1px solid pink;
.cls3 {
  border: 1px solid cyan;
.cls4 {
  border: 1px solid darkgreen;
.cls5 {
  border: 1px solid orange;
.cls6 {
  border: 1px solid darkred;
.cls7 {
  border: 1px solid black;
.cls8 {
  border: 1px solid yellow;
.cls9 {
  border: 1px solid blue;
.cls10 {
  border: 1px solid green;
<script src=""></script>
<div id="a1" class="cls1">text 1</div>
<button id="btn1">Change text - jquery (keep original)</button><br />
<button id="btn2">Change text - textContent (keep original)</button><br />
<button id="btn3">Change class (real change)</button>

  • In Chrome 55, only setAttribute() and jQuery text() triggered the Dom Change event.
  • In Firefox 50, everything triggered the Dom Change event.
  • In Edge 38, everything triggered the Dom Change event.
Source Show
◀ Wstecz