Cross-Browser Compatibility
Myth or Reality? There's a long tradition to be overcome Sniffers to look for browser and OS combinations Separate code forks for different browsers Special HTML "tricks" to overcome browser defaults and bugs Proprietary DOM and HTML So can cross-browser compatilibity be real?
The Reality Yes! Cross-browser compatibility lies within your reach! First, you must do as Yoda says: "Unlearn what you have learned" Second, adjust your thinking for a new reality Third, start coding! Let's look at some common pitfalls and things that must be unlearned
Shed the Deadweight Things to give up: Invalid HTML LAYERit's dead and it's time to move on Proprietary DOMs document.layers died with LAYER itself document.all is still alive, but it's also completely proprietary Code forking Most forking is based around incompatible proprietary DOMs, so give them up and forking is unnecessary
Shiny New Toys! Try playing with these: Valid HTML Purify your structure and compatibility will follow W3C DOM Both IE5.x+ and NS6 support the W3C DOM, so code written once can run in both with NO FORKING! How can this process be any easier? Let's find out!
Validating Your HTML The fastest way to improve your pages Any page that triggers an error is invalid and the problem needs to be fixed If you can get a page to validate with no errors or warnings, you're golden The results will be different depending on what DOCTYPE you use There's a CSS validator too Valid CSS is as important to page layout as valid HTML
DOCTYPE Issues Do NOT lie about your DOCTYPE! If you have HTML 4.0 Transitional markup, then say so; don't claim XHTML 1.1 Strict! The DOCTYPE you use will trigger one of two layout models in recent browsers Old, missing, or transitional DOCTYPEs will trigger "legacy" layout mode XML, XHTML, and strict DOCTYPEs will trigger "standards" layout mode
Legacy vs. Standards What's the difference? Plentytoo much to list here, in fact! Some highlights: 'height' and 'width' do not apply to inline elements 'width' means the content's width, not the aggregate of content + padding + border 'class' and 'id' values are case-sensitive units are required on length measures 'body' and 'html' can be styled separately
Common Errors We see a lot of recurring problems… Generally poor structure: TD elements outside of TRs Unclosed TABLE elements SPANs wrapped around DIVs Badly-nested inline elements FORMs spread across multiple cells, or wrapped around a few rows or cells of a table Class and ID names treeated as though they're case-insensitive
An Example of Bad FORM Have you ever done this? … That construct is invalid and can cause functionality and layout problems Similarly, putting the in one cell and in a different cell is a bad idea
Even Worse Markup Here's a popular one: … Yikes! Wrapping an inline element around a block- level element is no good The beginning of a block-level element implicitly terminates any unclosed elements, so the 'span' ends right before the 'div' begins Convert the 'span' to a 'div', adjust your styles and scripts as necessary, and be happy
Enjoy the Free DOM Both IE5+ and NS6 follow the W3C DOM You can manipulate style, structure, even content in a truly cross-browser fashion Any other standards-compliant browser will be able to run the same scripts and get the same results
The Proof Is In The Showing A working example: The show/hide functionality is all W3C DOM- based and does no browser detection at all Confession: there's an OS detect to set the proper graphic effect for the icons
Picking a Piece of HTML There are two basic choices document.getElementById('idname') Lets you manipulate whatever element in the document has that unique 'id' value document.getElementsByTagName('tagname') Lets you manipulate all elements of a given type There isn't a way to select elements by class name, so we'll just have to build one ourselves
getElementsByClassName The source: function getElementsWithClassName(elementName,className) { var allElements = document.getElementsByTagName(elementName); var elemColl = new Array(); for (i = 0; i < allElements.length; i++) { if (allElements[i].className == className) { elemColl[elemColl.length] = allElements[i]; } } return elemColl; } Use notes: To get all elements with a given class call getElementsWithClassName('*','className'); Doesn't work with non-standard browsers (including IE4 and NN4.x)
Forked Source The source: function getElementsWithClassName(elementName,className) { var allElements; = document.getElementsByTagName(elementName); var elemColl = new Array(); if (document.getElementsByTagName) allElements= document.getElementsByTagName(elementName); else if (document.all) { // -=-=- IE4 code fork -=-=- if (elementName=='*') allElements= document.all; else allElements= document.all.tags(elementName); } for (i = 0; i < allElements.length; i++) { if (allElements[i].className == className) { elemColl[elemColl.length] = allElements[i]; } } return elemColl; }
21st Century Forking The past: Forking the script for every browser you want to support Changing the behavior means rescripting in every tine The present: One script, many browsers Changing the behavior is a one-time thing Caveat: support for older browsers still requires forking Of course, you probably already have that code available
If You Must Detect… …do it properly! Detecting on the browser name (navigator.appName) is NOT enough! Both Netscape 4.x and Netscape 6.x will return "Netscape" There needs to be some parsing of the user agent string to see who created the browser and what version it is There are some good practical sniffers on mozilla.org
In Summary Simple steps for simpler authoring Transition from away from proprietary DOMs and toward the W3C DOM The only code forks you should need are for old browsers that aren't up to standard Validate your markup and CSS, and make sure your DOCTYPE is correct Remember that the DOCTYPE affects which layout mode modern browsers will use