Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

IE conditional comments around html tag adds Compat View icon to address bar #378

Closed
DingoEatingFuzz opened this Issue · 67 comments
@DingoEatingFuzz

Even though the doctype is HTML5 recommended and the X-UA-Compatible meta tag is present, by putting the HTML tag in a series of IE conditional comments, IE refuses to believe that the website is indeed "modern" and puts the dreaded "Compatibility View" button in the address bar.

The way I get around this is by using JavaScript to add the ie6/7/whatever classes.

Example:

<html class="no-js" lang="en">
...
<!--[if lt IE 7 ]>
    <script src="js/libs/dd_belatedpng.js"></script>
    <script> DD_belatedPNG.fix('img, .png_bg'); var ie = "ie6"; </script>
<![endif]-->        
<!--[if IE 7 ]> <script> var ie = "ie7"; </script> <![endif]-->
<!--[if IE 8 ]> <script> var ie = "ie8"; </script> <![endif]-->
...
if(typeof ie !== 'undefined') $('html').addClass(ie); // in js/script.js

I'm sure there are better ways to handle this, but this works as expected.

@shichuan

hmmm, i can't replicate the issue, would you mind provide a test case?

@DingoEatingFuzz

Thanks for the quick update.

Here are a couple pages that isolate the problem:

Using comments (has compatibility view button)

Not using comments (no compatibility view button)

Themble is an example of a complete site with the problem:

Themble

I noticed that the html5-boilerplate site doesn't have the problem. It could also be htaccess related.

@shichuan

yea, it happens without htaccess, there is the following in the htaccess that fixes this

BrowserMatch MSIE ie
Header set X-UA-Compatible "IE=Edge,chrome=1" env=ie
@DingoEatingFuzz

It might be a good idea to note that on the site or in the documentation for the folks who aren't using Apache :)

@gabor

hmm, maybe i'm misunderstanding something, but doesn't this mean that the
http-equiv=x-ua-compatible
solution in the html is useless?

if you have to put in the http header, then you do not need the html-tag...

@MartinMa

I think so too. The X-UA-Compatible meta tag is in fact useless here and could as well be removed from index.html of the boilerplate. Why was this issue closed again?

@DingoEatingFuzz

Not gonna lie: I accidentally closed it by clicking the "comment and close" button rather than the "comment" button. And now I don't know how to reopen it. Kind of a github noob.

From what I have noticed, the X-UA-Compatible meta tag in this scenario is useless, since without the htaccess redundancy, it doesn't work (or at least doesn't work fully). As mentioned originally, if the IE comments aren't wrapped around the html tag (they can still be used elsewhere) the meta tag works as expected. It seems to me like the HTML 5 boilerplate should be pushing for HTML(5) solutions. Not Apache ones.

@paulirish paulirish reopened this
@paulirish
Owner

reopened..

@paulirish
Owner

I just retitled the issue as "IE conditional comments around html tag adds Compat View icon to address bar"

Agreed this sucks. I don't think it'll make the 1.0 but let's figure out how best to address this for 1.1

@paulirish
Owner

Also I could repro in IE9 RC.. I imagine this is also present in IE8 final? Can someone confirm?

@ghost

The fix is as simple as getting that <meta http-equiv... /> in before the conditional comments. So to resolve it, we could do something like this:

<!doctype html>
<html class="no-js" lang="en">
    <head>
        <meta charset="utf-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
        <title>ie test</title>
    </head>
    <!--[if lt IE 7 ]> <body class="ie6"> <![endif]-->
    <!--[if IE 7 ]>    <body class="ie7"> <![endif]-->
    <!--[if IE 8 ]>    <body class="ie8"> <![endif]-->
    <!--[if (gte IE 9)|!(IE)]><!--> <body> <!--<![endif]-->
        <p>test</p>
    </body>
</html>

But it might be worth mentioning that "X-UA-Compatible" is not valid HTML5, so I think it's perfectly acceptable to remove it all together.

@MartinMa

