Same Markup: Writing Cross-Browser Code


I recently presented a session at MIX10 covering the topic of cross-browser best practices. The key focus of the session was not on a particular feature, but on how web developers can reliably write code that adapts to cross-browser differences.


IE9 reduces these differences and enables developers to use the same markup across browsers. Enabling the same markup means supporting the right features to make the same HTML, JavaScript, and CSS “just work”. Yet enabling the same markup on the web is an n-way street. Each browser must provide the right features, but developers also need to properly detect and use those features when they are available.


With respect to properly detecting features I’ll share examples of issues and best practices I’ve seen on the web. Most importantly I’ll offer patterns that can help you rewrite similar code to take advantage of the same markup. For now I’ll focus on more basic examples to illustrate the core concepts, but future posts will cover more complex examples in greater detail. Let me start by sharing a set of guidelines:


Same Markup: Core Guidelines



  • DO

    • Feature Detection
      Test whether a browser supports a feature before using it.

    • Behavior Detection
      Test for known issues before applying a workaround.

  • DON’T

    • Detect Specific Browsers
      Also known as browser detection. Don’t use the identity of a browser (e.g. navigator.userAgent) to alter page behavior.

    • Assume Unrelated Features
      Don’t perform feature detection for one feature, and then proceed to use a different feature.

These guidelines are important because most web pages today are a hybrid of code meant for multiple different browsers. Mixed in with this code are the tests for choosing what runs where. The conditions used in such tests determine how a page adapts to run on different browsers. From script at least, these tests generally take the following form:


if( condition ) {
// Primary Code
} else {
// Alternate Code
}

The conditions used in such tests are often not based on whether a given feature is available, but rather on which browser is in use. Therein lies the problem: altering code based on a specific browser limits the adaptability of web pages. The end result can be as serious as the page breaking when a new browser is released. Other times a legacy workaround continues to be used, even when that workaround is no longer needed.


DON’T: Detect Specific Browsers – Event Registration Example


You can easily test the effects yourself. The code below switches between event models based on the detected browser (a bad practice). Running this in IE9 illustrates that addEventListener doesn’t get used, even though it’s supported.


// [TR] Different listeners added for illustration
function f1() { document.write(“addEventListener was used”); }
function f2() { document.write(“attachEvent was used”); }

// DON’T USE THIS: Detecting specific browsers
if(navigator.userAgent.indexOf(“MSIE”) == -1) {
window.addEventListener(“load”, f1, false);
} else {
window.attachEvent(“onload”, f2);
}

Try It!

IE9 Output: attachEvent was used


DO: Feature Detection – Event Registration Example


The following code shows how to switch between event models correctly using feature detection. Instead of checking for IE, it checks for the availability of addEventListener itself. This code will continue to fallback correctly in legacy browsers without addEventListener, but more importantly will now ALWAYS use addEventListener when it is available. In short, this approach enables running the same markup in IE9 and other browsers.


// [TR] Different listeners added for illustration
function f1() { document.write(“addEventListener was used”); }
function f2() { document.write(“attachEvent was used”); }

// Use this: Feature Detection
if(window.addEventListener) {
window.addEventListener(“load”, f1, false);
} else if(window.attachEvent) {
window.attachEvent(“onload”, f2);
}

Try It!

IE9 Output: addEventListener was used


The challenge of getting the right code to run in the right browser is why feature detection has been seeing increased adoption in pages and frameworks. Feature detection enables cross-browser code to “just work” without requiring you to know the capabilities of each and every browser ahead of time. One framework which relies almost entirely on feature detection is jQuery. In fact the jQuery.support documentation details how you can use jQuery’s feature detection in your own site.


DO: Behavior Detection – getElementById Example from jQuery


In addition to straight feature detection, jQuery also makes extensive use of behavior detection. It does this by running a tests for known issues to determine if certain workarounds are needed. Below is a slightly modified snippet from the jQuery source code that tests whether getElementById includes elements with “name” attributes. This is a legacy IE bug that was fixed in IE8.


// We’re going to inject a fake input element with a specified name
var form = document.createElement(“div”),
id = “script” + (new Date).getTime();
form.innerHTML = “<a name='” + id + “‘/>”;

// Inject it into the root element, check its status, and remove it quickly
var root = document.documentElement;
root.insertBefore( form, root.firstChild );

// The workaround has to do additional checks after a getElementById
// Which slows things down for other browsers (hence the branching)
if ( document.getElementById( id ) ) {
// … Workaround code …

// [TR] Added for illustration
document.write(“getElementById workaround was used”);
}
// [TR] Added for illustration
else document.write(“No workaround was used”);

root.removeChild( form );

Try It!

IE9 Output: No workaround was used


DON’T: Assume Unrelated Features – Real-World Example


The final piece I want to touch on is assuming unrelated features. This is something we saw a number of examples of as we did compatibility testing for IE8. Sites suffering from this problem would perform feature detection for one feature, then continue to use a variety of other features without testing whether they were supported. The following modified example illustrates a case where a site was using the postMessage and addEventListener APIs, but was only testing for the former. Support for postMessage was added in IE8, but addEventListener was not added until IE9. If you run this example unmodified in IE8, it results in a script error, preventing any following script from executing.


// [TR] Try-catch block added to trap the script error in IE8
try {
function fn() {}

if(window.postMessage) {
window.addEventListener(“message”, fn, false);

// [TR] Added for illustration
document.write(“Message listener registered successfully”);
} else {
// … workaround for when postMessage is unavailable …

// [TR] Added for illustration
document.write(“postMessage is not supported, using workaround”);
}

} catch(e) {
document.write(“Message listener registration FAILED”);
}

Try It!

IE7 Output: postMessage is not supported, using workaround
IE8 Output: Message listener registration FAILED
IE9 Output: Message listener registered successfully


DO: Feature Detection – Test for Unrelated Features Independently


A corrected version of the above example is provided below. It checks for BOTH postMessage and addEventListener before using them.


function fn() {}

