NWDUG 2018 Sponsor
DrupalCamp Spain 2016 Sponsor
European Commission
ECMWF
EASA
United Nations
Hammersmith & Fulham
Alcatel-Lucent
Code Enigma
USAID
The Open University
4Music

Browser Modes, Document Modes, and Dealing with IE Compatibility View

|
source code on a laptop

The "Compatibility View" setting in Internet Explorer makes the browser pretend to be an older version (IE7) when displaying pages.

Microsoft's reasoning behind this is that a large number sites and internal web applications were designed for a specific version of Internet Explorer. When people upgrade to newer versions of IE, those sites may not work correctly anymore, if at all. Compatibility View makes old sites work again, but it comes with a cost.

When we launched a new site for one of our clients, their internal help desk got flooded with reports that the site was not rendering properly. Yet when we checked the site again, everything seemed normal in IE9, IE10 and IE11 - the supported IE versions.

We discovered that most non-power users within the corporate network had the "display in Compatibility View" setting enabled in their Internet Explorer settings for the corporate domain (the corporate site we relaunched).

IMAGE

This single checkbox setting turned out to be the cause of all the wailing and gnashing of teeth.

Understanding the IE Compatibility View setting

When IE Compatibility View is enabled for a certain domain three things happen:

  • IE will set its Browser Mode to "IE7" to identify itself as IE7. As a result, when the browser makes requests the relevant part of the user-agent string is set to "MSIE 7.0". Web Servers receiving the request will assume it came from an IE7 browser, and can act upon that information. This means you could send back a different response based on which browser version the request came from, if you wanted.

  • IE's Document Mode is also set to IE7. This will determine how IE displays the layout and how javascript and the DOM behave: IE will display the site as if it's IE7.

  • IE's Version Vector (stored in a registry key) is temporarily overridden to 7. IE uses the Version Vector when it processes conditional statements such as:

<!-- [if IE7] <link rel="stylesheet" type="text/css" href="/css/ie7.css"/><![endif] -->  
<!-- [if gte IE8] <link rel="stylesheet" type="text/css" href="/css/ie8.css"/><![endif] -->

In this scenario with Compatibility View enabled, IE versions higher than 7 will still use ie7.css and ignore ie8.css.

IE Compatibility View in corporate environments

You may find that IE Compatibility View is enabled in your browser for a certain site, yet you never added it to Compatibility View websites list.

There are two possible causes:

  1. Your network administrators pushed the site(s) to your Compatibility View site list via Microsoft's Group Policy Management.

  2. Your network administrators marked the site as an intranet site, and the checkbox "Display intranet sites in Compatibility View" is ticked. To learn more about this baviour, read: Stack Overflow - Why compatibility mode for intranet sites.

IMAGE

How to get around IE Compatibility View mode?

Modern websites that use the latest generation of html markup and css layout techniques can and will break in modern IE versions with IE Compatibility mode enabled.

To work around this problem we, as web developers, need a way say: "This is modern code. If you are a modern version of IE but happen to have Compatibility View mode enabled, ignore it for this particular site."

X-UA-COMPATIBLE to the rescue! It forces Internet Explorer to use a specific Document Mode to render our web page. We can either set this value using a META tag in the page source code, or add it as a custom header in our HTTP response.

The values we can set are:

  • "IE=edge"
  • "IE=11", "IE=EmulateIE11"
  • "IE=10", "IE=EmulateIE10"
  • "IE=9", "IE=EmulateIE9
  • "IE=8", "IE=EmulateIE8"
  • "IE=7", "IE=EmulateIE7"
  • "IE=5"

The most useful X-UA-COMPATIBLE value is "IE=edge", which means "use the highest, most recent Document Mode available". The other values have their use but are beyond the scope of this article. To learn more about supported values and use cases, read: Stack Overflow: What's the difference is X-UA-Compatible exists?.

To start using X-UA-Compatible you can either add it as a META tag to your html source, or include it as an HTTP header. Here's how:

Adding the X-UA-Compatible tag to your html source

Place the following META tag as high as possible inside the tags, preferably right after <title></title>:

<head>
  <title>Example Site</title>
  <meta http-equiv="X-UA-Compatible" content="IE=Edge">
</head>

There are several ways to do this:

Drupal 7 - option 1: add the META tag to html.tpl.php

  1. If your theme doesn't already have a html.tpl.php file, copy it over from the base theme you're using (if any) or from DRUPALROOT/modules/system/html.tpl.php

  2. Add the header directly under the title tag and save

Drupal 7 - option 2: inject the META tag via drupal_add_html_head():

In your theme's template.php, implement template_preprocess_html():

/**
 * Implements template_preprocess_html()
 */