I vaguely remember that there has been a reason for moving the conditional comments from the body tag to the html tag in the first place. Something with deferred loading of scripts in IE8?

Update: Ah, here it is http://webforscher.wordpress.com/2010/05/20/ie-6-slowing-down-ie-8/

@MartinMa

A potential solution to this problem could be this arrangement:

    <!doctype html>
    <html class="no-js" lang="en">
        <head>
            <meta charset="utf-8">
            <!--[if IE]><meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"><![endif]-->
            <title>Non-blocking downloads in IE8</title>
            <link rel="stylesheet" href="css/some.css">
            <link rel="stylesheet" href="css/random.css">
            <link rel="stylesheet" href="css/files.css">
            <!--[if IE 6 ]><link rel="stylesheet" href="css/and.css"><![endif]-->
            <link rel="stylesheet" href="css/a.css">
            <link rel="stylesheet" href="css/couple.css">
            <link rel="stylesheet" href="css/more.css">
            <link rel="stylesheet" href="css/huzzah.css">
        </head>
        <!--[if lt IE 7 ]> <body class="ie6"> <![endif]-->
        <!--[if IE 7 ]>    <body class="ie7"> <![endif]-->
        <!--[if IE 8 ]>    <body class="ie8"> <![endif]-->
        <!--[if (gte IE 9)|!(IE)]><!--> <body> <!--<![endif]-->
            <h1 style='color:green'>Non-blocking downloads in IE8.</h1>
        </body>
    </html>

This doesn't block downloads in IE 8 (see test cases below) and removes the compat view icon (only tested in current IE9).

Non-blocking: http://www.webpagetest.org/result/110320_MW_6S9X/

Blocking: http://www.webpagetest.org/result/110320_W1_6S9H/

P.S. As a plus it validates as HTML5 :)

@gabor

maybe the documentation could be changed a little (assuming the http-header method is bulletproof).
currently in the html it is:

<!-- Always force latest IE rendering engine (even in intranet) & Chrome Frame
       Remove this if you use the .htaccess -->
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">

we could change the html-comment to say something like you-should-do-this-in-htaccess-only-do-it-in-html-if-you-cannot-do-that...

@MartinMa

@gabor I agree, the http-header method should be the way to do this. Although Google planned to lobby validators to tolerate "X-*" http-equiv values and keys according to the comments on this issue here: http://code.google.com/p/chromium/issues/detail?id=22795

On another note, my sample code from above doesn't invoke chrome frame so it has to be changed to this (on line 5):

<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<!--[if IE]><![endif]-->

The empty conditional comment is because of the blocking issue in IE8. This all is starting to get a little messy :)

@irae

I also tested this issue and some combinations for resolving it. I believe that the better solution is to both move the conditional comments down and add the classes to with javascript:

<!doctype html>
<html class="no-js" lang="en">
<head>
  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
  <meta charset="utf-8">
  <!-- Always force latest IE rendering engine (even in intranet) & Chrome Frame
       Remove meta X-UA-Compatible if you use the .htaccess -->

  <!--[if lt IE 7 ]> <script>document.documentElement.className+=' ie6';</script> <![endif]-->
  <!--[if IE 7 ]>    <script>document.documentElement.className+=' ie7';</script> <![endif]-->
  <!--[if IE 8 ]>    <script>document.documentElement.className+=' ie8';</script> <![endif]-->
  <!-- Always put your css and js below this line, see
       https://github.com/paulirish/html5-boilerplate/issues/issue/378 -->

  <title></title>

I've added a pull request with this solution. The only downside I can imagine is having to support IE < 9 with javascript disabled. And this would be such an edge case that pointing an URL to this issue should resolve the problem.

@irae

I forgot to mention. AFAIK, Google Chrome frame docs advise putting the X-UA-Compatible as above in the document as possible. Since <meta charset="utf-8"> must be within the first 512 bytes it was necessary for it to be put before the X-UA-Compatible in previous versions.

So this time I changed the order, since the charset will not be affected by the conditional comments above it.

