10 HTML-CSS Cross-browser best practices

Note1: This article is intended at medium-experience designers. The beginners might use it too, but it may sound a bit too technical to them, and the advanced ones might start yawning at already-known infos ;)

Note2: This article will NOT focus on solving various CSS problems (this kind of articles are to be found in the rest of the blog) – it will only provide you with a relatively small set of simple rules to keep you from getting int crossbrowser problems in the first place.

We all know the problems that come up when cutting a HTML/CSS layout and it turns out that it shows up completely different  in various browsers. We personally wouldn’t mind this so much if our clients weren’t so darn picky and exasperatingly minute ;) But we end-up HAVING to cut generously cross-browser layouts, that look precisely identical no matter what you’re viewing them into.

So here’s my best practices to achieve this goal. If you take these into account when cutting any layout into HTML/CSS, you’ll almost never need to verify it in all the browsers again (never = 99% of the cases, which is pretty darn good).

1. The right tools: develop in Firefox, with Firebug installed and ready to use. This will always help you figure out what goes wrong and lets you test various workarounds. I know this saves me TONS of developing time. For other browsers, you could use the Modi V2.0 – it’s much weaker but a life-saver sometimes.

2. Always plan ahead. Never start cutting a layout before having a clear idea of every thing you’re going to do with it. Pre-cut it, either mentally or on a piece of paper, go through each and every element (at least for the most impoprtant ones), immagine what things might go wrong with it and remember these for later when you’re going to actually do the job.

3. Never use horisontal margins (left-margin / right-margin) on left/right-floating DIVs. Why? Because almost every browser interprets those darn margins differently. So, instead of hacking and over-hacking, for each browser individually, apply this simple rule instead.

4. When using absolutely-positioned elements, ALWAYS define that element’s parent’s position too. Why? Because the positioning of an element is always relative to the positioning of that element’s first parent with a specified positioning. And some browsers consider that the first parent is the one to relate to, while others, when not finding a specifically-positioned parent, consider the BODY to be that parent, which trashes the whole thing. So, keep in mind this simple fourth rule and you’ll always be OK.

5. Always use the CLEARFIX when using floating or block elements inside another block, if you want that parent block to extend vertically as to include the floating elements into its space. HTML and CSS were designed in an era where floating/block elements were supposed to wrap text around them, so using the CLEARFIX will safely get you through this issue.

6. Always try to avoid the table-related display properties (like display: table / table-cell etc). These have outrageously dissimilar behaviours in all the browsers and will almost certainly throw you into a wild goose chase around the bushy stuff CSS is made of. If you really must, use tables instead, where really needed. It’s not a disgrace, it’s even better to use the best of both table/div worlds.

7. For PNGs, always use the simple PNG hack I use too. This way, IE6 will finally understand PNG transparency too, and it’s best to anticipate and fix than to forget and wake up with IE6 bugs.

8. Pay attention to borders! If possible, never release a layout before verifying how the borders affect the layout. Why? Because some browsers tend to place the borders outside the box, others place them inside. This may or may not add up to the total weight / height of the bordered elements, and needs constant checking.

9. Test! Don’t rely 100% in what I’m writing here: I’m sure there are other aspects too that can cause havok on your cross-browser job. Install the most important browsers and test your work every once in a while, in the process. I test against: IE6, IE8, FF, Chrome, Opera and Safari (on Windows).

10. Always learn and save. Learn from your cross-browser experiences, and save those in a specially built template. I know I do. For example, in time, I came acrsoss various cross-browser problems that needed very specific browser-specific solutions. My answer tho this: a special “hacks” section at the bottom of the CSS template I always use when starting a new HTML/CSS cut. You can have it too, it’s “free-for-all-uses” (well, I didn’t actually invent those things, I just went ahead and compiled them neatly):

/* IE 6 and below hacks		*/
*html a { }

