Making the Web Bigger: DPI Scaling and Internet Explorer 8

This topic contains the following sections:

  • Introduction
  • DPI Scaling in Windows
  • DPI Scaling in Internet Explorer 8
    • Scaling the Chrome
    • Scaling the Web
    • Image Scaling in Internet Explorer 8
    • How to Get Back to the Default 96 DPI Web
  • Information for Developers
    • Favicons
    • Opt-In to High DPI Behavior for Web Browser Controls (WebOCs)
    • Detecting User DPI Scaling Settings With JScript
    • Providing Higher Resolution Images for Higher DPIs
    • Potential Layout Issues with Zoom and How to Fix Them

Introduction

Have you ever been bothered by the small text, images, and UI elements in Windows applications, or Web pages? This scenario has become more and more common because as display technology advances, display manufacturers keep packing more and more pixels into displays. While text, images, and UI elements can look much sharper and more readable on higher-resolution displays, the operating system has to take advantage of the extra pixels and scale up the visual Windows experience as a whole—otherwise, everything will just look smaller.

Here is an example of how a Web page appears on two displays that have the same physical dimension (15.1 inches diagonal) but different pixel densities:

Figure 1: Display with Low Pixel Density (Native Resolution: 960x600).

Figure 2: Display with High Pixel Density (Native Resolution: 1680x1050).

You can see that in Figure 1, the width of the Web page is about the same as that of the display; the Web page is thus much easier to read than it is in Figure 2. In Figure 2, the Web page takes up about half of the display width and is thus more difficult to read. You will also notice that the icons, text on the menu bars, and the status bars are also smaller and more difficult to see. (The advantage of this is that you have quite a bit more screen real estate in which to view your applications).

To address the issue of Web page content appearing small, many users lower the display resolution and thus prevent themselves from viewing Web pages at a native resolution: the resolution that a display is meant to be used at. Although the content does look larger as a result, it also looks less sharp. This is not an optimal solution, because users are not taking advantage of all the pixels that are available to them. The optimal solution is to use the display at its native resolution in combination with the Windows DPI Scaling feature.

DPI Scaling in Windows

In a nutshell, the Windows DPI Scaling feature will scale up fonts and UI elements (such as buttons, icons, input fields) by a certain percentage specified by a user. This is different from the scaling that occurs when the user lowers the display resolution: in the case of DPI Scaling, Windows provides fonts and UI elements that are drawn with more pixels, resulting in a larger, higher fidelity, and sharper Windows experience. (It is important to note that third-party Windows applications are responsible for being DPI-aware on their own. Microsoft is working with third-party developers to make this happen.)

The following procedure describes how to adjust DPI Scaling in Windows Vista.

  1. Open Control Pane.

  2. Double-click Personalization.

  3. In the left pane, under Tasks, click Adjust font size (DPI).

  4. Set DPI Scaling to 120 DPI by clicking the option button for Larger scale (120 DPI). To set DPI Scaling to other values, click the Custom DPI button.

DPI means "dots per inch," which can also be understood as "pixels per inch." Every display has a certain physical DPI, determined by how many pixels are packed into a physical inch of the display. The DPI Scaling setting communicates to Windows what physical DPI it should optimize for, thus the optimal experience will be achieved if the DPI scaling of Windows is set to a DPI value that is close to the physical DPI of the display.

DPI Scaling in Internet Explorer 8

Scaling the Chrome

Like Windows Vista, the Windows Internet Explorer 8 UI is entirely High DPI Aware, and you will notice that all UI Elements and UI Fonts are scaled accordingly. Additionally, larger and higher fidelity icons are used. Notice the difference in the Windows Internet Explorer chrome when Windows DPI Scaling is set to 96 DPI and 120 DPI, respectively:

Figure 3: Internet Explorer Chrome at 96 DPI.

Figure 4: Internet Explorer Chrome at 120 DPI.

Scaling the Web

By default, Internet Explorer 8 will zoom the content of a Web page to match your Windows DPI Scaling settings. (This is a change from Windows Internet Explorer 7, which did not zoom to match Windows DPI Scaling settings.) For example, if you set the DPI Scaling to 120 DPI, Internet Explorer 8 will zoom the content of a Web page by 125%, because scaling is done relative to 96 DPI, and 120/96 equals 1.25, or 125%. This is reflected in the Zoom UI in the bottom-right corner of the browser window:

In 96 DPI In 120 DPI In 144 DPI

 

On a related note, according to the CSS 2.1 specification, Web authors are told to assume that they are writing Web pages for a 96-DPI display, which also makes 96 DPI the Web default.

You might be wondering what it means to zoom the content of a Web page. At the basic level, the new Adaptive Zoom feature in Internet Explorer 8 will use the zoom factor to scale all elements that are defined with absolute lengths, but not those that are defined with relative lengths. This strategy cuts down on the appearance of horizontal scrollbars as well as other formatting problems that existed with the Internet Explorer 7 zoom.

Image Scaling in Internet Explorer 8

One of the improvements in Internet Explorer 8 is the usage of bicubic interpolation—a scaling algorithm that is an improvement of that used in Internet Explorer 7—to scale images on a Web page. Bicubic interpolation is used whenever an image is sized to a width and height that are not equal to the image's native dimensions, and it allows image scaling to occur whenever zoom is set to a value other than 100%.

Figure 5: Logo on left is scaled 50% using bicubic interpolation. Logo on right is scaled using nearest neighbor.

It is important to note that a scaled image will never look as crisp as the original, regardless of the type of interpolation method. However, the reduction in quality due to image scaling is less noticeable when the physical DPI of a display is close to the Windows DPI Scaling setting. For example, if we compare two displays, one with a physical DPI of 96 and the other of 120, the latter will have 125% more pixels per inch. This also means that the pixels on the 96-DPI display are 125% larger than those on the 120-DPI display. Therefore, when an image is scaled on the 120-DPI display to 125%, the interpolation method will fill in data for the extra pixels; however, because these pixels are smaller as compared to the 96-DPI display, the resulting image should look comparable to the original as viewed on the 96-DPI display. Of course, we are still not taking full advantage of the extra pixels of the higher-DPI display, but we will talk later about how developers can do this.

If you would like to opt -out of bicubic interpolation, you can use the CSS vendor property -ms-interpolation-mode and set it to nearest-neighbor:

<img style="-ms-interpolation-mode:nearest-neighbor" src="IE_Logo_150.png" alt="IE Logo" height="150" width="150">

How to Get Back to the Default 96 DPI Web

There are times when you might not want Internet Explorer to zoom pages for you: for example, when a page might not have been designed with zooming in mind, or when you might be testing how a Web page will appear to a user on a standard 96-DPI system; and that is fine. By setting the zoom factor to 100%, Internet Explorer 8 makes it very easy to get back to a standard 96-DPI viewing of Web pages:

As of Internet Explorer 8 Release Candidate 1, Internet Explorer will remember your last set zoom state. If you would like the old behavior back (Reset zoom to default for new Windows and tabs):

  1. Click Tools.

  2. Click Internet Options.

  3. Click the Advanced tab.

  4. Select Reset zoom level for new Windows and tabs.

  5. Click OK.

Of course, if you want to simulate how a page looks by default on a system that takes advantage of Windows DPI Scaling, you can set the zoom factor accordingly: 120 DPI = 125%, 144 DPI = 150%, and so on.

Information for Developers

Although DPI Scaling in Internet Explorer 8 is designed such that it is transparent to users and developers alike, there are things a developer can do to take full advantage of Internet Explorer High DPI behavior.

Favicons

A "favicon" is a small graphic that replaces the standard Web page icon when you visit a Web site. (See How to Add a Shortcut Icon to a Web Page.) Before Internet Explorer 8, releases of the browser have used 16x16 Web site favicons in several places in the main UI:

  • In the Address bar, when a Web site is loaded
  • In the Favorites list
  • On a tab, when a Web site is loaded
  • In the search box, for a search Web site

When Windows DPI Scaling is set to a value higher than 96 (100%), Internet Explorer 8 will draw all favicons at 24x24 pixels.

To get the best visual quality, Web site designers should also include a 24x24 bitmap in their favicon.ico (along with the 16x16 bitmap), so that Internet Explorer 8 can display a true 24x24 bitmap on the screen.