@shichuan

@irae: it might be a nice idea, but is it too much of a hack? imo

@ghost

I agree. I think the Javascript idea is very amateurish, especially since it seeks to resolve an issue caused by a piece of code that is not valid HTML5 in the first place. I would hate to see the HTML5 Boilerplate dragged away from the standards-compliance and best-practice foundation on which it was initially built.

Someone put in a pull request (might be the same guy; I don't remember) offering up the same bit of code. I would like to think that it isn't actually taken into serious consideration.

@irae

I also agree that this is amateurish. But I have a project that I am writing the front end code and I will not have access to the server. I don't even know where they will host it, what technologies, etc. This is a solution, ugly as it is, that is working better then the current solution of conditional comments around the <html> tag. In this case I prefer this ugliness that's only comments to modern browsers to broken functionality.

If anyone comes up with a better idea, I will be glad to change in my working projects and remove my own pull request.

@MartinMa

I noticed that my other comment on here is a bit distorted, so here are my two cents again.

  1. Either remove the meta tag altogether and refer to .htaccess (or other server config files).

  2. Or move the conditional comments down to the body tag. Like this:

    <!doctype html>
    <html class="no-js" lang="en">
        <head>
            <meta charset="utf-8">
            <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
            <!--[if IE]><![endif]-->
            <title>Everybody here is a cloud</title>
        </head>
        <!--[if lt IE 7 ]> <body class="ie6"> <![endif]-->
        <!--[if IE 7 ]>    <body class="ie7"> <![endif]-->
        <!--[if IE 8 ]>    <body class="ie8"> <![endif]-->
        <!--[if (gte IE 9)|!(IE)]><!--> <body> <!--<![endif]-->
            <h1>Everybody here will evaporate</h1>
        </body>
    </html>

Like I said before, we need the empty conditional comment because of the newly introduced "IE8 blocking Issue".
See test cases for details on that:
Non-blocking: http://www.webpagetest.org/result/110320_MW_6S9X/
Blocking: http://www.webpagetest.org/result/110320_W1_6S9H/

Thoughts? I like this one better, because it involves no Javascript to add the classes.

edit: corrected a little slip in the code

@necolas
Owner

@MartinMa: I think a problem with (2) is that a lot of CMS add id/classes to the body tag, which would create a lot of duplication. Furthermore, it could create problems for people writing IE6-specific styles because the browser doesn't really support chains of classes, e.g., ie6.mybodyclass {}

@shichuan

or we remove 'h5bp stripped version' and make h5bp download rely more on boilerplate custom (aka initializr), if people tick the option to have conditional comments, then a warning says they must have the X-UA-Compatible in server config.

@julienw

I use "<!--[if IE]><![endif]-->" as the very first line in my HTML files.
Then I use the "useful" conditional comments after the X-UA-Compatible meta.

IE8 is still in "IE8 Standards Mode". Didn't try with IE9 and I don't know how to check in IE7.

My 2 cents.

@necolas
Owner

ignore me

@julienw

I don't get it. I said I'm in standards mode event with these comments before the tag.

But some comments in this bug are saying that if you use some conditional comments around , then IE goes to quirks mode.

@necolas
Owner

@julienw Apologies, I misread your previous comment. If you open up IE8's dev tools, please can you check if you have "Browser Mode" set to "Internet Explorer 8" or "Internet Explorer 8 Compatibility View". If it's the former, it shouldn't drop the doc into IE7 Standards. If it's the later, it should drop the doc into IE7 Standards when using conditional comments outside of the opening html tag.

@julienw

I just checked using "IE8 Compatibility View", and it's still IE8 standards.

@necolas
Owner

@julienw Please could you drop a reduced testcase in a pastebin and link to it here? Thanks

@zachleat

Seems like there is a bit of confusion. Just because the button is showing doesn't mean that compatibility view is enabled. The button will be in a depressed state for that.

If the meta tag/http header is interpreted correctly, the button doesn't display at all (which is the desired behavior this ticket is trying to achieve).

@necolas
Owner

OK! @julienw seems correct, here's a basic testcase of what he is describing. It doesn't drop IE8 into IE7 mode. But other issues related to use on body remain.

Ex 1 : http://pastie.org/1926628

Switching the conditional comments back to the html element but leaving the empty conditional comment above the doctype also prevents IE8 from dropping into IE7 mode without needing the X-UA-Compatible header being set on the server-side.

Ex 2 : http://pastie.org/1926635

@julienw

Made this : http://pastie.org/1926658

Seems to trigger IE8 standards in both IE8 and IE8 Compat.

@necolas
Owner

@zachleat You may well be right about the confusion. Would be great if you got involved in this issue, if you have time. Thanks

@julienw

@zachleat @necolas in my code, I use document.documentMode to show the mode. Si I guess with this code there will be no confusion :)

