Feb 24, 2008

Internet Explorer rendering problems or how to repaint Web-page

A short prelude.

I'm developing a small checklist application, to study ruby/rails and to play with various Web 2.0 UI patterns. And to get a tool which will help me to organize all my todos.

On the checklist screen I have, guess what - list of tasks, the checklist is comprised of. On some actions (like completing a task) the tasks are updated incrementally (with plain Javascript), on some actions (like undo) the list is reloaded as a whole.

Now the story.

To avoid task rendering in two places (on the server-side, when tasks are loaded from the server and on the client-side when they are updated in-place) I've used an approach when all rendering is performed by Javascript, even on the full page reload. This implies generation of the HTML on the browser-side and inserting the resulting HTML into the page in window.onload hook.

The problem was that in IE the inserted HTML was rendered like a total mess. Elements were painted one upon another, lost their position, styles.

As I found out later, the page resize fixes the rendering.

So I had to force a repaint of the inserted elements to fix the rendering.

The solution was simple. All I had to do was to add a fake CSS class to the inserted element and remove it afterwards (in fact, there is no strict need to remove the class). This operation forces an element restyling in IE and fixes its rendering. Looks like a hack, and it is.

By the way, moving task list rendering from the server side to browser gave me performance gain of 200% on the server.

11 comments:

Anonymous said...

谢谢你,这招很有用!

parag said...

You can try using Other Alternate Browsers, if problem is really with your Internet Browser or the system.

Brett said...

AHA! BINGO! Just what I needed, and it works! Thankyou, Kir!

I was actually resizing my window in script to work around this issue. I was doing window.resizeBy(0,1), which also "worked", but (a) it's visible to the user, and (b) it had the unfortunate side-effect of partially disconnecting the sizing of one frame from the window.

Your method has neither of these side effects. True, it's a hack, but compared to mine, it's a thing of beauty.

*KISS* *KISS* *KISS*

Anonymous said...

Thank you very very much!! You saved my day!

Anonymous said...

After 30 mins ... Thanks ^^

Anonymous said...

by fake css, do you mean an empty one or a duplicate?

Anonymous said...

please give us a simple example. thanks.

Kir Maximov said...

By fake css, I meant expression like
parentElement.addClassName("foo")
(if use prototype library), where foo css class doesn't exist in my code.

Anonymous said...

tnx for the reply Kir.

i'm not using another js library right now so i tried using DOM only and set the className of the parent element. it doesn't seem to work.

var origClassName = document.getElementById('scrollableGrid').className;

document.getElementById('scrollableGrid').className = origClassName + " foo";

is it supposed to work? if yes, did i do it correctly?

Kir Maximov said...

Yes, your variant should work. If not, you probably have some other problem :(

Anonymous said...

it's weird but i finally got it to work:

setTimeout("document.getElementById('scrollableGrid').className = document.getElementById('scrollableGrid').className + ' foo'", 100);

tnx a lot!