For example, to do this using Visual Studio 2008:

  1. Open the favicon.ico file in Visual Studio 2008 (press CTRL+O).

  2. Open the Image menu, then New Image Type.

  3. Click the Custom button.

  4. Set the bitmap size:

  5. Click OK, and design the 24x24 icon in the bitmap editor.

  6. Add the favicon.ico file to your site.

If only a 16x16 bitmap is available in a site's favicon.ico (as is the case for most sites today), Internet Explorer 8 will not scale up the bitmap, but rather will render the 16x16 icon on top of a page icon that is designed at 24x24 resolution. Here are examples for www.live.com on a system set to 120 DPI:

Figure 6: Address Bar

Figure 7: Tab Title

Figure 8: Search Box

Opt-In to High DPI Behavior for Web Browser Controls (WebOCs)

In order to preserve compatibility with previously developed WebOCs, by default Internet Explorer 8 does not render the web content of WebOCs using the Internet Explorer 8 High DPI behavior, but rather uses the Internet Explorer 7 behavior, which scales up fonts specified in absolute values, such as points. To take advantage of the Internet Explorer 8 High DPI behavior in your programs, you need to use a DOCHOSTUIFLAG called DOCHOSTUIFLAG_DPI_AWARE. You use this flag by using the method GetHostInfo, which has a DOCHOSTUIINFO structure as one of its parameters. In turn, DOCHOSTUIINFO has a operator DWORD called dwFlags as one of its members, that can consist of one or more DOCHOSTUIFLAG values. You must include DOCHOSTUIFLAG_DPI_AWARE in dwFlags in order to take advantage of the Internet Explorer 8 High DPI behavior in your WebOC.

The quick and easy way to simulate how the HTML content of your WebOCs will appear once opted -in to the High -DPI behavior is to open the equivalent HTML content (composed in an HTML file) in Internet Explorer 8, and simply check out the rendering at the equivalent zoom settings (120 DPI to 125% zoom, 144 DPI to 150% zoom). We do recommend that you test out the WebOC in actual High DPI scenarios to be completely sure the HTML content renders as you hoped.

Detecting User DPI Scaling Settings With JScript

There are times when you might want to know at which DPI Scaling a user is viewing your Web page. You can find this information by querying the screen.deviceXDPI or screen.deviceYDPI DOM property. For example, if the page is zoomed to 125%, screen.deviceXDPI will return 120 (120/96 equals 1.25, or 125%). Note, however, that the value returned is entirely dependent on the zoom state of Internet Explorer and not necessarily the DPI Scaling Setting of Windows. For example, if your Windows DPI Scaling is set to 144 DPI and you are viewing a Web page at 100% zoom, screen.deviceXDPI will return 96 (96/96 equals 1, or 100%), not 144.

Once you have the DPI information, you can:

  • Make layout tweaks to optimize for different DPIs.
  • Swap in higher-resolution images to take advantage of the extra pixels available to you (thus avoiding the use of imperfect image interpolation).
  • Place elements on a Web page relative to the browser chrome.

Providing Higher Resolution Images for Higher DPIs

As mentioned previously, a potential downside of zooming in on a Web page is the imperfect nature of scaling up images. There are a couple of ways a developer cannot only get around this, but can take advantage of the fact that they now have more pixels to work with. The following solutions can also be taken advantage of by WebOC developers when it comes to their HTML content, assuming they opted in to High DPI behavior as described previously.

Substitution Method

<html>
<head>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<title>High DPI Images</title>
<style type="text/css">
img {
        border: 2px solid black;
}
</style>
</head>
<body>
<img src="IE_Logo_150.png" alt="IE Logo" height="150" width="150">
</body>
</html>

The simplest method is to provide a higher resolution image, but specify the appropriate (smaller) size in the height and width attributes of img. For example, let's say you currently have an image on a page that is 150 by 150 pixels:

<html>
<head>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<title>High DPI Images</title>
<style type="text/css"> 
img {
    border: 2px solid black;
}
</style>
</head>
<body>
<img src="IE_Logo_150.png" alt="IE Logo" height="150" width="150">
</body>
</html>

Figure 9: 150x150 at 100% Zoom

Now, if we zoom into this page at 200%, the image is scaled to 300 by 300 pixels, and therefore looks less sharp:

Figure 10: 150x150 at 200% Zoom

Now, if we instead insert a 300 by 300 pixel image (not just scaled but specifically designed for that size) in place of the original, we'll be taking advantage of the extra pixels. The image will instead be scaled down for all zoom levels below 200%. Scaling images down has way better results than scaling images up because in the latter case image interpolation is essentially making up data by creating pixels where there were none in the original, while in the former case pixels are being removed. We do not change anything in the HTML besides the source image:

<html>
<head>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<title>High DPI Images</title>
<style type="text/css"> 
img {
        border: 2px solid black;
}
</style>
</head>
<body>
<img src="IE_Logo_300.png" alt="IE Logo" height="150" width="150">
</body>
</html>

Please note that the height and width parameters of the image must be specified, otherwise Internet Explorer will render the image at its native size at 100% zoom, and will scale accordingly relative to the native size of the image for other zoom settings.

Figure 11: 300x300 (Left) vs. 150x150 (Right) at 100% Zoom. Note how they are virtually identical.

Figure 12: 300x300 (Left) vs. 150x150 (Right) at 200% Zoom. 300x300 clearly has higher fidelity.

Although this provides a higher fidelity experience when zoomed, larger images means larger file sizes, and larger file sizes means your page will use higher bandwidth and will be slower to load. Additionally, you will be providing larger images to those who won't necessarily gain any benefit because they are viewing your page at 100%.

JScript DPI Detection Method

As mentioned previously, you can detect the DPI rendering of your page, which corresponds to zoom setting, by checking the screen.deviceXDPI DOM property. You can use this property to feed up different images to users based on their zoom setting. Also note that the onresize event is triggered upon change of zoom factor, therefore you should make sure that any code that takes into account DPI is executed when the onresize event is triggered, as well. Here is an example that loads in an image specifically targeted at 96 (100%), 120 (125%), 144 (150%), and 192 (200%) DPI:

<!doctype>
<html>
<head>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<title>High DPI Images</title>
<style type="text/css"> 
img {
        border: 2px solid black;
        float:left;
}
 
#information {
        float:left;
        margin-left: 10px;
}
</style>
<script type="text/javascript"> 
var lastDPI;
var dpiAwareImageEl;
var zoomSettingEl;
var imageNameEl;
var titleEl;
var image96dpi;
var imag120dpi;
var image144dpi;
var image192dpi;
 
window.onload = onLoad;
 
function onLoad() {
    dpiAwareImageEl= document.getElementById('dpi_aware');
    zoomSettingEl = document.getElementById('zoom_setting');
    imageNameEl = document.getElementById('image_name');
    titleEl = document.getElementById('title');

    image96dpi = 'IE_Logo_150.png';
    image120dpi = 'IE_Logo_180.png';
    image144dpi = 'IE_Logo_225.png';
    image192dpi = 'IE_Logo_300.png';
 
 
    if (screen.deviceXDPI) { // To avoid throwing JavaScript errors in other browsers
        lastDPI = screen.deviceXDPI;
        window.onresize = onResize;
        zoomSettingEl.innerHTML = lastDPI/96*100;
 
    }
 
    
    assignImage();
}
 
function onResize() {
    if (lastDPI != screen.deviceXDPI) { // Only take action if zoom factor has changed (won't be triggered by actual resize of window)
        lastDPI = screen.deviceXDPI;
        zoomSettingEl.innerHTML = lastDPI/96*100;
        assignImage();
    
    }
}    
 
function assignImage() {
    if (screen.deviceXDPI <= '96' || !screen.deviceXDPI) { // 100% Zoom or less, or non-IE browser
        dpiAwareImageEl.src = image96dpi;
        imageNameEl.innerHTML = image96dpi;
    }
    else if (screen.deviceXDPI <= '120') { // 125% Zoom
        dpiAwareImageEl.src = image120dpi;
        imageNameEl.innerHTML = image120dpi;

    }
    else if (screen.deviceXDPI <= '144') { // 150% Zoom
        dpiAwareImageEl.src = image144dpi;
        imageNameEl.innerHTML = image144dpi;

    }
    else { // Greater than 150% Zoom
        dpiAwareImageEl.src = image192dpi;
        imageNameEl.innerHTML = image192dpi;
    }
}
</script>
</head>
<body>
<h1 id="title">Providing Higher Resolution Images for Different Zoom Factors</h1>
<img id="dpi_aware" alt="IE Logo" height="150" width="150">
<div id="information">
    <div>Zoom Setting: <span id="zoom_setting">100</span>%</div>
    <div>Image file used: <span id="image_name">IE_Logo_150.png</span></div>