@zachleat

This seems to get rid of the button, maintaining Standards mode in both IE8 and IE9.
https://gist.github.com/980895

You might also think that since we have a comment above the doctype, it might trigger quirks mode, but I tested it in IE7 too and it maintains Standards mode. IE must pre-process the conditional comments out prior to rendering, avoiding that bug somehow.

Please confirm, but take care to remove of any existing Compatibility View settings in your browser for intranet sites (Tools -> Compat View) or .htaccess rules that might interfere.

@necolas
Owner

@zachleat That was what I found in the "Ex 2" pastie as well. Glad you can confirm it.

@zachleat

@necolas Ah, apparently I'm horrible at reading. Sorry about that.

@paulirish
Owner

so an empty CC before the doctype eh

cool hack.. what do you guys think? put into the BP? or document.. this one seems like a tough call..

@irae

Is this safe to use? Does this work in feature phones browsers? Not that It would be a real problem, but it's best to know what kind of problem, if any, this could raise before inclusion.

@DingoEatingFuzz

Being the person who raised this issue, I obviously hate the compatibility view (aka, break your website) button a lot. However, I am also on the fence with this.

I honestly don't care about standards; I care about what makes my websites work. This part of me says put the hack in because it works.

The other part of me says don't put the hack in because boilerplate code isn't supposed to be bloated. If the average person is just going to delete the hack and opt for sending this via HTTP header then it shouldn't be in the code by default. It should just be documented.

So I guess my only question is, how many people will need/use this?

@necolas
Owner

@DingoEatingFuzz and others who have reporting this issue : please can you test to confirm if this alternative code avoids the issue too. It should do because the conditional comments appear after the X-UA meta tag and the opening html tag will be replaced by those that are included in head.

Another bonus is that you can stick all html attributes you want (lang and facebook xmlns stuff) on the html tag that is not within the conditional comments...the extra class in the conditional comment is then added to the first html tag. DRYer :)

<!doctype html>
<html lang="en">
    <head>
        <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
        <!--[if lt IE 7]><html class="no-js ie6"><![endif]-->
        <!--[if IE 7]><html class="no-js ie7"><![endif]-->
        <!--[if IE 8]><html class="no-js ie8"><![endif]-->
        <!--[if gt IE 8]><!--><html class="no-js"><!--<![endif]-->

        <meta charset="utf-8">
        <title>Document</title>
    </head>
    <body>
    </body>
</html>

vs

<!--[if IE]><![endif]-->
<!doctype html>
<html lang="en">
<!--[if lt IE 7]><html class="no-js ie6"><![endif]-->
<!--[if IE 7]><html class="no-js ie7"><![endif]-->
<!--[if IE 8]><html class="no-js ie8"><![endif]-->
<!--[if gt IE 8]><!--><html class="no-js"><!--<![endif]-->
    <head>
        <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
        <meta charset="utf-8">
        <title>Document</title>
    </head>
    <body>
    </body>
</html>
@irae

@DingoEatingFuzz I think that the people who needs this code most are probably the ones with less advanced html skils and possibly less able to configure apache (or other httpd).

I vote for inclusion with inline comment about it's removal.