if(window.postMessage) {
if(window.addEventListener) {
window.addEventListener(“message”, fn, false);
} else if(window.attachEvent) {
window.attachEvent(“onmessage”, fn);
}

// [TR] Added for illustration
document.write(“Message listener registered successfully”);
} else {
// … workaround for when postMessage is unavailable …
// [TR] Added for illustration
document.write(“postMessage is not supported, using workaround”);
}

Try It!

IE7 Output: postMessage is not supported, using workaround
IE8 Output: Message listener registered successfully
IE9 Output: Message listener registered successfully


Moving Forward


I’ve outlined the benefits of using feature and behavior detection over detecting specific browsers, but my intent is for this to be the start of a conversation, not the end of it. Watch for future posts covering more detailed examples of issues we’ve seen on the web and how they can be coded to work correctly across all browsers. We’ll also be examining our own sites and encouraging them to update to follow these practices. Please feel free to ask questions and share insights, especially around specific issues you’ve encountered while developing your own pages.


Tony Ross
Program Manager



Comments (79)

  1. Anonymous says:

    If you start deleting my posts that has no insults, bad mouthing and got just the plain hard opinion again, I will f*cking troll this site forever

  2. Anonymous says:

    F*cking bullsh*t dictators. main reason I hate you microsoft, f*ck off

  3. Anonymous says:

    F%¨&%$&ERS KEEP DELETING MY COMMENTS

  4. Anonymous says:

    What kind of web world do you guys live in? You have a bastard child (IE6) wreaking havoc at 9 years of age, and a retarded cousing (IE7) doing the same.

    It’s even "funnier" that you didn’t mention it (IE6) on the post. Yet I find it pretty harsh, since it’s completly yours, and even msn.com website looks awkward in IE6, why don’t include that on the "cross browser" testings as well? Since it’s market share is bigger than Firefox 3.6 anyway?

    Being a web programmer, having to support, now with the coming of IE9, 4 browsers separatedly, make my work a bit dull and boring while fixing the entire site for IE, but I happily code once for standards browsers like Firefox and Chrome.

    Not sure if this will ever come to an end, since no support for IE9 on XP, way to go microsoft!

  5. Anonymous says:

    @wechrome try playing with PNG transparency in ANY IE. try using fadein/fadeout. try divs floating on top of flash (on any IE). using mouseover, mouseenter, or mousemove on an ul with li’s with margins or borders (awesome flicker effect). hacks to make multiple backgrounds, stacking a bunch of divs to create something simple, like a piano glow on a black gradient background, or stupid read-only javascript properties that aren’t read-only on any other browser, no XHTML at all, have to stick to the freak HTML + some XML markup, poor CSS2.1 implementation, slow javascript, the list is endless.

    No IE is standard and they all suck big time, and I can’t expect less from IE9, because, ahem, it’s microsoft with "their standards".

    So yeah, basically, I will have a conditional comment for IE 6, IE7, IE8 and IE9, great feeling. People wasn’t expecting to have stylesheets only for IE8 as well, and guess what, it happened anyway ;)

    Or you can go hacky, and use EMULATE IE7 lol, or any other hacky X-UA-COMPATIBLE *¨%# so you won’t need to bother with broken IE8 in any mode.

    And it’s "funny" how Firefox, Chrome and Opera displays the website from last post (being unibanco.com.br) just fine, even in quirks mode and not being IE, but IE7 and beyond fail, as usual and expected.

  6. Anonymous says:

    it is awesome, and really great. Thank you a lot…

    <a href="http://www.hileindir.net">hile indir</a>,

  7. Anonymous says:

    it is awesome, and really great. Thank you a lot…

  8. Anonymous says:

    阿彌陀佛 無相佈施

    不要吃五辛(葷菜,在古代宗教指的是一些食用後會影響性情、慾望的植

    物,主要有五種葷菜,合稱五葷,佛家與道家所指有異。

    近代則訛稱含有動物性成分的餐飲食物為「葷菜」,事實上這在古代是稱

    之為腥。所謂「葷腥」即這兩類的合稱。 葷菜

    維基百科,自由的百科全書

    (重定向自五辛) 佛家五葷

    在佛家另稱為五辛,五種辛味之菜。根據《楞嚴經》記載,佛家五葷為大

    蒜、小蒜、興渠、慈蔥、茖蔥;五葷生啖增恚,使人易怒;熟食發淫,令

    人多慾。[1]

    《本草備要》註解云:「慈蔥,冬蔥也;茖蔥,山蔥也;興渠,西域菜,云

    即中國之荽。」

    興渠另說為洋蔥。) 肉 蛋 奶?!

    念楞嚴經 *∞窮盡相關 消去無關 證據 時效 念阿彌陀佛往生西方極樂世界

    我想製造自己的行為反作用力

    不婚 不生子女 生生世世不當老師

    log 二0.3010 三0.47710.48 五0.6990 七0.8451 .85

    root 二1.414 1.41 三1.732 1.73五 2.236 2.24七 2.646

    =>十3.16 π∈Q’ 一點八1.34

  9. Anonymous says:

    Lol you f*cks, you deleted most of my comments, eat sh!t. I’m going to troll this site for a while o/

  10. Anonymous says:

    Hey IE team, why don’t you stick your heads out of your a$$es and just drop the whole fvcking IE lameness, else we will have to use Chrome Frame forever

    http://code.google.com/chrome/chromeframe/

  11. Anonymous says:

    Hail the new Microsoft dictatorship!

  12. carlos says:

    Again, just switch to webkit. Concentrate your efforts in the user interface.

    The wheel ( decent engine that support near 100% of old and modern web standards ) was invented years ago and it is rolling.

    Just my 2 cents.

  13. Wurst says:

    On IE there exists "navigator.plugins" but it is always empty.

  14. wechrome says:

    @Menace,

    "Being a web programmer, having to support, now with the coming of IE9, 4 browsers separatedly, make my work a bit dull and boring while fixing the entire site for IE, but I happily code once for standards browsers like Firefox and Chrome."

    What 4 browsers separately? IE6 is horrible, IE7 is bad, sure, but IE8 is mostly not requiring any specific fixes. So you just code once, and it mostly works across Firefox, IE8, and Chrome. I have spent countless hours to fix webpages for IE6 and IE7, but I don’t remember spending much time fixing webpages for IE8 at all.

    For today’s web developers, you can treat IE8 and IE9 as "standards browsers" most of the time already, unlike IE6 and IE7.

    As far as I see, you can just code once, and expect it to work all okay in Firefox, Chrome, Opera, Safari, and IE9. Then you may need to fix some minor things with just under minutes for IE8. It’s the IE6 and IE7 specific problems that mostly always take hours upon hours to fix.

  15. Wurst says:

    »With the new features that Internet Explorer 4.0 provides, it may be desirable for both client-side and server-side scripts to determine the browser version, so that a Web application can either take advantage of new functionality, or degrade gracefully, depending on the version of the currently-running browser.«

    http://support.microsoft.com/kb/167820

  16. raffi12 says:

    @carlos

    Which webkit should they use? Browsers based on webkit all render differently and support different features.  Especially the mobile versions of webkit.

    Besides they can do better if they want.

  17. vmajor says:

    @wechrome

    IE8 does not work well at all if there is javascript on the page. We have so many problems with getting our sites to work with IE8 that it takes up about 20% of our development time and sometimes it is impossible to make IE8 work within the allotted resource allowances so we just turn the advanced features off.

    The necessity to do that disgusts me, but until IE dies or Microsoft grows a conscience or a soul we are stuck with having to hack our sites for the benefit of the uninformed users that use IE8 (or even worse IE6 or IE7).

    Yes I likewise wish that MS dumped their core and adopt Webkit or Gecko (or even Presto)  and dress them up. MS can indeed build a nice interface and GUI.

  18. mocax says:

    i just stick to a css framework (960 grid) and js library (jquery), so i’ve got little or no problems with cross-browser compatibility.

    let the guys at jquery handle the headaches :D

  19. Jack says:

    Thanks for a good article.

    Would all the whiners here rather have Microsoft NOT telling web developers to use good programming?

  20. wechrome says:

    @Menace, I’m talking about real world production site, not some flashy bleeding-edge experimental sites.

    And yes IE8 still lacks some nice visual effects, but those are not needed. Unlike IE6/7 that can usually makes a site completely a mess, with IE8 it’s easy to degrade gracefully, so those people with Opera/Chrome can see a flashy site, while those with IE8 sees a non-flashy, but still very much functional site.

    If we give browser scores, and Opera/Chrome get 100 points, Firefox gets 95 point, then I’d say IE8 gets 80 points, compared to IE7 at 40 points, IE6 at 20 points.

    If you insist on making the whole site flashy and pixel-perfect in all browsers, then yes IE8 can cost you some time, but IE6 would cost you exponentially more time. But if you aim for a functional site for everyone and give those with Opera/Chrome some extra nice effects (which is what most real world web developer are doing nowadays, as trying to implement those same effects in IE6 is simply practically impossible), then IE8 hardly cost you any extra work. It’s the IE6 and IE7 that are the big pain, you mostly don’t need IE8 specific hacks and the site is still quite functional.

    And what part of CSS2.1 is IE8 poor at? IE8 is poor at CCS3 for sure, but its CSS2.1 implementation is mostly quite okay.

    @vmajor, if you put 20% development for IE8 specific problems, I’d wonder how much time you put for IE7 and IE6? I’d say IE7 would cost 10 times more development time, and IE6 100 times more time, than IE8.

    Really, if you want some super advanced and complex Javascript features, then reserve them for Opera/Chrome, and turn them off for IE versions less than 9.

    Again turning off some advanced effects is easy, as compared to fixing a complete mess from the ground up.

    Like I said, it’s quite easy to do graceful degradation with IE8, usually taking just minutes. Not supporting some advanced features and technology (IE8) is one thing, doing some basic things the wrong way (IE6/7) is another completely different, and exponentially more severe, problem.

  21. graham says:

    @Menance – I guess the question for you si what kind of developer world do you live in? No browser is perfect, especially when it comes to javascript. It’s our job as developers to work within the constraints of all browsers, aiming for progressive enhancement enables people on up to date browsers to enjoy a rich user experience, while people on older browsers can still access the content. Don’t forget it is the content people want, not just a pretty picture. If you can’t get a site to work it’s time to check in with the design teamand make amends there.

    Of course you’ll spend some time on IE6 but this shouldn’t be a lot, mostly with layout and checking for script errors – the latter a very good use of the browser. Again, a few more checks and fixes for IE7 but never really any that warrent an IE7 specific stylesheet. IE8, once you’re familiar with it, throws up as many problems as a firefox or safari – it’s a good browser with great CSS2.1 support.

    IE9 is looking amazing and we should really be thanking the team to embracing the developer communities rather than bashing them every time they post on this blog. Are you feeding back to the working groups MS are now part of? This is how you, as a developer, can make a difference. IE6 is really starting to fade away and it’s amazing to be part of another round of browser wars/advances that are really pushing web development forward in a way not seen for the last few years.

  22. or you could do says:

    Or you could just do:

    <!IE < 9 cond comment>

     <script src="legacyIEHacks.js"></script>

    <!end legacy IE hacks–>

    then do all your normal code using standards based calls.

    Call document.getElementById(id) and it just works.  Use jQuery’s $(‘#id’) and it just works.

    I have no intention of littering my code with hacks and tests to handle legacy bugs in IE6, IE7, & IE8.

  23. Kevin says:

    Thanks for this article. The info is quite helpful.

  24. Grah says:

    Actually, I think the "DONT" postMessage example is a relatively legitimate one. The event model is a pretty integral part of anything you do with the DOM, so… not supporting it sucks for the ones not supporting it.

    If this was authored before IE8 was out, I hereby grant absolution to the developer responsible.

    If this was authored when IE8 was out… well then I guess it’s between god and the dev.

    It’s obviously hitting some of the wrong guys (the MS devs cleaning up after the mess), but ya took tha job, ya know? My sympathy is limited.

  25. Will Peavy says:

    @carlos and vmajor: In what specific way would Webkit (in place of Trident 5) improve IE9?

  26. @Tony Ross [MSFT]

    First of all, your post is entirely about javascript and javascript code (browser forking). In my opinion, it has nothing to do with markup or same markup (repeated 7 times in your post).

    Checking the capability and support of an object is one thing but checking it for the correct object is as equally important. E.g. When Opera 7 came out, it had support for addEventListener but only for DOM nodes, not for the window object. This sort of situation can happen. It’s always better, best and more reliable to test support on the object which is going to be used. Your post does not explicitly mention this. You mentioned the guideline of same method or same feature but not same object or same DOM node.

    I have always avoided to register the load event to the window because document and window are loaded asynchronuously. In my opinion, it always better to register the load event on the body element, not the window, in other to do whatever script you want.

    Coding manners

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

    var form = document.createElement("div")

    is quite awkward and counter-intuitive. Why not

    var objDiv = document.createElement("div")

    ? or even a more semantic variable name serving the purpose of the code?

    form.innerHTML = "<a name=’" + id + "’/>";

    Can you create a minimized anchor in HTML5? Why create an empty anchor in any HTML document to begin with?

    Why create and try to DOM-insert an empty anchor before the document root element? This does not seem coherent, logical or even possible to begin with. (FWIW, the script fails in Konqueror 4.4.2.)

    If all this is allowed in HTML5, then it certainly is weird looking to me.

    Other references

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

    Your post is very silent on what other browser manufacturers’ documentation have been provided during years.

    Object detection

    http://developer.apple.com/internet/webcontent/objectdetection.html

    at Apple

    Towards capability detection at Opera

    http://dev.opera.com/articles/view/using-capability-detection/

    Developing Cross Browser/Cross Platform Pages

    https://developer.mozilla.org/en/Using_Web_Standards_in_your_Web_Pages/Developing_Cross_Browser//Cross_Platform_Pages

    A Strategy That Works: Object/Feature Detecting from comp.lang.javascript FAQ

    http://jibbering.com/faq/faq_notes/not_browser_detect.html#bdFD

    > We’ll also be examining our own sites and encouraging them to update to follow these practices.

    Yes. That is very very important to do this. Utterly important. The X-UA-compatible meta-tag system would not have been any useful if Microsoft/MSDN had started to explain how to detect support for method or feature in objects or DOM nodes years ago.

    regards, Gérard

  27. Why create and try to DOM-insert an empty anchor before the document root element?

    root.insertBefore( form, root.firstChild );

    Correction. The code inserts it before the root’s first child which is the <head> node. It is definitely not a good example. I do not understand how this can work without javascript errors…

    regards, Gérard

  28. Victoria says:

    I don’t know how Microsoft can even dare to lecture web developers about proper web standard practices when their browser doesn’t even follow the correct standards! It is like being told to use your umbrella during a flood.

    I have to use browser detection because some versions of IE, especially IE6, don’t render some of my layouts correctly.  In that way, an alternative layout can be displayed to those users (along with a message telling them to get a proper browser!)

    Maybe when you start to show a proper commitment to web standards, people will take note of what you are saying here.

  29. Luke says:

    <<The X-UA-compatible meta-tag system would not have been any useful if Microsoft/MSDN had started to explain how to detect support for method or feature in objects or DOM nodes years ago.>>

    Pure, unsubstantiated fantasy, yet again.

    MSDN documentation does not magically make for better web code. MSDN documentation *plainly* stated that STRICT mode would result in new behavior in new browser versions, and yet (surprise, surprise) there was shock and dismay from the web community when this happened in IE7 and begging for the "UA-Compatible" system which was eventually introduced.

    Rather than wasting your time rewriting history in the IEBlog comments, how about you start your own blog evangelizing best practices, and try to find some way to get readers to follow your guidance? They’re clearly not following the best-practices listed on MSDN for the last decade.

  30. Wurst says:

    @Victoria: I hope you are not using JavaScript for this.

  31. @wechrome

    > If we give browser scores, and Opera/Chrome get 100 points, Firefox gets 95 point, then I’d say IE8 gets 80 points, compared to IE7 at 40 points, IE6 at 20 points.

    On which topic are those scores about or coming from? Ease of developing a web-standards-compliant website? I may agree with you on those scores… but you did not define on what topic or perspective such scores apply to.

    > what part of CSS2.1 is IE8 poor at?

    Margin collapsing, clearance, integer implementation (for z-index, orphans and widows), border-style: hidden, min- and max- properties, cursor parsing, visibility, etc.

    @Wurst

    > "navigator.plugins" but it is always empty.

    Many people reported this already, including in IE Blog in 2009.

    regards, Gérard

  32. Tino Zijdel says:

    > We’ll also be examining our own sites and encouraging them to update to follow these practices.

    That’s great. You may want to start with the browser ballot page ( http://www.browserchoice.eu/BrowserChoice/browserchoice_en.htm ) – I already created an improved version for you: http://crisp.tweakblogs.net/blog/3751/the-ms-browser-ballot-page-analyzed.html ;)

  33. Will says:

    tino, the "ballot" page was obviously designed by eu-government lawyers.

  34. ken says:

    @Wurst re: the KB link

    "APPLIES TO

       * Microsoft Internet Explorer 3.0

       * Microsoft Internet Explorer 3.01

       * Microsoft Internet Explorer 3.02

       * Microsoft Internet Explorer 4.0 128-Bit Edition"

    I *really* hope you don’t support those…

  35. carlos says:

    @Will Peavy

    "@carlos and vmajor: In what specific way would Webkit (in place of Trident 5) improve IE9?"

    For example, IE will instantly scalate from 28% to 88% of SVG support (*)

    (*) http://www.codedread.com/svg-support.php

  36. Gary says:

    Since when has a scripting language suddenly changed to a markup language?

    HTML -> Markup

    ECMA/JavaScript -> Scripting.

    Clue is in the name really.

  37. Menace says:

    @graham I deal with QUALITY online, semantic HTML coding and EYECANDY for the prospects/clietns of my clients, I use 960.gs, I use jquery 1.4.2, I use Flash for somethings Javascript is too slow to do, and have a lot of clients, and been doing web for a lot of time. Don’t come pointing fingers.

  38. Mitch 74 says:

    @Menace: while I can’t fault you for using jQuery, and I applaud your quest for quality, you haven’t done "real" JS coding if you haven’t tried doing object detection without standing on the shoulders of giants.

    But still, there is a difference to be made, right now.

    CSS support and DOM support.

    While CSS support improved a LOT between IE 6 and IE 8 (IE 8 is, indeed, almost painless to synchronize with other browsers while IE 6 actually REQUIRES a few kb of CSS fixes – IE 7 fixes most of these, but also has its own quirks and regressions), the DOM saw very little improvement between the 3 versions.

    If I must take a very simple example where object detection fails, or gets VERY difficult, is with innerHTML: if you check that it is supported, it IS supported. If you try to run it as a write property, it works.

    If you try to use it as a write property on a table or table body, you get a fatal error of ‘unknown’ origin.

    And that’s in IE 6/7/8 only.

  39. Dave Hodder says:

    This is all very good advice.  There’s far too much code out there doing browser sniffing rather than behavior detection.  And the "assuming unrelated features" problem will undoubtedly cause real issues once IE9 is released with addEventListener() and more.  Thanks for making this post.

  40. Rob says:

    @Mitch 74:

    … you haven’t done "real" JS coding if you haven’t tried doing object detection without standing on the shoulders of giants …

    Really? Seriously? So if someone wrote an implementation of a linked list in Javascript, or say, a large LOB application using ExtJs/JQuery/a.n.other framework, or any other number of complex things, they still wouldn’t have done "real" javascript coding? I guess if the definition of doing "real" javascript coding is "doing object detection", you’re utterly correct. In this instance though, I think you’re quite far from there. If that’s the case, perhaps we should all go back to coding in assembly? ;)

  41. Mitch 74 says:

    @Rob: I wasn’t being derogatory; I just wanted to emphasize how, using libraries like jQuery, which abstract all this stuff of "object detection and quirks workaround" in a browser, hides away the trouble that people that develop for a browser without these libraries (for performance and/or size reasons, or simply because they actually MAKE those libraries) may encounter.

    That does NOT detract from the actual skill of the programmer; however, since the topic at hand is object detection, I’ll say, and I stand by what I say, developing something from A to Z for all browsers is a PAIN. If you’re doing ECMAscript on top of jQuery, then it means you NEED each and every user to download 24 Kb of jQuery libraries (that’s the current, already gzipped, code-packed version) on top of your own code. If you’re programming for internal use, you don’t have too many visitors, alright; if you have thousands of visitors a day, then it means megabytes of bandwidth.

    If I take my own situation, object detection code FOR MY OWN USE requires, compressed and packed, around 3K. Total code stands at 10 K. If I had used jQuery, I would have needed 30 K total (some, but not all, of my non-detection code would probably not be required with jQuery).

    With 10 000 visitors/month, most of them unique (no caching)  and not including bots, that would have meant 200 Mbytes/month extra traffic. Just for jQuery. Bandwidth ain’t cheap, and I have a tight budget.

  42. Matt says:

    Mitch, Google would be happy to host JQuery on their ultra-fast CDN for you, with long-lived cache headers. Since it’s shared cross-site, chances are good it’s already in the end-user’s cache anyway.

    http://encosia.com/2008/12/10/3-reasons-why-you-should-let-google-host-jquery-for-you/

  43. Matt says:

    @Mitch: Also, where are you hosting? I get 400gigs/month for $27 bucks. So, in your example, the marginal bandwidth cost is about 1.3 cents. Which is less than most programmers make per minute.

  44. Menace says:

    @Mitch 74 well, there’s something called cache and exist for solely a reason. When you control your cache the way you want, you won’t have any bandwidth problems over the major benefit it brings. If you know how to create a gzip/custom headers/packaging proxy in PHP, you wouldn’t be questioning about bandwidth.

    I always coded using "vanilla" Javascript, since 1998, until I first met jQuery in 2007. The main reason I stuck with it is the cross-browser facility. If IE wouldn’t exist anymore, I think I would just be using querySelector/All and still plain vanilla javascript. The fancy flashy stuff is flash’s job (until canvas and svg is par to it).

  45. Phil says:

    @Matt – not in today’s economy :-)

  46. @Jack

    > Would all the whiners here rather have Microsoft NOT telling web developers to use good programming?

    Oject/method support detection has been proposed and recommended many years ago (july 26 2004) in this blog and many years before that. In 2008, Scott Dickens [MSFT] continued to promote user agent string detection in Code Focus magazine. MSDN has never stopped promoting, explaining, examplifying user agent string detection and has been silent about object/method support detection.

    comp.lang.javascript newsgroup FAQ notes and Peter-Paul Koch quirksmode site were promoting and explaining about object/method support detection a lot sooner than 2004. Again, IE Team/Microsoft/MSDN have been promoting user agent string detection for probably over 10 years.

    The work on IE7 and IE8 (2005 to 2008) was in no way whatsoever preventing IE Team/MSDN to update their documentation and tutorials and in no way whatsoever preventing Microsoft/MSDN from upgrading their coding techniques and practices. We have excellent reasons to state and claim that IE Team/MSDN/Microsoft controlled websites are not what they should be.

    Gérard Talbot

  47. Luke says:

    Gerard: Have you noticed that the problem with lying on the internet is that it’s so easy to get caught?

    Scott’s 2008 article simply explained what user-agent string IE8 sent, and it in *no way suggested* that sites should be writing code that depends upon it.

    As for MSDN, yes, there are decade-old articles about IE4 that are clearly marked as "retired" and not updated. On the other hand, the most popular article "Detecting Internet Explorer" explicitly says: "It is not recommended that you block access to content based on the user-agent string of the browser." and "Serving content based solely on the user-agent string is often an unreliable way to detect the full capabilities of the browser."

    So, I say again, rather than wasting your time rewriting history in the IEBlog comments, how about you start your own blog evangelizing best practices, and try to find some way to get readers to follow your guidance? They’re clearly not following the best-practices listed on MSDN for the last decade.

  48. Mitch 74 says:

    @Menace: as I said, I get thousands of UNIQUE visitors to my websites (different IPs and all). As such, caching is useless – so I plainly deactivated caching in some cases, because otherwise I’d get nags from people using stale copies (for some reasons, IE sometimes refuses to check if the server copy is newer – oh, right, "auto" caching is so efficient). And, I also mentioned that my JS libraries were already packed and compressed.

    I could simply link to the jQuery website and use THEIR bandwidth for jQuery. I’d rather not, it’s rude.

    @Luke: while there are, indeed, rather recent articles that promote object detection, sadly I have to side with Gérard here. Many many MANY MSDN articles still promote UA detection.

    And there’s one good reason for it: you can try and perform object detection as much as you want, the fact is that many objects are claimed as supported by IE – but are so quirky you need to check that they work properly before you use them.

    Case in point, to use document.getElementById, should you check:

    – that it merely is supported?

    Or should you also check that it returns:

    – a collection if several elements share the same ID?

    – an element that has the required value, but for its ‘name’ property?

    – an ID with a different case?

    Answer:

    – IE 6 returns a collection if several elements have the same ID. This is erroneous: only one element should have a given ID. So, getElementById should NEVER return a collection.

    – IE 7 looks at name and ID for that property. It’s completely wrong: several elements may have the same name (think select-one), and name != ID

    – IE 7 is case insensitive on attribute values: that is completely wrong.

    And, right there, MSDN defines that (I cite):

    "Returns the first object with the specified ID or NAME."

    That same article contains a link: http://msdn.microsoft.com/en-us/library/cc288325%28v=VS.85%29.aspx

    Title: Defining Document Compatibility

    I cite the second line of the first Jscript example in that page:

    if (window.navigator.appName == "Microsoft Internet Explorer")

    What’s wrong with that, let’s see… First, it uses a lax comparison (==) instead of a strict one (both are supposed to be strings, thus you should use === to ensure there is no unwanted type conversion happening). Second, it detects the user agent’s name.

    Yay object detection in MSDN.

  49. EricLaw says:

    <<(for some reasons, IE sometimes refuses to check if the server copy is newer)>>

    There are no known issues with over-aggressive caching when the server sends proper cache directives. To understand how HTTP caching works, please see http://www.enhanceie.com/redir/?id=httpperf.

    <<I could simply link to the jQuery website and use THEIR bandwidth for jQuery.>>

    I believe John actually takes technical measures to prevent that, or has in the past.

  50. Dave Ward says:

    Regarding jQuery hosting, it’s not only acceptable, but encouraged to use the copy hosted on Google’s CDN.  They put it (and other libraries) there specifically for that very reason.

    My recent research has shown that a surprisingly high number of the Alexa top 100,000 are using it too.  So, you do have a good chance of a cache hit primed by another site, even if you don’t have any repeat users of your own.

  51. Rob^_^ says:

    Here is an interesting feature test to try

       if (typeof (google) == ‘object’)

       { sAns = ‘Yes'; }

       else

       { sAns = ‘No'; }

       document.writeln("<p><span>Google Gears – " + sAns + "</span></p>");

       if (typeof (chromium) == ‘object’)

       { sAns = ‘Yes'; }

       else

       { sAns = ‘No'; }

       document.writeln("<p><span>Google Chromium – " + sAns + "</span></p>");

    Try this on a page loaded in Chromium or in IE8 where Google Gears has been installed.

  52. Wurst says:

    @Dave Ward

    Microsoft is also hosting jQuery:

    http://www.asp.net/ajaxlibrary/cdn.ashx

  53. Jelges says:

    Hallo, will IE9 include a download manager to be able to pause downloads and maybe with container file and Torrent File support?

    How about including an option to save a browser session maybe even saving it to a file or some kind of hibernation for IE9?

    Why don’t You plan an IE9 GDI Version for Windows XP?

    Thanks.

    Sincerely Jelges

  54. Adi says:

    Why not Microsoft, Mozilla, Apple, Google, Opera etc get together and develop a common standard?

    In this way, developers will have to write one single code for all browsers and it will be less work for you as well.

  55. Hoink says:

    @Jelges: Even if the devs wanted to support XP they’d have to get it past the Microsoft lawyers.

  56. Mitch 74 says:

    @Adi: that’s what the W3C is, basically. Sadly, it took 6 years for MS to remember they were members, and then 4 more years to remember that, "oh, right – we should also implement what is studied there". Or something. Gross, biased oversimplification on my part – the IE team started implementing stuff anew in IE 7, and started doing it correctly in 8. And 9 is getting mightily interesting.

    @EricLaw: no known issue with aggressive caching? Well then, how comes that my host defines "Expires" at 1981, and I still get caching?

    @Matt: your hosting budget is ten times mine. Literally. Yes, my boss is Scrooge’s spiritual heir. And the host disabled caching, and compression, and… whatever. Making saving a byte wherever possible, a priority. If I could manually gzip my files and send them with appropriate headers, I’d do it too (I tried: headers are overwritten).

  57. Andy Earnshaw says:

    Just to re-iterate my previous comment to another post, it would be great to be able to opt into IE9’s script engine only.  With IE8 you have to run in IE8 standards mode to access the new scripting features, meaning you have to target multiple versions of IE using different CSS which can be quite awkward and time consuming.

    PS EricLaw did respond to that comment and I think he missed my point of opting into the scripting engine, I totally understand forcing the scripting engine might break old sites but if I were given the choice with a particular command (or meta tag) it wouldn’t be a problem.

  58. Mitch 74 says:

    @Andy: the problem isn’t so much with the scripting engine itself (it is actually shipped separately from IE) than it is with IE’s DOM support (the objects that IE supports can be manipulated with Jscript)…

  59. mrx says:

    I think I.E needs his own automatic update, a lof of people doesnt run windows update so there browser is obsolete.

  60. Luke says:

    <<<a lof of people doesnt run windows update >>>

    I’m not sure where you get your information, mrx– you’re not exactly in a position to know this.

    If users aren’t keeping the rest of Windows up-to-date, they’re insecure anyway.

  61. EricLaw [MSFT] says:

    @Andy: No, I didn’t miss your point; as I replied to your original comment, I simply agree with Mitch.

    @Mitch: Pretend I’m from Missouri– please provide a repro URL or network capture (www.fiddlercap.com). Keep in mind that HTTP Cache-Control headers override the Expires header. Who is your hosting provider, by the way?

    @Hoink: I’m not sure what you’re implying?

  62. Wurst says:

    @Mitch: Compression header overwritten? I knew that transparent proxies used for information control purposes (censoring) would do that, but hosting providers?!

  63. Wurst says:

    OT: IE Testing Center has a faulty test according to Mozilla devs: https://bugzilla.mozilla.org/show_bug.cgi?id=554016

  64. Hoink says:

    @EricLaw[MSFT]:

    I was just guessing. From the blog of another MS employee:

    « Although the XmlLite developers wanted to provide a redistributable for Windows XP, they never managed to get it past the Microsoft lawyers. »

    http://weblogs.asp.net/kennykerr/archive/2009/12/24/windows-web-services-fail.aspx

  65. EricLaw [MSFT] says:

    @Hoink: IE8 on XP uses XMLLite. "Redistributable" means that 3rd parties may ship it.

  66. anonymous says:

    Microsoft has completely abandoned Windows XP by not supporting IE9. This is the worst kiss-off to any Microsoft product I’ve ever seen, and one’d think MS would show a little more respect to its best-selling OS of all time. But the reality is, Microsoft is looking ahead to new revenue and not behind to money that’s already in the bank. And hundreds of millions of people will be running XP for years to come, despite Microsoft’s best efforts at selling them a later Windows version. This flies in the face of its publicly-stated life cycle support plans.

  67. Mitch 74 says:

    @EricLaw: headers…

    Expires: Thu, 19 Nov 1981 08:52:00 GMT

    Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0

    Provider: Nuxit (yes, in France)

    Sample URL: see above… Alright, I don’t update it THAT often any more. It’s very unsettling when I do update the thing and test it "live", and all browsers happily chug along with refreshing the cache, …but IE. And I mean IE 5,6,7 and 8 (actually, since I deactivated scripting for IE6-, I get trouble with 7, 8 and 9DP1).

    @Wurst: inexpensive hosts on shared servers will save resources by disabling compression. But, since you have stuff like CMS that try to enable it by forcibly defining HTTP headers, you may need (in order to prevent an HTTP 500 error) to prevent said headers from being sent. "Rewriting" is too strong a word, sorry – it’s more a header restriction.

  68. Matt says:

    <<This flies in the face of its publicly-stated life cycle support plans.>>

    No, it absolutely does not.

    And for those keeping score, Win7 is by far the fastest selling OS of all time.

  69. EricLaw [MSFT] says:

    @Mitch74: By “link above” do you mean the MoneyShop.fr link?

    If so, I’m rather confused. Your homepage is GZIP compressed, while you earlier said you wasn’t allowed?

    On the homepage itself, I do see the no-cache directives, including the bogus “pre-check=0″ and “post-check=0″ directives added by PHP for no reason (http://blogs.msdn.com/ieinternals/archive/2009/07/20/Using-post_2D00_check-and-pre_2D00_check-cache-directives.aspx).

    However, on the resources (images,script,css) your page uses, I see no caching directives at all, which permits their future reuse without validation.

    I don’t see any caching of your homepage itself; on every visit, I see a new request for the content. It’s not even a conditional request, because the homepage itself provides neither an ETAG nor a Last-Modified time.

  70. Mitch 74 says:

    @EricLaw: OK, now I get it: I investigated more. And I can confirm one thing: it’s only text/html content that allows (and even forces) compression. Any other content (application/xhtml+xml, text/x-javascript, text/css) will not be compressed – even if required through htaccess or in file header modifications.

    And, silly me, I send application/xhtml+xml MIMEtypes to those browsers (meaning, Firefox, Safari, Chrome(ium), Opera, IE 9) that explicitly support it (yeah, well, it helps me detect mistakes in my mark-up faster).

    And I must admit, I program in Firefox first (which shows me headers with a key press) and test in IE last (which requires me starting a VM, then load Fiddler, then open IE, then look at page headers… impractical).

    Now, about the CSS and Javascript being cacheable: well, I hardly can put META http-equiv elements in it, can I… And since the cache headers are pretty much frozen by my host (I can add extra headers, but not modify existing ones), well, tough for me.

    Note that when I test a new version of my code, I usually make use of Ctrl+F5 (same thing in IE and Fx, it bypasses the cache) – but even when I do that, I sometimes get "stale" code in IE 8. Never in Fx or other browsers.

    Thinking harder about it, and ‘logging’ how I test my code updates, it may be that the peeve I have against IE’s cache is that Ctrl+F5 is less reliable in it than in Fx.

    Considering that a debug session may have me press that combo a hundred times a day, it becomes a bit of a blur. Still, would you mind having a harder look at Ctrl+F5’s behaviour in IE 9?

    Note: suggestions to disable the cache in developer tools will be ignored. I need to see if my customers may get a mere annoyance or a complete break (so switching back’n’forth ain’t a solution, while a working Ctrl+F5 would be).

  71. EricLaw [MSFT] says:

    @Mitch: I’m sorry to hear your web host isn’t working well for you. I’m not sure whether they have any local competition which might offer you a better experience.

    As for the browser issues, I spend a LOT of time looking at Internet Explorer’s network behavior, and I’ve never seen the behavior you describe. I’ve never seen CTRL+F5 fail to unconditionally re-request resources, for instance.

    Does your ISP perhaps have a transparent proxy which is doing overaggressive and illegal caching?

  72. Mitch 74 says:

    @EricLaw: AFAIK, no proxy – and if it were the case, it would affect all browsers, not IE alone (except if they set up the proxy to rat on IE…). I can usually solve IE’s problem with hitting Ctrl+F5 twice, but not always.

    There recently was a time when I had to open developer tools, flush the cache, close IE 8, then reopen it and open again to see the actual files; this occurred even on my development machine, and the only thing between the server and IE 8 was the virtual machine’s NAT (and Windows’ proxy)

    It could have been a matter of having two tabs with the website open, and refreshing one didn’t work as the other (thus, with stale copies) was already loaded.

    Maybe I’m the odd one out there, as I develop on a LAMP physical machine (without a proxy nor cache), and test in a VM’ed Windows. I don’t see how that would affect the results, though – but I could be that one-in-a-million person affected by that Shroedinbug. Or could it come from my webpages’ size? I try to keep them small (under 32K), maybe I trigger something… Frankly, I don’t know.

  73. EricLaw [MSFT] says:

    > it would affect all browsers

    You mentioned that you were sending XHTML to the other browsers and HTML to IE. That could well explain the difference in a network intermediary’s behavior.

    If you ever manage to get a network capture of bad behavior (e.g. with Ethereal, Charles, Fiddler, etc), I’d love to have a look– just mail it to me.  Thanks.

  74. Wurst says:

    « Does your ISP perhaps have a transparent proxy which is doing overaggressive and illegal caching? »

    I heard about 3G ISPs using similar stupid and page-breaking methods.

  75. Mitch 74 says:

    @EricLaw: I will, for sure.

    If I can catch it, that is…

    @Wurst: I’ve heard about stuff like that. But as far as I know, my dev machine doesn’t have a proxy.

  76. wechrome says:

    @Gérard Talbot,

    "On which topic are those scores about or coming from? Ease of developing a web-standards-compliant website? I may agree with you on those scores… but you did not define on what topic or perspective such scores apply to."

    Since the topic I was talking about was developing a functional site across different browsers, the scores are obvious about the ease of developing a functional site (not necessarily a fully W3C-validated site) across those browsers, and how much trouble (or the lack thereof) they have given me in the past.

    For the past two months, I have encountered about a couple dozen problems in my current project, and ALL of them are IE6 and IE7 specific. Especially IE6, it’s just frustrating that perfectly valid markup can result in IE6 RANDOMLY show or hide a part of the page at each refresh, and after two days of fruitless attempts at fixing the problem, putting one extra useless div around another existing div at some completely unrelated place somehow fixes the problem O_o

    And it’s not even any complex site at all, all simple effects, no flashy stuff, that I haven’t encounter a single IE8 problem for those same couple months. It just works with IE8 like it does with Firefox/Opera/Chrome. the existence of IE6 and IE7 is the sole reason that I’m currently four days behind my schedule *_*

    It’s those kind of illogical, at times seemingly random, problems from IE6 and IE7 that frustrate the most.

    "Margin collapsing, clearance, integer implementation (for z-index, orphans and widows), border-style: hidden, min- and max- properties, cursor parsing, visibility, etc."

    All browsers have some quirky CSS2.1 implementation, and I’d say IE8 is NOT poorer than any other standards-compliant browser out there at CSS2.1

    And it surely doesn’t cost me much time as a normal web developer, I’ll be fully happy if only IE6 and IE7 disappear.

  77. Mitch 74 says:

    @wechrome: I disabled all Javascript and advanced (level 2/2.1) CSS on my websites at the start of the month for IE 6 and lower. Interestingly, and although I had extensively tested my websites under IE6 (and even IE 5), my efficiency and conversion ratios have _increased_ ever since. That does include IE 6 users.

    My current recommendation is thus:

    Develop for an "IE 8" feature level:

    – it’s not too hard having CSS that works cross-browser with that version

    – you don’t need TOO MANY IE7 hacks and workaround to make IE7 usable

    – its DOM support is still awful and, again, supporting IE 7 (and 6) isn’t too difficult

    Then, create a "handheld/limited" profile:

    – with limited CSS, which would fit a small screen better anyway,

    – with limited/disabled Javascript, which should always be considered possible: NoScript is VERY popular on Firefox, and anyway there are many ‘basic’ HTML 4.01 and CSS features that can replace a bunch of JS code and still remain quite user-friendly.

    Not that both parts are not necessarily codependent.

    I’ll cite, for example, on CSS alone:

    – using :hover

    – using display:none

    – using :before and :after with ‘content’

    – using overflow (and even overflow-x/y, which although not standard are pretty well supported)

    In HTML, you may:

    – use all lower case, and use the same term for id and name

    – use ‘title’ extensively

    – use ID’ed DIV’s that you then position with CSS (handhelds can’t deal with tables well, and when they do, they do so inconsistently)

    – use HTML tags such as sub, sup, pre, address, cite, abbr, fieldset etc. with their intended use. Interestingly, once you’re done with pushing ‘pure’ HTML use, you may notice that your page doesn’t look half bad, and is already quite easy to use.

    – do NOT rely upon HTML automatisms, such as list elements or paragraphs closing: always specify where they should end, and don’t play cute with block and inline elements: a paragraph should NOT contain a table (eventhough IE 7 and lower will gladly accept an inlined table), so close your paragraphs before you run into another block level element. If you want to position a table next to a paragraph, don’t forget that:

    * a table can have a CAPTION

    * positioning falls into the ‘style’ category: deal with it with CSS.

    And, last but not least, VALIDATE YOUR CODE! While browsers fly off the handle on erroneous markup, even IE 5/6 can behave in an almost predictable fashion if you feed them valid code.

  78. Matt says:

    Mitch: While your strategy seems reasonable, you shouldn’t believe the hype… NoScript is not "VERY popular". A single digit percentage of firefox users actually have it (and a smaller portion have it turned on correctly). Giorgio would have you believe otherwise and presents misleading stats. For instance, he counts every update as a "download" but he updates the thing nearly every other day, meaning the download count is hundreds or thousands of times higher than the user count.