</div>
</body>
</html>

Although providing specific images for all of these zoom levels is overkill, this example illustrates how you can customize your code in order to adjust your page for any zoom level granularity you'd like, and this isn't limited to substituting images.

Potential Layout Issues with Zoom and How to Fix Them

Although one of the mail goals of Internet Explorer 8 Zoom is to provide benefits to end users without requiring web developers to modify their code, there are a couple of issues that might arise when viewing pages at a zoom level not equal to 100%.

Microsoft Silverlight Applications

You may come across a site where a Silverlight application is not scaling with zoom and/or not being laid out correctly relative to other elements on the page. As of version 2.0, Silverlight is not DPI-aware. However, you can add minimal code in order to get the appropriate functionality. Using the knowledge that a resize event is triggered on zoom, you can listen for the Content.Resized event in your Silverlight Application:

   App.Current.Host.Content.Resized += new EventHandler(Content_Resized);

Here is a simple example that scales the entire application based on the zoom-adjusted width of the Silverlight object container:

  • In the XAML, put a ScaleTransform that you will use when the Silverlight plug-in resizes:

    <UserControl.RenderTransform>
        <TransformGroup>
            <ScaleTransform x:Name="zoomTransform" ScaleX="1" ScaleY="1"/>
        </TransformGroup>
    </UserControl.RenderTransform>
    
  • Lastly, apply the scale as a factor of your application's size:

    void Content_Resized(object sender, EventArgs e)
    {
        System.<tla rid="windows"/>.Interop.Content content = App.Current.Host.Content;
    
        double scalePlayerX = (content.ActualWidth / this.Width);
        double scalePlayerY = (content.ActualHeight / this.Height);
    
        this.zoomTransform.ScaleX = scalePlayerX;
        this.zoomTransform.ScaleY = scalePlayerY;
    }
    

This is a very quick and easy solution, but one problem with it is that the fonts as well as the images are being scaled with interpolation, and in turn will add fuzziness to them. Additionally, scaling will also be caused by resizing of the window rather than just by zoom.

There is a better, but more involved way, of making Silverlight High DPI aware. As mentioned previously, you can detect the zoom factor of the given page using the screen.deviceXDPI DOM property. This property is accessible via the HtmlWindow.Eval method:

double pageDPI = HtmlPage.Window.Eval("screen.deviceXDPI");
double scaleFactor = (pageDPI / 96);

Note  Since screen.deviceXDPI is unique to Internet Explorer, you need to be careful using the property when developing Silverlight applications cross-browser.

 

You can then use this information for such things as to lay out your application again, provide higher resolution images, and substitute larger fonts, upon the Content.Resized event and application initialization. By dividing pageDPI by 96, you will get the scaling factor that you need to provide a more enhanced experience for varying zoom levels. For example, let's say your application used a font that was 12px normally (at 100% zoom). If the user zooms to 150% on the page that contains your application, pageDPI will give you 144 and scaleFactor will give you 1.5. You can then change your application's font size to 12px * 1.5 = 18px in the initialization and Content.Resized handler, which will cause your application's fonts to scale relative to the user's zoom setting.

Adobe Flash Applications

In the same vein, there are sites where Flash applications do not scale with zoom or are not laid out properly relative to other elements on the page. Similarly to how you fix the issue for Silverlight applications as outlined above, you need to respond to the Flash Stage.onResize event, which is triggered upon Zoom in Internet Explorer 8. You can also access screen.deviceXDPI via ExternalInterface.call method. (Note: Since screen.deviceXDPI is unique to Internet Explorer, you need to be careful upon using the property when developing Flash applications cross-browser). The rest is beyond the scope of this topic, but you can find additional information about Flash programming at http://www.adobe.com/devnet/flash/.