Cross Browser Development: A Few CSS and JS Issues
Coding cross browser friendly JavaScript and CSS got you down? In a recent project, Ron, David, and I worked through some painful cross browser issues. Ron noted that he even banged his head against the wall over a couple of them :) Three of these issues come up frequently in my other projects full of CSS and JS development, so I wanted to share.
Variable Declaration in JS
In several cases, I noticed that excluding variable declaration (“var”) resulted in broken JavaScript-based functionality in IE only. I typically include variable declaration when I’m writing JavaScript. In our project, we were working with legacy code and conflicting variable names may have be introduced, resulting in broken functionality. Examples of before and after:
Bad | Better |
---|---|
var display_cart_popup = function() { popup_id = '#addNewCartbox'; left = (parseInt($(window).width()) - 772) / 2; ... }; |
var display_cart_popup = function() { var popup_id = '#addNewCartbox'; var left = (parseInt($(window).width()) - 772) / 2; ... }; |
... address_display = ''; |
... var address_display = ''; |
I researched this to gain more insight, but I didn’t find much except a reiteration that when you create variables without the “var” declaration, they become global variables which may have resulted in conflicts. However, all the “learning JavaScript” documentation I browsed through includes variable declaration and there’s no reason to leave it out for these lexically scoped variables.
Trailing Commas in JSON objects
According to JSON specifications, trailing commas are not permitted (e.g obj = { “1” : 2, }). From my experience, JSON objects with trailing commas might work in Firefox and WebKit browsers, but it dies silently in IE. Some recent examples:
Bad | Better |
---|---|
//JSON response from an ajax call { "response_message" : '= $response_message ?>', "subtotal" : = $subtotal ?>, "shipping_cost" : = $shipping ?>, "carttotal" : = $carttotal ?>, "taxes" : = $taxes ?> } |
//JSON response from an ajax call { "response_message" : '= $response_message ?>', "subtotal" : = $subtotal ?>, "shipping_cost" : = $shipping ?>, "taxes" : = $taxes ?>, "carttotal" : = $carttotal ?> } |
//Page load JSON object defined var fonts = { [loop list=`$Scratch->{fonts}`] '[loop-param name]' : { 'bold' : "[loop-param bold]", 'italic' : "[loop-param italic]" },[/loop] }; |
//Page load JSON object defined var fonts = { [loop list=`$Scratch->{fonts}`] '[loop-param name]' : { 'bold' : "[loop-param bold]", 'italic' : "[loop-param italic]" },[/loop] 'dummy' : {} }; |
Additional solutions to avoid the trailing comma include using join (Perl, Ruby) or implode (PHP), conditionally excluding the comma on the last element of the array, or using library methods to serialize data to JSON.
Floating Elements in IE
Often times, you’ll get a design like the one shown below. There will be a static width and repeating components to span the entire width. You may programmatically determine how many repeating elements will be displayed, but using CSS floating elements yields the cleanest code.
Example of a given design with repeating elements to span a static width.
You start working in Chrome or Firefox and apply the following CSS rules:
CSS rules for repeating floating elements.
When you think you’re finished, you load the page in IE and see the following. Bummer!
Floating elements wrap incorrectly in IE.
This is a pretty common scenario. In IE, if the combined widths of consecutive floating elements is greater than or equal to 100% of the available width, the latter floating element will jump down based on the IE float model. Instead of using floating elements, you might consider using tables or CSS position rules, but my preference is to use tables only for elements that need vertical align settings and to stay away from absolute positioning completely. And I try to stay away from absolute positioning in general.
The simplest and minimalist change I’ve found to work can be described in a few steps. Let’s say your floating elements are
<div id="products">
<div class="product">product 1</div>
<div class="product">product 2</div>
<div class="product" class="last">product 3</div>
<div class="product">product 4</div>
<div class="product">product 5</div>
<div class="product" class="last">product 6</div>
</div>
And let’s assume we have the following CSS:
<style>
div#products { width: 960px; }
div.product { float: left; width: 310px; margin-right: 15px; height: 100px; }
div.last { margin-right: 0px; }
</style>
Complete these steps:
- First, add another div to wrap around the #products div, with an id of “outer_products”
- Next, update the ‘div#products’ width to be greater than 960 pixels by several pixels.
- Next, add a style rule for ‘div#outer_products’ to have a width of “960px” and overflow equal to “hidden”.
Yielding:
<div id="outer_products">
<div id="products">
<div class="product">product 1</div>
<div class="product">product 2</div>
<div class="product" class="last">product 3</div>
<div class="product">product 4</div>
<div class="product">product 5</div>
<div class="product" class="last">product 6</div>
</div>
</div>
And:
<style>
div#outer_products { width: 960px; overflow: hidden; }
div#products { width: 980px; }
div.product { float: left; width: 310px; margin-right: 15px; height: 100px; }
div.last { margin-right: 0px; }
</style>
The solution is essentially creating a “display window” (outer_products), where overflow is hidden, but the contents are allowed to span a greater width in the inside
The white border outlines the outer_products “display window”.
Some other issues that I see less frequently include the double-margin IE6 bug, chaining CSS in IE, and using ‘#’ vs. ‘javascript:void(0);’.
Comments