/* IE 7 only hacks		*/
*:first-child+html a { }
/* Opera 9 and below hacks	*/
html:first-child a { }
/* Safari and Opera hacks	*/
@media screen and (-webkit-min-device-pixel-ratio:0) {
a {}
}
/* HR Styling hacks		*/
/* IE				*/
hr { height: 1px; color: #d5d8d8; border: none; }
/* Gecko-based browsers		*/
html>body hr { height: 1px; background-color: #d5d8d8; border: none; }
/* Opera & Gecko-based browsers	*/
html>body hr { height: 1px; background-color: #d5d8d8; border: 0px solid #d5d8d8; }
/* clearfix			*/
.clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; }
.clearfix { display: inline-block; }
/* Hide from IE Mac \*/
.clearfix { display: block; }
* html .clearfix { height: 1%; }
/* End hide from IE Mac */

This way, I always have my permanent hacks (see CLEARFIX) included, and always have my temporary, browser-specific hacks at hand. For instance, if I want a CSS class – let’s say  .my_class – to behave specifically in a browser, I simply use the already prepared hack by duplicating the line and replacing the dummy a selector whit the class that I need. Something like this:

/* IE 6 and below hacks		*/
*html .my_class { color: #fff; }

That’s it for now… Read, learn, apply, and please let me know if you found this useful or if you have other best-practice ideas too in this matter.

Later bonus:

You can always install my simple Screen Ruler Favelet, in any browser, to check the sizes and dimensions of everything you design, by right-clicking here, choosing to save the link in the Bookmarks/Favourites and then calling it anytime from the Bookmarks/Favourites of your browser

PNG transparency in IE5+ and FF

If you ever had to use GIFs and you know just how jaggedy that transparency around the edges is, the PNG format, with it’s smooth transparency levels, is purely God-send. it’s just that IE (5,6,7) is, as usual, so stupid, that it doesn’t know what to do with the transparent areas and simply puts them over an abnoxious opaque gray rectangle. If you really must have PNG transparency into IE, you must use a dedicated filter (yet another M$ abomination), which filter in turn is able to display a transparent PNG as a background image, like so:

filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true, sizingMethod=scale, src=img/png-file.png);

The most commonly used solution for the geek ones os to implement a javascript programmed to parse the whole shazan, to look for PNG references and, with a global replace, to turn those into filter areas. Since this is a javascript-dependent solution, and since it comes with alterations on the structure of the document, I’ll just drop it right here and move along to the really intersting part of the problem, which is the simpler CSS solution.

Why CSS? Well, simply because most ofthen than not, you need to use PNGs within an external CSS, and javascript stops there.

If you didn’t get a chance to read the !important; article, I strongly recommend you do so before moving along with this article.

Normally, in CSS, we set a background image like this:


.style {
background-image: url(
img/png-file.png);
}

, which works in any sane browser, but not in IE.
In IE, as I was saying, you MUST do it like this:


.style {
filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true, sizingMethod=scale, src=img/png-file.png);
}

As you can see, we have two different properties trying to accomplish the same thing. If you already read the above-recommended article, you’ll understand how the solution to this problem is to apply a double !important; , like this:

.style {

background-image: url(img/png-file.png) !important;

background-image: none;

filter: none !important;

filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true, sizingMethod=scale, src=img/png-file.png);

}

This way, FF will “see” one valid background and zero filters, while IE will “see” zero background and one filter. Problem solved. That’s it for today…

ABSOLUTE-positioned elements in RELATIVE context

Sometimes, as in the case of the graphically rich yet still editable buttons, you may need to use elements positioned ABSOLUTE in a context positioned RELATIVE.
We’re talking about the “position” CSS property, that can take one of 4 possible values: absolute / relative / fixed / static. I’ll leave aside fixed and static for now, and I’ll focus instead on those that interest us here: relative si absolute.

tutorial-2.gifIn this image I’m using as an example, the blue border represents the parent element (the context), the red border is an element positioned absolute, and the green border represents an element positioned relative. The red and green elements are included, code-wise, in the blue one, obiously.

Relative – using the position: relative; CSS property, we instruct the browser to position the element relative to its context, in a fluid mode. In other words, we force the relative element to depend, position-wise, on it’s parent, but also on the in-line flow of the other elements present in the same context. Put bluntly, we force the element to behave like a letter in a block of text.
Absolute - using the position: absolute; CSS property, we instruct the browser to position the element relative to its context, but independent of the in-line flow of the other elements in the context. In other words, we force the element to maintain fixed position coordinates, expressed in pixels or directions.

At least in theory. Continue reading ‘ABSOLUTE-positioned elements in RELATIVE context’

!important;

If you didn’t know it yet, there’s a little CSS “hack” that, properly used, not only passes all classic validation systems, but is also very useful. We’re talking about !important;.

Basic usage: instead of width: 300px; you can write width: 300px !important;. But, more important, what does it do? Let’s see…

The basic function of !important; is to priorotize/set an ierarchy among the CSS properties attached to a page (be those inline or linked in external css files). In this respect, it can be used for 2 main purposes: Continue reading ‘!important;’

Horisontally centered DIVs: look out for MARGINs!

I googled this shit till I saw green… Why? Because I wanted to get a simple thing: a DIV horisontally centered in the page. IE, simple and retarded as it is, worked. FF instead, with it’s purist pretentious flavour, refused. That is, until I found out why.

Saner browsers (FF included) don’t take things “for granted”. They don’t work user-friendly, but mathematically. To position an element in relative terms, the browser needs to know exactly what are the parameters needed for the calculation of that particular relative position. Since, in this case, we’re talking horisontal positioning, the browser needs to know the div’s horisontal margins (left and right). In other words, if I want a DIV to be horisontally centered, I MUST tell it to have:

margin-left: auto;
margin-right: auto;

Without these simple settings, FF would stubbornly position any non-floating div to the left margin of it’s holder/parent, irrespective of that holder/parent’s text-align.

All said and done, the problem is solved. Too easy? Doesn’t matter, what matters is that it helps you.

DIV vertically centered in the page – no tables