Why? Removing is easier then inserting it and forgetting or not caring to remove it is (probably) less harmful then forgetting or not caring to insert it.

(and I'm still wishing for some kind soul with many phones available to test this on older phones)

@necolas
Owner

I've done a write up of @julienw's technique and the one I posted above http://nicolasgallagher.com/better-conditional-classnames-for-hack-free-css/

What do people think of these techniques?

@julienw

I think we have to understand what IE does.

My view is that it does some heuristics with the beginning of a file. We already know this for determining the content-type of a file, either with the first bytes or with the meta charset. But maybe he does this too for "preloading" the conditional comments engine (that could be why conditional comments around don't trigger the 100ms penalty), or for finding the document mode.

Someone has to do some more systematic tests, and it won't be me as I'll soon have no access to computer. :-)

@paulirish
Owner

Nice writeup.

To me, it seems like the best solution here is docs on setting this in your server config. Similar to the favicon stuff.. Set it back there and clean up the markup.

@guitarzan

@necolas I haven't tested it, but I think your double-<html>-tag idea should be written like so:

<!doctype html>
<html lang="en" class="no-js">
    <head>
        <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
        <!--[if lt IE 7]><html class="no-js ie6"><![endif]-->
        <!--[if IE 7]><html class="no-js ie7"><![endif]-->
        <!--[if IE 8]><html class="no-js ie8"><![endif]-->
        <!--[if gt IE 8]><html class="no-js"><![endif]-->
        <meta charset="utf-8">
        <title>Document</title>
    </head>
    <body>
    </body>
</html>

The difference is in the final conditional comment. Non-IE browsers will use the very first <html> tag and so don't need the extra one that shows up in the "gt IE 8" line. A further simplification is therefore possible:

<!doctype html>
<html lang="en" class="no-js">
    <head>
        <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
        <!--[if lt IE 7]><html class="no-js ie6"><![endif]-->
        <!--[if IE 7]><html class="no-js ie7"><![endif]-->
        <!--[if IE 8]><html class="no-js ie8"><![endif]-->
        <meta charset="utf-8">
        <title>Document</title>
    </head>
    <body>
    </body>
</html>

In this example, IE9 and up will use the original <html> tag just like non-IE browsers.

Finally, using the method in your most recent check-in on index.html, you could just write:

<!doctype html>
<html lang="en" class="no-js">
    <head>
        <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
        <!--[if lt IE 9]><html class="no-js oldie" lang="en"><![endif]-->
        <meta charset="utf-8">
        <title>Document</title>
    </head>
    <body>
    </body>
</html>

... and only old versions of IE would get the extra <html> tag. All other browsers (and validators) would see only the first.

@necolas
Owner

@guitarzan That won't work because the IE-specific classes won't bubble up to the first <html> tag. You can't have a class on the uncommented tag for this to work.

@guitarzan

I see (I think). So this would work:

<!doctype html>
<html lang="en">
    <head>
        <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
        <!--[if lt IE 9]><html class="oldie"><![endif]-->
        <meta charset="utf-8">
        <title>Document</title>
    </head>
    <body>
    </body>
</html>

... if you don't need the "no-js" class?

@necolas
Owner

@guitarzan Yes it would :)

@nimbupani

The final resolution for this thread is we will continue to recommend server side config and remove the html meta tag. Perhaps we need stronger words there to mention how using it server-side would be more useful?

@mathiasbynens mathiasbynens closed this issue from a commit
@mathiasbynens mathiasbynens Encourage people to send the X-UA-Compatible HTTP header instead of l…
…eaving it in the HTML, to avoid edge case issues. Fixes #378.
5e26749
@necolas
Owner

Eh?

@paulirish
Owner

anything prior to doctype will throw IE6 and only IE6 into quirks. fwiw.

@paulirish
Owner

fshost left this comment on my blog which more clearly states what he was trying to say here