function YOUR_THEME_NAME_preprocess_html(&$vars) {
  $tag = array(
    '#type' => 'html_tag',
    '#tag' => 'meta',
    '#attributes' => array(
      'http-equiv' => 'X-UA-Compatible',
      'content' => 'IE=edge',
    ),
    '#weight' => -99999,
  );
 drupal_add_html_head($tag, 'my_custom_ie_metatag');
}

Remark: we're setting the weight attribute to -9999 to make sure this element gets added tag as high up as possible in the <head> tag.

Django 1.9: add a middleware class that adds the header to the response object:

class XUACompatibleMiddleware(object):
    def process_response(self, request, response):
        response['X-UA-Compatible'] = 'IE=edge'
        return response

Django middleware example courtesy of https://gist.github.com/vstoykov/4989570

Adding the X-UA-COMPATIBLE header to the HTTP response

Setting X-UA-Compatible as an HTTP header is usually a better idea than setting it using the META tag because:

  • It keeps your html source cleaner.

  • It avoids the HTML5 validation error that occurs, since it's a non-standard (Microsoft-only) META tag.

  • It ensures that the directive gets parsed by IE before any other such directives in the html source. As soon as IE detects the directive in the HTTP response it will set the Document Mode and won't even bother with trying to interpret similar Document Mode-changing directives in the html source.

Option 1: make your web framework set the HTTP header

In php here's how you'd set the header:

<?php header('X-UA-Compatible: IE=edge'); ?>

Where and when you need to do this depends on how your application works.

If you're using Drupal 7, you can set an HTTP header with drupal_add_http_header().

A good place to do so would be in hook_init():

/**
 * Implements hook_init().
 */
function YOUR_MODULE_NAME_init() {
  drupal_add_http_header('X-UA-Compatible', 'IE=edge');
}

If you want to make sure this header is only added on responses to normal html requests and not on responses to ajax and other requests, you'll want to use hook_page_build().

This can also be a solution if you're having caching issues and you're finding that the header doesn't get set every time.

/**
 * Implements hook_page_build().
 */
function YOUR_MODULE_NAME_page_build(&$page) {
  drupal_add_http_header('X-UA-Compatible', 'IE=edge');
}

Option 2: make your web server set the HTTP header

Apache 2.2, Apache 2.4 (using .htaccess)

Add the following directive to the <IfModule mod_headers.c> block at the bottom of the .htaccess file, located in your Drupal root directory:

<IfModule mod_headers.c>
    [...]
    Header set X-UA-Compatible "IE=Edge"
</IfModule>

Remark: Make sure to use Header set instead of Header add. Using the latter can cause unforeseen consequences if the X-UA-Compatible header is already present. Header set will correctly replace any header with this name or create one if none exists.

Nginx (using a vhost)

Add the following to your site's vhost config file, on Debian systems most likely located at /etc/nginx/sites-available :

server {
   [...]
   add_header X-UA-Compatible "IE=Edge";
}
Microsoft IIS7 (using web.conf)

Add the following snippet inside the <system.webServer> block in the web.conf file, located in your Drupal root directory:

<system.webServer>
    [...]
    <httpProtocol>
      <customHeaders>
        <add name="X-UA-Compatible" value="IE=edge" />
      </customHeaders>
    </httpProtocol>
    [...]
</system.webServer>

Option 3: make your HTTP accelerator set the HTTP header

HTTP Accelerators such as Varnish can also be configured to set HTTP headers:

Add the following to your .vcl file, usually located at /etc/varnish on Debian systems:

sub vcl_deliver {
  if( resp.http.Content-Type ~ "text/html" ) {
    set resp.http.X-UA-Compatible = "IE=edge";
  }
}

Closing thoughts

X-UA-Compatible is a workaround for IE Compatibility View, which is a workaround for companies refusing to update old IE sites, which is inexcusable.

Neither X-UA-Compatible nor this whole article should have to exist.

Related resources:

Photo of html source code by Sai Kiran Anagani.

Author
Joeri PoesenDirector of Training
Upcoming events

Drupal 8 Core Concepts
17 DEC 2018 - London (1 day)
Seats available - register now

Drupal 8 for Content Editors
18 + 19 DEC 2018 - London (2 days)
Seats available - register now

Drupal 8 for Site Builders
20 + 21 DEC 2018 - London (2 days)
Seats available - register now

Subscribe to the Pathway mailing list

You can unsubscribe at any time by clicking the link in the footer of our emails.

For information about our privacy practices, please visit our privacy policy.

We use Mailchimp as our marketing platform.

By clicking below to subscribe, you acknowledge that your information will be transferred to Mailchimp for processing. Learn more about Mailchimp's privacy practices here.

Past events

Drupal 8 for Site Builders
OCT 2017 - Malaga (2 days)
Registration closed

Drupal 8 Module Development
OCT 2017 - Malaga (2 days)
Registration closed

Drupal 8 Theme Development
OCT 2017 - Malaga (1 day)
Registration closed