I'm Dudley Storey, the author of Pro CSS3 Animation. This is my blog, where I talk about web design and development with HTML, CSS and SVG. To receive more information, including news, updates, and tips, you should follow me on Twitter or add me on Google+.

my books

Pro CSS3 Animation book coverPro CSS3 Animation, Apress, 2013

my other blogs

Massive Head CanonMassive Head Canon: Intelligent discussion of movies, books, games, and technology.

my projects

The New DefaultsThe New Defaults — A Sass color keyword system for designers.

CSSslidyCSSslidy — an auto-generated #RWD image slider. 3.8K of JS, no JQuery.

Forcing a Webkit Repaint

Some coding techniques for when you absolutely, positively need Chrome, Safari and Opera to repaint

Under certain conditions, Webkit will not repaint the browser window to reflect DOM additions or changes. This is a known bug: in the case of Wednesday’s article on making an automatic image checkerboard with SVG and JavaScript, switching from rectangular to circular clipping areas in Chrome will produce an effect that looks like Figure 1:

Figure 1: The effect of switching from rectangular to circular clipping paths in the auto image checkerboard in Chrome, without a repaint.

To address this in the CodePen version, I’ve added four lines to the end of the script:

var bridge = document.querySelector("#clipit img");
bridge.style.display="none";
bridge.offsetHeight;
bridge.style.display="block";

This finds the image, quickly hides it, calculates its current height, and then sets it back to display: block. For all purposes this happens instantaneously, so there is no visual “flicker” in the browser. There are just two things to note:

  1. We don’t have to store offsetHeight; referencing it is enough to give Webkit a reminder that the element should be redrawn.
  2. We redraw the image to which the SVG is applied, not the SVG itself.

Other Solutions

This is not an absolute suggestion, just the best one I’ve found. However, it may force both a reflow and repaint, making Webkit work overtime. There are some other solutions that may be more effective in certain cases:

  1. Adding an empty <style></style> tag after the script; either dynamically with JavaScript or writing it directly into the code of the page.
  2. Adding a transform or something else that will not otherwise alter the appearance of the element:

    element.style.webkitTransform = "scale(1)";

    Or in CSS:

    .quickfix { 
       transform: translateZ(0); 
    }

    Similar techniques involve adding and removing an invisible outline:

    .quickfix { 
       outline: 0px;
    }
  3. If the element is absolutely positioned: adding a z-index value to the element can force a repaint:

    element.style.zIndex = "2";

This fix is not needed in every case, and I hope it will be unnecessary in the future, but right now when you need it, you really need it.

This site helps millions of visitors while remaining ad-free. For less than the price of a cup of coffee, you can help pay for bandwidth and server costs while encouraging further articles.