Doug
Doug

Reputation: 2312

How to force ie8 to repaint after adding a class to a dom element

In ie8 if elements don't 'repaint' with the associated css when you change the classname, how can you force the browser to refresh and not kill ie8 performance?

This post (How can I force WebKit to redraw/repaint to propagate style changes?) suggested calling offsetHeight which forces a repaint.

This post (http://www.tek-tips.com/viewthread.cfm?qid=1688809) had a comment that suggested adding and removing a class from body element.

Both of these approaches killed ie8 performance and the first had side-effects on my layout.

What's the best approach?

Upvotes: 20

Views: 16248

Answers (6)

Urchin
Urchin

Reputation: 405

I had a lot of difficulty and tried everything to no avail...until I tried this for IE8

function toggleCheck(name) {
  el = document.getElementById(name);
  if( hasClass(el, 'checked') ) {
    el.className = el.className.replace(/checked/,'unchecked');
  } else if( hasClass(el, 'unchecked') ) {
    el.className = el.className.replace(/unchecked/,'checked');
  }
  document.body.className = document.body.className;
}
function hasClass(element, cls) {
  return (' ' + element.className + ' ').indexOf(' ' + cls + ' ') > -1;
}

And now my CSS changes for my checkboxes work beautifully for IE8, Chrome, and Firefox!

Upvotes: 0

user489998
user489998

Reputation: 4521

Ridiculously, this works:

function ie8Repaint(element) {
    element.html(element.html().replace('>', '>'));
}

Nothing actually changes in the DOM so it won't affect any other browsers.

Upvotes: 6

James Lawruk
James Lawruk

Reputation: 31345

This expands on the other answers here. You need to both add a new class (Doug's answer) and ensure the class has a different content value (Adam's answer). Changing the class alone may not be enough. The content change is needed to force IE8 to repaint. Here is a related blog post.

Here is the JQuery to change add the new class:

$(".my-css-class").addClass("my-css-class2");

Here is CSS with the 2nd class having a slightly different content value:

.my-css-class:before {content: "\e014";}
.my-css-class2:before {content: "\e014 ";}

Upvotes: 1

Adam Jenkins
Adam Jenkins

Reputation: 55623

The correct answer to this question is that you need to actually change the content rule.

.black-element:before { content:"Hey!"; color: #000;}
.red-element:before { content:"Hey! "; color: #f00;}

Notice the extra space I added after Hey! on .red-element

Upvotes: 9

webaware
webaware

Reputation: 2841

Fire a move or resize event on it.

var ie8 = whateverYouUseToDetectIE();
var element = document.getElementById("my-element");
element.className += " new-class";
if (ie8) {
    element.fireEvent("resize");
}

Upvotes: 2

Doug
Doug

Reputation: 2312

The solution I came up with for my ie8 issue was to add/remove a class on a near parent of the element i'm changing. Since I'm using modernizer, I check for ie8 and then do this add/remove dance to get the new css to paint.

        $uicontext.addClass('new-ui-look');
        if ($('html').is('.ie8')) {
            // IE8: ui does not repaint when css class changes
            $uicontext.parents('li').addClass('z').removeClass('z');
        }

Upvotes: 24

Related Questions