Empty DIV takes up space after setting innerHTML to blank on IE (aka blank lines after UpdatePanel postback)

Maybe this is common knowledge, but my co-worker and I spent some time chasing this down today, so I figured I'd post it in the hope that it will save other people some time. 

Normally, a empty, unstyled DIV reserves no space in an HTML document. However, it seems that under Internet Explorer (we were testing under IE7), if you set the innerHTML property of such a div to an empty string, suddenly the DIV starts taking up space. In other words, if you have this:

some text
<div id = "theDiv"></div>
some more text

and execute a line of script that does this:

document.getElementById("theDiv").innerHTML = "";

then suddenly a blank line will start appearing in between "some text" and "some more text" - the DIV now occupies space in the flow. This doesn't happen in Firefox, and I believe it's a bug in IE.

We were seeing this using ASP.NET AJAX. We have multiple UpdatePanels on a page, and one of them was rendering empty content. After an async postback, a blank line started appearing where the empty UpdatePanel was. The UpdatePanel script code sets the innerHTML property to the result of the async-postback (blank in this case), and suddenly the UpdatePanel DIV was taking up space where it hadn't before.

The fix in our case was easy - set the RenderMode property of the UpdatePanel to "Inline".

 

28 Comments

  • @Will
    While it's certainly true that innerHTML isn't part of an official standard, it's a de-facto standard that most browsers support, and is used by almost all AJAX toolkits (include ASP.NET AJAX, which we're using). So it's not really practical to avoid.

    XmlHttpRequest isn't part of any standard either, but I won't let that keep me from using it.

  • @kevindente

    All I'm saying is that because its is not a standard, don't be surprised when it behaves differently (much as XmlHttpRequest behaves differently) on different platforms.

    It just so happens that there IS a standard alternative to innerHTML, whose behavior is predictable.

  • @Will,
    While I get what you're saying, it seems pretty obvious to me that the semantics of setting a blank innerHTML and removing all child nodes should be the same. So I don't really see this as a "standard" vs "non-standard" issue - just a bug.



  • FYI: I get your RSS feed in gmail and the link was a bit odd today - I ended up on an weblogs.asp.net login page. Logging in to view a blog kinda defeats the purpose...

  • In your above example, I can't help but think you should have used a span tag instead of a div tag all along and the problem would have never occurred.

    If the result was always going to be blank, what is the point in even having a html tag to write a result to? Why not just forget the whole writing a result?

    Choose the tag best fit for the job, or in this case, why bother with a tag if the result set isn't going to return anything?

  • cpradio,

    The example above is a contrived one to illustrate the issue. Our real scenario was a lot more complicated - the contents of the DIV were conditionally set based on the state of the application.

  • I still stand by my statement to choose the correct tag for the job. As if you wanted it inline to begin with, it should have always been a span tag, not a div.

    However, if you wanted it to be a block content, then dom elements would have been best, ie: using the createTextNode on your div instead of the innerHTML and you wouldn't have had any problems (as stated before).

    When did the developer lose the responsibility for knowing which HTML tag best represents what they are trying to achieve? Some days I feel Visual Studio does nothing but make more of a mess online, much like FrontPage did. If you do not understand the HTML markup first, how can you responsibly build a site using it?

    Just my two cents, we developers need to stop being lazy and get back to the HTML roots we were once required to have. Just because the technology continues to increase and make knowledge of HTML less and less, doesn't give us the right to complain when browser function improperly because we used the wrong tag, or because we didn't understand the DOM specification for what we choose to use.

  • Kevin - do you have a solution that doesn't involve setting the rendermode to inline? We have block content inside the panel and making the panel a span will cause issues with XHTML (unable to put block elements in inline ones).

    Basically what we have is:

    UpdatePanel1 with a div that contains a label and radio list with 2 options

    UpdatePanel2 with a placeholder that contains a div and a dropdownlist

    UpdatePanel2 has UpdateMode set to Conditional and a TriggerElement pointing to the UP1 radio list. The options in the list show/hide the second panel. We're using the Control-Toolkit Animations to fade the div in the second panel in so it's more noticable.

  • Sean,
    Another option is to set the line-height of the div to 0.

  • Jero,
    Did you try the line-height option described in my last comment?

  • Hi kevindente,
    I tried but the line-height set to 0 break the the tableless design I have into the update panel, I use several divs and it seems that solution malform the visual view, anyway I'll try again, thx for response.

  • I'm using UpdatePanels and the comment insertion didn't work for me... I tried putting it in there manually and using javascript but no luck...

    Here's what did work for me - I created a control and derived from UpdatePanel. I overrode RenderChildren and before the call to base.RenderChildren(writer) I put the following code:
    ==========================================

    string isEmpty = "true";
    for (int i=0; i<this.ContentTemplateContainer.Controls.Count; i++)
    {
    if (this.ContentTemplateContainer.Controls[i] != null && !(this.ContentTemplateContainer.Controls[i] is LiteralControl) && this.ContentTemplateContainer.Controls[i].Visible == true)
    {
    isEmpty = "false";
    break;
    }
    }
    ScriptManager.RegisterStartupScript(Page, typeof(Page), this.ClientID + "_display", "$get('" + this.ClientID + "').style.display = " + isEmpty + " ? 'none' : 'block';", true);


    ==========================================

    Now whenever I have an empty UpdatePanel it automatically gets hidden. It's kinda ghetto but I haven't found another way to handle it yet. Thoughts?

    -chad

  • just use style.display = "none"

  • Don Bradken thanks, it worked perfectly :)

  • I found IE still rendered things incorrectly if the UpdatePanel contained elements that rendered but had no visual presence on the page (hidden input controls, empty divs, empty spans, elements with style="display:none", etc.)

    I like Chad's approach of creating our own inherited version of UpdatePanel and overriding RenderChildren.

    In my version, I just ensured that the it generated had style="display:inline", so that it behaved like a but didn't break XHTML validation rules.

    This seems to fix the IE bug in all situations, and I believe it always generates valid XHTML.

    Here's my code, on which I'd appreciate any comments:

    ========================
    public class UpdatePanel : System.Web.UI.UpdatePanel
    {
    protected override void RenderChildren(HtmlTextWriter writer)
    {
    if (!this.Page.IsPostBack && this.RenderMode == UpdatePanelRenderMode.Block)
    {
    StringBuilder sb = new StringBuilder();
    base.RenderChildren(new HtmlTextWriter(new StringWriter(sb)));

    string renderedHtml = sb.ToString();

    if (!renderedHtml.StartsWith("<div "))
    throw new Exception("An UpdatePanel with a RenderMode of Block isn't rendering as a ");

    writer.Write("<div style=\"display:inline\"");
    writer.Write(renderedHtml.Substring(4));
    }
    else
    base.RenderChildren(writer);
    }
    }
    ========================

    I don't believe that Exception would ever get thrown, but I'd rather be safe than sorry.

    I suppose you could argue that if the RenderMode is Block we should leave it alone, but if RenderMode is Inline we should replace the with a ...

  • I lost all my hair working on the same problem!
    thanks Don, style.display = "none"
    worked like a champ!!!


  • The "line-height: 0;" method did the trick for my application. Thanks, Kevin

  • Thanks for the "render: inline" tip. That fixed it for me.

  • I found your solution after I typed "html div leave one blank line" in google. Thanks.

  • Thanks very much,

    I've spent a good while trying to solve the issue till I saw ur blog!!



  • Thanks, though this makes perfect sense to me even without an explanation. If you want to hide a div, use div.(object element).display = 'none';

  • This can also occur when you have multiple spans set with style display: block that will have visible=false in them (so that they won't take up space when the contents aren't shown) - e.g. in my Modal Popup:-




















    <asp:ListItem Text="Less Than" Value="
    " />
    <asp:ListItem Text="Less Then Or Equal To" Value="
    " />

    <asp:ListItem Text="Not Equal To" Value="" />

























  • Just another strange addendum to my last bit of code - if you remove the RenderMode="Inline" and put a final span before the /ContentTemplate like this

    Some Text

    it "fixes" the problem. However, if you remove the space at the end of the span text, like this

    Some Text

    the blank line reappears.

  • "That happens because you're altering the DOM in a non-standard (albeit cross-browser) way."
    - False. I encountered the same issue when simply declaring a div in HTML, with no contents before . This is simply a bug in IE. The workaround I came up with was to insert inside the div.

  • On second thought it might not be a bug. As I understand it... a div is a block item, therefore it automatically adds a
    before and after the enclosed content. These breaks would take up space even without content inside the div.

  • Cool... style.display=none/inline/block works.. Thanks Don Bradken

  • hola
    i'm so thrilled that i found this website. that posting was so cool. thanks again i added the rss on this site.
    are you planning to post similar articles?

  • I used display=table property and it works.
    thanks.

Comments have been disabled for this content.