Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Force rendering a DOM element when Webkit is acting up
forceRerenderOnWebkit: ->
@el.parentNode.style.cssText += ';-webkit-transform:rotateZ(0deg)'
@el.parentNode.offsetHeight
@el.parentNode.style.cssText += ';-webkit-transform:none'
@madrobby

This comment has been minimized.

Copy link
Owner Author

commented Nov 13, 2011

Anyone know of a better way?

@xavierm02

This comment has been minimized.

Copy link

commented Nov 13, 2011

Why do you concat to cssText?
Using style.WebkitTransform = 'rotateZ(0deg)'; would probably do the same while being a bit faster.
And btw, why do you want to force repaint?

@madrobby

This comment has been minimized.

Copy link
Owner Author

commented Nov 13, 2011

The concat works on any browser, not just Webkit, it just silently fails. I need to repaint because I've stumbled upon some rendering glitches with Webkit (the repaint forces the element to be correctly rendered).

@helgri

This comment has been minimized.

Copy link

commented Nov 13, 2011

isn't any 3d transform forcing a re-rendering 'cause the element is transmitted to the gpu?

@madrobby

This comment has been minimized.

Copy link
Owner Author

commented Nov 13, 2011

@helgri yeah, but it need to be flipped on, rendered once (the offsetHeight forces a recalculation/repaint) and then switched off again so you can use it more than once on a given element. you can even use "normal" CSS properties, like "height" for example, or you could toggle "display". I choose this because I know that I won't use it for this particular element, and so I don't need to store the old value, etc.

I was wondering more if there's an approach where I don't need to mess with CSS at all.

@WebReflection

This comment has been minimized.

Copy link

commented Nov 13, 2011

Node.prototype.repaint = function () {
    var
        offsetHeight = "offsetHeight",
        parentNode = this.parentNode
    ;
    return parentNode && (offsetHeight in parentNode) ?
        parentNode[offsetHeight] :
        this[offsetHeight]
    ;
};
@helgri

This comment has been minimized.

Copy link

commented Nov 13, 2011

I see... and the rotation value works for you, because you know, that you don't use it. in other sites this may break...

you could also add/remove a .repaint class (with your rule), than it's also not necessary to store old values.

so best solution would be to avoid dom operations at all... what about adding/removing a css rule for the element to the stylesheet doc via javascript? won't touch the dom.

@KrofDrakula

This comment has been minimized.

Copy link

commented Nov 13, 2011

Have you tried modifying the class name and/or id? It worked for me on several occasions, eg. forcing iOS 5 to render position:fixed iframes whine scrolling. Any change triggered a rerender, so appending a bogus class or assigning to the id worked.

@bundyo

This comment has been minimized.

Copy link

commented Nov 14, 2011

Should be enough to get the computed style of the element to force a repaint.

@gr2m

This comment has been minimized.

Copy link

commented Nov 15, 2011

I don't have a better solution, but your suggestion just fixed a bug I had in Opera. Thanks :-)

@gr2m

This comment has been minimized.

Copy link

commented Nov 15, 2011

I also found this plugin:
http://plugins.jquery.com/files/jquery.forceredraw-1.0.3.js_.txt

It confirms @KrofDrakula's suggestion for most cases but also has a "brutal" fallback where it changes CSS as you do in your suggestion, just using a 1ms timeout before it changes it back

@KrofDrakula

This comment has been minimized.

Copy link

commented Nov 15, 2011

@gr2m: It would seem the "brutal" version here changing the padding seems a bit overkill; I use the following code for a rock solid repaint:

function forceRedraw(el) {
  var t = el.ownerDocument.createTextNode(' ');
  el.appendChild(t);
  setTimeout(function() { el.removeChild(t); }, 0);
}
@helgri

This comment has been minimized.

Copy link

commented Nov 15, 2011

@gr2m damn, i just suggested a class named "repaint", not "redraw" ;)

but i still favor a solution which doesn't need to touch the dom at all

@catx23

This comment has been minimized.

Copy link

commented Jun 3, 2013

on mobile webkit browsers, the "add/remove" class works best with "display:none" and a minimum delay of 1000ms. brutal but works at least.

@nuragic

This comment has been minimized.

Copy link

commented Jun 10, 2014

Hi guys! Thanks to all for the suggestions... So, anyone know what is the most optimal way to force a reflow? Any jsPerf there? :)

@digitalicarus

This comment has been minimized.

Copy link

commented Oct 8, 2015

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.