Back in the day, when TABLES ruled the world, getting a layout compleely centered in the page was relatively easy: you’d just insert a one-cell table, align that table to the center both horisontally and vertically, and then you’d insert yet anothr table in that cell. That was it, plain and simple. But this would never work in NS, for the simple reason that NS would only observe the first table’s height – the rest of the tables’ heights being totally disregarded. Well, that was back in the day, when not only did people know what NS was (Netscape, for younger kids), but NS was the buzz-word of the day and everybody used it. Not anymore.

But the problem stays. Why? Because verical-aligning is only specific to certain HTML elements, and DIV isn’t one of them. So what then?

Well… it depends. You have not one, but two solutions, depending wheather you want your DIV to have a fixed height, or you want it to have a height relative to the height of the page. In either case, the basic principle is that your DIV must be placed into a context clearly defined position-wise, be it relative or absolute. Let’s take them one at a time…

 


1. Vertically centered DIV with the height relative to the height of the page.

Simple :) You set the din in the CSS, with the following parameters:

position: absolute; height: x%; top: ((100-x)/2)%;

tutorial-3.gif

Well, what I just wrote is an EXAMPLE, not to be taken literally, but to be interpreted. Don’t just copy-paste, cuz it won’t work. See it “translated” into usable code, in this example:

position: absolute; height: 40%; top: 30%;

If you have any questions, please leave a comment and we’ll sort them out

Continue reading ‘DIV vertically centered in the page – no tables’

CLEARFIX – problem and solution for FF and IE (incluing IE7)

When working with DIV-s (as I’ve been doing, for a while now), if you want a layout going down as long as its contend goes, you’re forced to work with FLOAT-s. That is, with DIV-s that are positioned RELATIVE and that have a float:left or a float:right set up on them.

The Problem
The problem is that the FLOAT’s visual rendering model is an archaic one, dating back when a float was limited to an <IMG>’s align: left / align: right, which allowed the text to flow around an image (or an image to “text-wrap”). Back in the day, a float was limited, conceptually, to < IMG > si < P >. What resulted from the old model? Something like this:

tutorial-5.gif

If you look closer, you’ll see that the image included in the first < P > (marked with magenta in the image) has an align=”left” (the functional equivalent of float: left; in CSS), which makes the < P >-s (including the ones to follow) to seamlessly flow around the image. All nice an dandy.

But what do you do when you want that image/float to “force” the height of it’s containing holder? What do you do if you want that < P > -ul containing the image to stretch down in a way to include ALL the image? That was easy peasy with tables, but DIVs make it much harder. Continue reading ‘CLEARFIX – problem and solution for FF and IE (incluing IE7)’

1px table border

Here’s an older, html trick, from the days when CSS was just a dream…

If you ever tried to get an 1px; border on a table, in HTML, you probably wrote this: < table border = ” 1 ” bordercolor = ” #000000 ” > etc. But see it in a browser and it’ll show 2px borders instead. WHY? Simple, if you come to think about it: because, when defining the 1px border, it applies to both the table and it’s cells (by means of inheritance), and the 2 borders adding up always result in disurbing, thick, 2px borders. To better understand how this happens, suffice it to give the table acellspacing=”5″ – only then will you see how, in fact, the border was 1px thick… The 2 cases look like this:

tutorial-7.gif

Still, what to do, if CSS isn’t at hand and you still want that fine 1px border? Use this little trick:

< table cellspacing = ” 1 ” bgcolor = ” #000000 ” > … and then give all the cells a white background-color. This way, with no table-border but with an 1px spacing, the spacing WILL BECOME the 1px border you wanted in the first place.

:hover

SIMPLY PUT: menu with submenus, CSS-only (no JS)

Any modern browser (implicitely excluding all versions of IE), if is playing by the CSS book, has support for the dynamic pseudo-class:hover” on ALL tags, not just on the lonely sad pathetic < a >.

Note: As you may already know, in CSS there’s a series of dynamic pseudo-classes (:hover, :active si :focus) that traditionally get associated with “a” in order to create different styles for the 3 possible different states of a link, as in a:hover, for instance.

Modern browsers, as I was saying, having implemented the support for this, allow for the association of the pseudo-classes with any HTML tag. In other words, you could very well define something like:

td       {background-color: #cccccc;}
td:hover {background-color: #336699;}

which would result in a background-color change on those td-s, on roll-over, without any need whatsoever to use HTML-bloating javascript code.

Continue reading ‘:hover’

Border around empty table cells

It happens often, when working with tables, to “forget” empty cells, i.e. cells without any content at all within, not with even as much as a shy & nbsp ;. That makes them look awkward in the browser (awkward = borderless) and,most of all, to look like coding errors, which coulod become unpleasant. For those lacking the patience to fiddle again the whole html code, there’s a solution: to define the following property in the CSS code:

{ empty-cells: show }

This will force all the empty cells to SHOW the border, even if empty. (the other possible values for this property are: hide and inherit)