Joeytje50
Joeytje50

Reputation: 19112

Force-recalculate styles in IE8-

How do I most accurately force the browser to recalculate styles, either on the whole body or on a single element?

I can't simply reload the whole DOM by replacing the innerHTML or something, because that would lose all attached event handlers, so I'd need to use something that would just force the browser to recalculate the styles. This does need to work with IE8.

I have tried searching for anything that would fix this problem, but atleast with the term "recalculating styles" I don't get anywhere, and the only related result I could find for "reloading styles" was "How to refresh the style of a page after css switch". That question doesn't work for me though, since I am not directly changing the class of the element that needs to change styles, but its sibling.

Here is a simplified demo, with just the relevant code:

HTML:

<span id="foo">This gets a class,</span>
<div>...and this should become red,</div>
<button onclick="document.getElementById('foo').className = 'foo';">...if you click here</button>

CSS:

span.foo + div {color:red;}

If you test that demo, atleast in IE8-emulation mode in IE11, you'll see that the style won't update. For me, it only updates after I've selected the node in the DOM viewer in the F12 interface. (PS: IE8-emulation mode is in the bottom tab in IE11's F12 interface).

Upvotes: 1

Views: 1159

Answers (2)

Lucas
Lucas

Reputation: 21

I had a similar issue with IE11 - it was bugging out with weird z-index issues in a particular part of a Vue.js app. Inspecting affected elements or resizing the window suddenly caused it to fix itself up.

I found I could force a recalculate style of the whole body in Javascript by adding and removing a style tag with a universal CSS selector:

var head = document.querySelector("head");
var style = head.appendChild(document.createElement("style"));
var styleSheet = document.styleSheets[document.styleSheets.length - 1];
styleSheet.insertRule("* { }", 0);
head.removeChild(style);

Inspired by this answer to another question.

Upvotes: 2

Fabr&#237;cio Matt&#233;
Fabr&#237;cio Matt&#233;

Reputation: 70149

Toggle a class on an ancestor of the element being targetted by the + selector:

$('body').addClass('ie_force_restyle').removeClass('ie_force_restyle');

This will force IE8- to re-execute selectors matching for all descendants of the given element.

To be a bit more efficient, you could target #foo's parent as well:

$('#foo').parent().addClass('ie_force_restyle').removeClass('ie_force_restyle');

Demo

Tested on Windows 7 x64 - IE8.

Note: I've only tested this for the adjacent sibling selector +, but I'm pretty sure that it should work for ~, :first-child and other selectors which do not react to DOM changes in old IE.

I can't claim originality though, I've found this solution somewhere in the dark corners of the internet while I was working on my :checked pseudo-class polyfill for IE8-.

Upvotes: 1

Related Questions