If you wrap the html tag in conditionals ie 9 is going to throw the browser into quirks mode by default - which means that if you attempt to use the boilerplate code as is on an existing website, there is a good chance a standards compliant layout not intended for quirks mode is going to be destroyed. Just a heads up because some of the comments here are probably due to this.

as you can see there CC comments are AFTER the doctype. so.. this point is moot.

@necolas
Owner

But we havent got anything prior to the doctype. Don't get the comment about "moving on to a different template"

@paulirish
Owner

me neither!

also 20 people are getting emails for these... so let's shut up now. :D

@paulirish
Owner

♥♡♥

@paulirish
Owner

As this issue is referenced in our inline documentation, I wanted to add this extra data point:

@puresight found that..

To get IE 9 into edge mode on an intranet site, I had to send X-UA-Compatible as an HTTP Header--a meta wasn't enough

@gigafied gigafied referenced this issue from a commit
Commit has since been removed from the repository and is no longer available.
@barkan

I hate to raise the dead, but is there any reason that this isn't an option for people who have to put the tag in their HTML so it still validates?
<!--[if IE]>
<meta content="IE=edge,chrome=1" http-equiv="X-UA-Compatible" />
<![endif]-->

@andvik

yes this is an old issue, but you could include a web.config file with the following for IIS users - or add it in a comment somewhere so they know what to do if they don't run apache:

  <system.web>
    <httpProtocol>
      <customHeaders>
        <clear />
        <add name="X-UA-Compatible" value="IE=EmulateIE8" />
      </customHeaders>
    </httpProtocol>
  </system.web>

I would personally lean towards just including a web.config file with it in. It wont affect the apache server, just as the .htaccess wont affect IIS. Wouldn't having this in a web.config remove the need for the tag?

@andvik

ok - i feel silly now - there is already a web.config in the "Customize Boilerplate" section.

Anybody else finding this thread through a search for the solution - go customize your boilerplate and include "web.config" if your running ISS :)

@djcsdy

This is all preposterous.

Just wrap and apply classes to <body> instead of wrapping <html>. Problem solved.

@djcsdy

OK, so I skipped over some of the comments. Fair enough.

@TheDutchCoder

Is there a reason why this is kept in boilerplate if it:
1. Doesn't work as expected / intended;
2. Really is a webserver configuration thing that has no place in a template.

I'd prefer it to be not in the mark-up at all, but if it must, then please have it commented out. People who choose to use it, can always add it in.

@blaiseliu

andvik, isn't it supposed to be placed inside system.webServer?

like:

<system.webServer>
<httpProtocol>
  <customHeaders>
    <clear />
    <add name="X-UA-Compatible" value="IE=edge" />
  </customHeaders>
</httpProtocol>
...
@TheDutchCoder

blaiseliu: correct

@andvik

blaiseliu: Yes, I believe you are right - good catch

@garthvh

When IE sees conditional comments, it assumes the page is not standards compliant and kicks into compatibility mode overriding the meta tag value. Adding the value as a header in the httpProtocol section of the system.webServer section of the web.config is the only way I have consistently been able to force the browser to use the highest standards mode available on pages with conditional comments on them .

@peterdesmet peterdesmet referenced this issue in peterdesmet/peterdesmet.github.com
Open

Disqus comments do not load in IE 9 #17

@lovett lovett referenced this issue in cfpb/regulations-site
Closed

IE Compatibility Mode issues #433

@ascott1 ascott1 referenced this issue in cfpb/regulations-site
Merged

Finalize IE Warning & possible compatibility mode fix #449

@nternetinspired nternetinspired referenced this issue in joomla/joomla-cms
Closed

Use IE=edge by default. #2313

@redian redian referenced this issue in owncloud/core
Merged

Improve IE Compatibility #3179

@marcopontili marcopontili referenced this issue in jsbin/jsbin
Closed

Avoid IE Compatibility view mode #1633

@michaelwills michaelwills referenced this issue from a commit
Commit has since been removed from the repository and is no longer available.
@jchaney01 jchaney01 referenced this issue from a commit
Commit has since been removed from the repository and is no longer available.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.