mail us  |  mail this page

contact us
training  | 
tech stuff  | 

Tech Stuff - CSS Techniques, Experiments and Wheezes

During our quest for a CSS based (table-less) layout in mid-2003 we ran a number of experiments to clarify our understanding (bit of an exageration vague notion would be more precise) and to explore potential browser problems, many of which are outlined in our layout notes. This page provides and documents the experiments we ran and some techniques we developed and adopted or adapted along the way. Use view source to look at the HTML and CSS code.

Notes: We recently had cause to check some of these experiments during 2006 (many of the originals were done in 2003) and found a number of solutions were clearly dependent on historic browser bugs and other aberant behaviours. We have updated a number - if we have missed any drop us an email if you have the time, energy or inclination.

Contents

Note: Which DOCTYPE you are using may significantly affect the handling of various css attributes (i.e. quirks mode and all that brain-hurting stuff). In the pages below we use the following DOCTYPE declaration:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
  "http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd">

Note: This page now uses an HTML5 DOCTYPE - well, non-DOCTYPE really of <!DOCTYPE html>.

Table width=100% in a <div>

MSIE (5+ & 6+) can behave very badly when it hits a width="100% inside a <div>. It just forgets any margins and seems to assume the containing block is the screen i.e. the parent of the containing 'div'. Use 'view source' in your browser to see the minimal HTML and CSS in the example pages. The first set of examples all use position:relative (default) the solution for position:absolute is different.

This page has placed a table inside a div which is centered on the page using right and left hand margins. The inner table has no width attribute so all browsers display it correctly.

This page has a width=100% and works for all browsers including MSIE.

This page has a width=100% and a DOCTYPE which places the browser in quirks mode (we removed the DTD URI reference) and blows away our margins in MSIE only (Gecko and Opera 7.x display it correctly) which seems to use the screen dimensions as the containing block (and gives 100% of this width), accepts the right hand margin from the containing 'div' but ignores the left margin (go figure).

This page places the table with a width="100%" inside a second 'nested' div and fixes MSIE in both quirks and standards modes (and works for all other browsers). The 'dummy' div must have 'width:100%' and serves as wheeze to pass down the real margin constraints. It appears that the containing block (from which the constraints should be taken) is interpreted to be the 'parent' of the containing object (just our guess).

Position:Absolute

This page uses our solution above but adds position:absolute to the outer div the enclosed table still has a width="100%" inside the second 'nested' div and again blows away our margins in MSIE in both quirks and standards modes. Gecko displays it correctly in both modes. Opera truncates the table (loses the width=100%) in standards and quirks mode.

This page creates a containing div with the position:absolute directive, the inner div declares the margins the enclosed table still has a width="100%" without the second 'nested' div. MSIE and Gecko display correctly in standards mode, Gecko is OK in quirks mode but MSIE blows aways the margin. Opera 7.x truncates the table (loses the width=100%) in both modes.

Finally we placed a width:100% in the inner div (the containing div is unchanged). Wow. Blows away the width for MSIE and Gecko in Standards mode (Opera 7.x kinda OK). In quirks mode MSIE is perfect, Gecko blows the width and Opera 7.x truncates.

Trust it all makes sense to you!

Center a page with CSS

CSS has no block level centering features, for example, center a table. The centering solution depends on whether the 'thing' you want to center has fixed or variable width. Use 'view source' in your browser to see the minimal HTML and CSS in the examples below.

If you want variable width in the center it's simple just set the appropriate left and right margins on an enclosing div as in this page.

If you want a fixed width in the center it gets a bit trickier. Gecko and Opera 7.x can operate very happily with 'margin:auto;' and 'width:300px;' as in this page but MSIE chokes on it and aligns it on the left. It does not like 'auto' margins at all.

humble pie: When we wrote the above we thought it was correct. It was not. We had cause to look again about a year later and found that the DOCTYPE definition in the above page is incomplete - it was missing the url declaration and consequentially we should have said that MSIE in quirks mode does not handle it correctly. But if we add the url to the DOCTYPE it is OK for MSIE as well . So there you go.

The only way we have found to center a fixed width 'div' for all browsers is to absolutely position it in the center and then set the left margin to - (half the width) as in this page. Ugly but it works.

Finally Rob Church has pointed out that MSIE behaves well with 'margin:auto;'if you use any XHTML DOCTYPE as well e.g.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 
 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 
 OR 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 

The proof is here. Thanks Rob.

Conditionally generating a button with CSS

We wanted a technique to conditionally generate a button or marker on a page to show certain characteristics if they are present. You will see an example of these buttons on the right hand menu of this page.

The button idea has a long and illustrious history - they are modifications of Eric Meyer's CSS implementation of the Raging Platypus design who got the idea from Antipixel. So there. We conditionally generate them on a page which has been modified to use improved CSS techniques using a CSS Selector.

The first 4 definitions below just build the button. The button technique uses a 'span' tag to split the style characteristics of a single list element (damned clever wish we'd thought of that). The enclosing list element style is set to 'visibility:hidden' by default and the fifth CSS selector used to set 'visibility:visible' if this button is enclosed in a 'div' which is only present in our revised layout schema. The use of '#id' in the fifth selector allows us to expand the technique for other buttons and you could omit it if you have just one item. You can adapt the basic technique to reflect your conditions.

Note: The HTML construct uses 'ul' elements - it could use a table but there is less HTML mark-up in a list.

/* STYLE SHEET Fragment */
.b-b {list-style:none;
	margin:2px;
	font: 9pt Arial, sans-serif;
	padding:0 1em;
	}
li.b-b-l {visibility:hidden;
	margin:10px 0;
	}
.b-b-a {background:blue;
	color:white;
	text-decoration:none;
	border:1px solid black;
	padding:0 0.25em 0 0;
	}
a.b-b-a span {color:blue;
	background:white;
	padding:0 0.25em 0 0.33em;
	text-decoration:none;
	}
div.l-r #layout {visibility:visible;}

<!-- HTML Fragment -->
<div class="l-r">
<ul class="b-b">
<li class="b-b-l" id="layout">
<a class="b-b-a" href=""><span>CSS</span> Layout</a></li>
</ul>
</div>

Regular Border round adjacent items

If you want to display a regular border round items, for example, items in a list or a series of paragraphs then allocating say a 4 pixel border on each side will result in a thick line between items. Note: This particular example uses a series of paragraphs enclosed in a 'div'. Use 'view source' in your browser to see the minimal HTML and CSS in the example pages.

To fix the problem and provide a consistent border the trick is to leave one of the adjacent sides as a zero which works great but leaves a gap on the last side.

So finally we fill in the gap using the containing block (in this case the div) which closes the border for all browsers except Mozilla/Gecko and Opera which leaves a gap on the right of the bottom margin. This is because the calculation of the containing block width (the div.l-l) is computed as:

  margin-left + border-left + padding-left 
  + width (if defined)
  + padding-right + border-right + margin-right

(defined in CSS2 Box model section 8.1 and Visual formatting model details section 10.3.3 in more detail. Both Gecko and Opera do the right thing whereas MSIE essentially ignores this model - does its own thing and in this case gets the right effect.

To create a solution acceptable to all browsers you can use one of the following techniques:

  1. Create and apply a style to the last paragraph to let it close all the borders

  2. Since the problem is caused by calculation mismatches - do them manually by adding to the div width.

  3. Alternatively, since it's a width problem cauased by margins, padding and borders use alternative methods to create the padding/margin effects such as text-indent (or text-align) and height - then either use the same technique as above or use the containing div to bound the three sides and the paragraphs to handle the bottom line.

Which, if any, makes the most sense will depends on your circumstances.

Note We sometimes use:

 border:4px solid blue;
 border-width:4px 4px 0 4px;
/* rather than */
 border-width:4px 4px 0 4px;
 border-style:solid;
 border-color:blue;

The reason - the first is shorter and both give the same result (well if you ignore the bottom 4px which you probably want anyway) - however it's generally best to use the second method since it may be less confusing.

Production CSS Pop-out/pop down Menus

Look Ma .. no javascript. We've used pop-out, pop-down CSS menus on this site since mid 2003 for Gecko and Opera, from end 2003 with up to four level of nesting - we conditionally generate a Lite Javascript version for MSIE pre version 7.0.

Gecko, WebKit, Trident and Opera CSS Menus - Multi-level

These menus don't work for MSIE 5/6 - hey blame Microsoft not us!

Wish we could claim to have invented this stuff or found it out ourselves. Instead the inspiration (and some of the CSS) comes from a great article/demo from Eric Meyer. Though Eric disengeniously suggests the key to the pop effect is the 'ul li:hover' sequence that's actually the simple and obvious bit, it's a lot more complex than that - or maybe (more likely) we are just stupid.

Use 'view source' in your browser to see the minimal HTML and CSS in the example pages. This page shows our first simplified version which we used during testing and development. It has horizontal pop-out menus with three levels and works great in Opera 7+ and Gecko but does NOT work for MSIE since this browser does not support the child selector ('>') or the pseudo class 'hover' for anything but anchor tags.

This page has limitations in that the 'top' and 'left' attributes are always relative to the containing block (in this case the initial <ul class="p-l1">). Consequently when the third level menu is pop'd it writes using the 'top:0' measure from the initial 'ul' top edge. The menus end-up giving the appearance of going up and down. This is not the effect we want. We were pretty certain this was our layout error not a browser limitation. OK but how do we fix it?

The vertical menu works for Gecko (given the limitations noted above) but Opera chokes on it and will not allow us to get to the Third-2 menu item (if you get our drift). Again poor old MSIE does 'nuthin' at all.

Back to the drawing board we go.

Our second version contains a number of changes and conclusively proves that we have unwittingly gotten, and maintained, a relationship with our initial containing block (the <ul class="p-l1">) such that calculation of 'top' is relative to the top edge of this box. In order to display the expanding menu against the individual line item, say Horizontal-3, we have to force CSS to use the <li> 'top' property as the containing block.

Experiment 3 was an attempt to create a containing block that was too small and perhaps use this to break apart the relationships (shows you how smart we are). We had to explicitly add 'position:relative;' in the containing 'div' to get it to use a 'top:100%' for position (which was a clue if only we could have spotted it). An interesting side effect for which we have absolutely no explanation is that if we add a border to the 'div' the roll-over effect no longer works. Another clue?

Experiment 5 is here and was a simple attempt to try and get some visual clue as to what is going on. We kept our red border to the <div> (see above) and added a green one to the initial <ul> element. Interesting - because the roll-over effect works again. Go figure.

With the clear impression now that the solution has something to do with 'position:relative;' we built experiment 6 which forces a property of 'position:relative;' into every <li> element even if it's contained in a 'position:absolute;' block (which is not exactly intuitive behaviour) and Whazam!!

This experiment has the additional benefit that it works for both Opera 7.x and Gecko (do you need to ask about MSIE!).

The remaining question is: Do we have a browser quirk - in which case we cannot use this for production sites or should things happen this way - in which case we can use it for production sites? We had to read lots of W3C documents and armed with some knowledge - always a dangerous thing - we moved in a generally forward direction.

OK it's normal behaviour as defined in the CSS2 spec. This spec says (we paraphrase) that the 'position:relative;' attribute establishes a new containing block from which descendant elements can take their positioning. Further the initial or default position attribute is static not relative which to those of us brought up on the old DHTML positioning stuff is counter-intuitive. Seems that relative is kinda 'moveable' by using 'top', 'bottom' etc. as offsets from where it would normally be placed (an implicit target which is itself) but retains its original 'place-hole' (even if it has been moved), whereas absolute is positioned according to the same offsets but against a defined target (an explicit target - the containing block) and has no 'place-hole'. All pretty obvious really!

So the reason the experiment finally works is: each nested <ul> uses 'position:absolute' which creates no 'place-hole', it is then positioned against the current containing block (typically a <li>), each <li> element is given an explicit 'position:relative' attribute (which overrides its default 'static') and allows it to become a containing block. Presumably its 'place-hole' exists but is relative to its absolutely positioned <ul> and hence is floating in the 'ether' until made visible. Since each <li> is now a containing block this allows us to position (using 'top', 'left' etc.) further menu levels using it as a base. So there. Clear as mud!

Vertical CSS Menus

Well it ain't over yet. We have some top menu/banner stuff that was placed inside a table and survived our initial conversion to CSS layout due simply to reasons of laziness. We wanted to see what would happen whe we placed a CSS pop-up inside table.

Mmmmmmm! Very interesting.

The problem is that to force the menu items onto a single line inside the <divs> (used to create containing blocks) we used the 'display:inline' attribute which (as any fool - except us - knows) immediately invalidates the 'top' attribute and hence the pop-up effect does not work correctly. The positive part is that the HR does not move and hence the popups do not redraw the page. Nice try but no cigar.

To fix the alignment problems we replaced the 'display:inline' with a 'float:left'. The table/cell has no 'width' attribute. When the popup/hover changes the width of the cell the float directive seems to be stronger and redraws the table cell vertically and we get a real mess. The HR bar moves indicating that we will get a page re-draw. Allocating a width attribute of, say 50%, is one solution to this problem. But again we will get a page re-draw.

After some more experimentation we decided that life was too short to continue with this approach and so we decided to replace the banner table with a table-less structure. This was our first attempt. OK so it works for Gecko and Opera 7.45+ (versions of Opera prior to that quoted did not support the feature and .. need you even bother asking about MSIE).

Now we apply our 90% width constraint and some alignment. Again Gecko and Opera 7.45+ but not - what a surprise - MSIE.

We add our logo and some crude positioning (with a <br>!! - the production version uses 'padding' to control vertical spacing instead) and we have a solution for Gecko and Opera 7.45+.

To summarize: We appear to have a horizontal pop-out that works for Gecko and Opera 7+ and a vertical solution for Gecko and Opera 7.45+ only. But it will degrade in all other browsers to a non pop-out. Is this enough?

Since Gecko is still a pathetically small part of the market (no we don't know why either) there really is no way to justify the investment. But the real reasons we have done it are:

Are we going to use these techniques on our site? After all this hard work - darned right we are!

All Browsers CSS Pop-out/pop down Menus

In April 2006 we revisited pop-ups for some new developments and again felt that shudder of disgust that we still had Javascript for simple navigation functions. MSIE 7 (beta in April 2006 if you are using XP which we are not) promised clean CSS pop-ups but we were still stuck with MSIE 5/6 - so we went in search of a solution - and blow me, we found one. Its based on two principles - MS Conditional Comments which allows us to override standard definitions selectively within the target browser and a very clever insight in this article by Venimus for the codeproject. So we figured we could get rid of most of that residual Javascript. This is what we did.

The first series of experiments were to try and find the minimal CSS needed to get pop-ups to work in a MSIE environment - essentially trying to find the limitations in the MSIE CSS model by observation. This page starts from the experimental layout described in the article above and works for MSIE 5.5/6, MSIE 7, Opera (8.54) and Gecko (but with an annoying box below the menu item) using a DOCTYPE HTML 4.0 without a URL - we added a </a> tag to terminate the enclosing anchor tag sequence for the inner table. The only other item we added was an absolutely positioned div under the menu to allow us to test and interaction problems. MSIE completly ignores the size value of the font (defined in the .l-f style) but seems to handle everything else correctly.

Simply removing the enclosing table structure appears to have no effect on the layout.

Adding a paragraph and some modest renaming of class fields appears to have no effect on the layout.

MSIE - when display:block is applied to .c-table and .two classes a subsequent attempt to change the styles to display:none; has no effect and the pop-ups will work when the mouse is over the pop-up area (but only after the first pop-up) but applying the style to .first .c-table cancels this effect. Our guess would be that exactly similar effects are cancelled but effects applied to slightly different CSS definitions are triggered only at certain times.

A two level pop-up menu example - but still vulnerable to the mouse over pop-out area (but only if you exit the second-level pop-up area - if you remove the mouse via the first pop-out level the effect is cancelled - so we have are not triggering the same re-draw mechanisms as the first level). This minor change using a display:none div to trigger the pop-up process makes this visible. The surrounding box remains visible any mouse movement into the box will activate the pop-up.

This experiment was designed to see what menu bar layout limits exist. The main menu was placed in a table and did not work until we wrapped the whole structure in a div once again and we fooled around to get vertical bar separation in the menu line items. This page uses a DOCTYPE HTML 4.0 transitional and no URL - works for MSIE 6, Gecko (vertical only layout) and Opera (but leaves a bar at the bottom after the hover event). Annoying artifact in MSIE when hovering over a part of the first menu (same effect if horizontal or vertical). DOCTYPE HTML 4.0 and loose.dtd URL - Gecko (vertical only layout) is perfect, MSIE does not redraw the screen correctly and Opera pops but menu disappears on hover. with a transitional XHTML 1.0 DOCTYPE - works for MSIE 6, Gecko (vertical only layout) but not Opera (pops but menu disappears on hover). Again annoying artifact in MSIE when hovering over a part of the first menu (same effect if horizontal or vertical). The page does not validate as XHTML 1.0 because the table is nested in an a tag which is not allowed - so perhaps makes this test moot.

In all the above cases the area covered by the pop-up menu is constantly live which does not allow placing of any active links in this area - an unacceptable solution. However we have a solution which works for MSIE and Gecko with the same markup (vertical menus only) but not for Opera which is not really acceptable since it leaves this fine browser in the cold. Further the positioning of the menu items - horizontal or vertical is pretty minimal at best and would probably require some conditional CSS generation of code.

At this stage we had no idea where to go next.

Setting Zero Margins on a page with CSS

OK so you got one of those pages with <body topmargin="0" marginwidth="0" leftmargin="0" marginheight="0"> (don't we all) and either its just been bounced by the W3C Page Validator as not being valid serbo-croat HTML (or anything else known to mankind) OR you are just plain offended by using all those deprecated attributes in a single line.

Just set the 'body' 'margin' and 'padding' attrubutes in the style sheet to 0 (remember you don't need a unit with 0, after all 0 = 0 - right?).

// head stuff
<style type="text/css">
<!--
body {margin:0;padding:0;}
/* other style definitions */
-->
</style>

Goodness its even shorter than the invalid stuff - does life get better?

Aligning text on the left and right with CSS

So your layout designer wants the left hand text left aligned and some text on the same line to be right aligned. Mmmmm....

Add a class definition to the item you want on the RIGHT (we called it 'right' - original or what) and define it's HTML first. Class 'right' contains a float:right attribute. see an example use view->source to see the minimal css and html. This works perfectly for MSIE 6 but not Gecko which makes a real pig's ear of the whole thing.

<style type="text/css">
<!--
.right {
	float:right;
	}
/* dummy div is not needed - it just shows */
/* the limits of the 'block' */
.dummy {
	background:red;
	color:white;
	}
//-->
</style>
<!-- other stuff -->
<div class="dummy">
<h2 class="right">Right Title</h2>
<h2>Left Title</h2>
<p>just a line of normal text</p>
<p class="right">Text on right</p>
<p>Text on left</p>
</div>

To fix the problem for Gecko add a 'margin:0px;' statement in 'right' (experiment with the value) and all is well. see an example use view->source to see the minimal css and html. We think this is a Gecko bug but you can read the W3C description and make your own mind up.

<style type="text/css">
<!--
.right {
	float:right;
	margin:0px;
	}
/* dummy div is not needed - it just shows */
/* the limits of the 'block' */
.dummy {
	background:red;
	color:white;
	}
//-->
</style>
<!-- other stuff -->
<div class="dummy">
<h2 class="right">Right Title</h2>
<h2>Left Title</h2>
<p>just a line of normal text</p>
<p class="right">Text on right</p>
<p>Text on left</p>
</div>

Printer Friendly pages with CSS

We provide a printer friendly button on each screen that allows a user to view the central content only - no left or right hand menus and no advertising. Selecting the browser's print feature will print what you see. We use style sheets with a couple of embedded lines of Apache SSI to conditionally generate the right CSS definitions. We've seen articles about doing this with PHP or Javascript - just a lot easier for us to use SSIs. We now provide a print style sheet to enable the same effect from any page. In both cases the print output is the same it's just the screen view that changes.

Using these techniques is made trivial if the pages are organised into distinct divs the enclose the major sections. We did this as a happy by-product of moving to CSS 3 column liquid layouts many years ago.

Screen Printer Friendly View:

We use a top banner, three central columns and a footer. All are enclosed in <div>s. By simply changing the definition of the divs we can easily remove the left and right columns and make the central columns full width. To make it even simpler we send the same page content again - just inhibit (visibility:hidden) certain divs.

Note: We originally used the visibility:hidden; attribute to achieve this effect but the div's occupied space and Gecko decided that hidden did not apply to printing so we finally figured out that display:none; was much more effective.

This is the CSS and HTML for a three column layout.

<style type="text/css">
<!--
.left {position:absolute;top:60px;left:6px;width:110px;}
.center {margin:0 160px 0 125px;} /* in-line */
.right {position:absolute;top:60px;right;6px;width:150px;}
//-->
</style>
<!-- other stuff -->
<div class="center">
<!-- center column stuff -->
</div>
<div class="left">
<!-- left column stuff -->
</div>
<div class="right">
<!-- right column stuff -->
</div>

When we generate printer friendly pages we modify only the CSS as follows:

<style type="text/css">
<!--
.left {display:none;}
.center {margin:5px;} /* in-line */
.right {display:none;}
//-->
</style>
<!-- other stuff -->
<body>
<div class="center">
<!-- center column stuff -->
</div>
<div class="left">
<!-- left column stuff -->
</div>
<div class="right">
<!-- right column stuff -->
</div>
</body>

OK so it wastes a bit of bandwidth by sending down the left and right hand menus that will never be displayed but it took us 30 minutes to implement - site wide.

The 'printer friendly' feature (on the right menu just below the buttons) is simply an 'anchor' tag with a query string added as shown below.

<a href="url/of/this/page.html?pf=yes">printer friendly</a>

On the server we use an SSI conditional expression to generate the conditional CSS like this:

<style type="text/css">
<!--
<!--#if expr="${QUERY_STRING} = /pf=yes/"  --> /* SSI */
.left {display:none;}
.center {margin:5px;} /* in-line */
.right {display:none;}
<!--#else  -->
.left {position:absolute;top:60px;left:6px;width:110px;}
.center {margin:0 160px 0 125px;} /* in-line */
.right {position:absolute;top:60px;right;6px;width:150px;}
<!--#endif  -->
//-->
</style>

In practice our SSI is a little more complex because we also generate browser specific CSS but the principle is the same as above. If you want to undestand Apache SSI (Server Side Includes) you can read about it. And if you don't - well that's OK too.

Printer Style Sheet:

We now use a printer style sheet to achieve the same effect as shown above but which is effective from every page irrespective of the use of printer friendly feature. The printer style sheet is a separate style sheet witha media=printer value in the style sheet declaration and is shown below:

<style type="text/css" media="print">
<!--
/* ZYTRAX STYLE SHEET PRINT TEMPLATE */
.left {display:none;}
.right {display:none;}
.center {margin:30px 0 0 0;} /* inherits all other attributes */
-->
</style>

These definitions override the various attributes - not the entire style - defined in the normal (screen) stylesheet. If an attribute does not change it can be omitted, equally every attribute that is different must be defined in the media style sheet.

CSS - Paras - Divs & Spacing & Cascades

We don't use CSS every day so we forget stuff - frequently. We forgot this one recently. This page shows a simple list of items e.g. a menu all neatly enclosed in paragraphs. Use view->source in your browser to look at the minimal CSS and HTML in the sample pages.

So we want to tighten up the spacing between elements. Being lazy human being we thought - just slap a div with some margins and padding round the paragraphs and the CSS cascade will do the job. It does not.

We forgot the CSS Box model which says that while the div has box properties - so does each para and the para does not inherit. There are four possible solutions (well actually there are more than that but ...):

  1. Define a class and apply to each para

  2. Use a single para and br

  3. Apply a class directive to the p tag

  4. Be very lazy and use the anonymous box (one which is not enclosed in para tags and which consequentially does inherit from the div) and br between lines (for good measure we added a line-height attribute to the div to tighten up spacing still further.

So there you go - which one is most useful depends on your context, your willingness to type stuff and the color of your socks that day!

CSS - Notes on float and clear

We recently got caught with the undesired effects from a float in a div used in a CSS pop-up menu bar. Which lead to minor ruminations about when is the float effect valid and particularly how do you get rid of it.

Float in a div with position:absolute

Floats in an absolutely positioned div have no residual effect outside the div. The absolute position has taken the whole div contents out of the document flow so they cannot effect anything else in the page. Floats in these divs are harmless and terminate with the closing div.

Float in a div with position:relative

When the float is defined in a div with either no position (default is static) or position:relative you can have problems in terminating the float effect - the float effect hangs around forever until explicity canceled by a clear:none attribute. Since float is not inherited this can be confusing and counter-intuitive - but when you consider that float affects the following structures it becomes more sensible. Take the example below which illustrates the effect in action:

...
<style type="text/css">
.bigdiv {... position:relative; clear:both; ...}
.menubar {...}
.menuitem {... float:left; ...}
</style>
...
<!-- HTML fragment -->
<div class="bigdiv">
...
<div class="menubar">
...
<div class="menuitem">
...
</div>
<div class="menuitem>
...
</div>
</div>
<!-- any HTML here is affected by the float:left -->
<!-- even though it is contained in a div (bigdiv) with clear:both -->
</div>

The HTML below the end of the .menubar div is still subject to the efects of the float:left. To clear it you must explictly define clear:both in a new structure as shown below:

...
<style type="text/css">
.bigdiv {... position:relative; clear:both; ...}
.menubar {...}
.menuitem {... float:left; ...}
.clearfloat {... clear:both; ...}
</style>
...
<!-- HTML fragment -->
<div class="bigdiv">
...
<div class="menubar">
...
<div class="menuitem">
...
</div>
<div class="menuitem>
...
</div>
</div>
<div class="clearfloat">
<!-- any HTML here is not affected by the float:left -->
<!-- because the clearfloat div contains clear:both -->
</div>
</div>

CSS - Trivial Image zoom

We had need for a image zoom feature. The functionality required must use a single image (to save bandwidth) but be able to display it at multiple (well if you insist - two actually) levels of resolution, it must use CSS (not Javascript) and finally since this feature would be used on multiple pages with varying image sizes we wanted something that would not require explicit definition of an image size in either the CSS or the HTML. There are a number of solutions to this problem around the web including this one which is very complete and comprehensive. But they all looked a tad too complex for our simple needs - and minds. So we created this kludge. Warning: It does not validate as valid HTML 4.01 or even serbo-croat HTML so if that idea offends your sensibility - go for the one above which does - but it does work for Gecko, MSIE 6 and, with a trivial change, for Opera.

The functionality uses a single image which can be displayed at a particular resolution (thumbnail concept - using a percentage of < 100%) to keep the display area used down to a minimum but when moused over a larger image will pop-up without a screen redraw - again driven by the resolution percentage (=> %100). The demo pages use a table to enclose the picture and some text but this plays no part in the solution - it could be any suitable formatting structure.

The CSS works for MSIE by enclosing the image and a hidden div (which contains the expanded image) inside a dummy anchor tag which has the unfortunate side effect of making the W3C page validator extremely unhappy. This page works for MSIE and Gecko but not for Opera and fully satisfies our needs since it requires no image specific width attribute. It also shows some modest positioning with respect to the containing object (the div.container). Unfortunately Opera requires a width attribute to display images and defining an explicit width in the enclosing div.container will choke MSIE but defining a width in the enclosing table cell and giving the div.container a width:inherit cures the problem and works for MSIE, Gecko and Opera. Since the enclosing table cell can be set to any value capable of containing the biggest image the solution is reasonably generic and still meets our needs.

Note on images sizes: Compressing an image in the browser causes little degradation in quality (Opera is not so good at this as MSIE and Gecko) - but expanding the image past its 100% value depends on how much compression was applied when the image was created. There are two possible strategies:

  1. Apply no (or very little) compression to the image and it can be expanded to 130 - 150% with modest or no degradation in visual quality - depending on its content and use.
  2. Set the expansion at 100% and use jpg compression to reduce the size until visible degradation starts to occur - in general this technique will yield smaller image sizes.

If you want to add a caption to the zoomed image - as in this page - just add the caption text and formatting inside the invisible div.

CSS - Show/Hide Text

We tend to be a bit wordy. We assume that everyone likes to know all the gory details of why we do stuff. Some folks just want the skinny. No messin' around. So we finally got round to adding a show/hide feature which we will use, sparingly, for new pages.

Bad news. It is not possible to show/hide permanently via CSS alone you need a bit of javscript as well. But if it's acceptable to hover the mouse to expand you could do the whole thing with only CSS.

The example page (use your browser's 'view source' feature to look at the minimal CSS and JS) provides:

  1. Click the show info to display the hidden text. Click the hide info to remove the text.

  2. Two divs are used to allow removal of the show info (and associated text). To simplify the JS function we define the id attribute of the first div to be the same as the second with a trailing 'a' thus 'hide' is the id of the second div and 'hidea' is the name of the first. We could equally have used a second parameter to the function toggle.

  3. We use a single JS function toggle with a single calling parameter (the second div name) that simply tests the value of the display CSS attribute and toggles it between the values block (display) and none (hide). The first div is toggled to the opposite value. Note: The default value of display is '', which is 'block'(display) so no style directive is required for the first div. Using the id name as a call parameter simply means you can have any number of these hide/show sections within a page.

  4. The JS function supports only DOM1/2/3 - MSIE 5.5, 6, 7 and 8, Gecko (FF, etc. - all), Opera (6+), WebKit (Safari, Chrome, etc. - all) - and older MSIE versions by making a simple test for document.getElementByID. Anything else (is there anything else?) - tough.

  5. Neither div has a class name which means it inherits all its properties from the nested div so this solution can be used on any page which has this structure and will take on any nested characteristics, such as, font, size, color etc.. It does, however, mean that you need to use the style attribute in the div tag to apply essential properties.

  6. The example shows use of two style attributes (display and border) to show a method of identifying the expanded text if required. Simply remove border from the style attribute if this is not needed.



Problems, comments, suggestions, corrections (including broken links) or something to add? Please take the time from a busy life to 'mail us' (at top of screen), the webmaster (below) or info-support at zytrax. You will have a warm inner glow for the rest of the day.

Tech Stuff

RSS Feed Icon

If you are happy it's OK - but your browser is giving a less than optimal experience on our site. You could, at no charge, upgrade to a W3C standards compliant browser such as Firefox

Search

web zytrax.com

Share

Icons made by Icomoon from www.flaticon.com is licensed by CC 3.0 BY
share page via facebook tweet this page

Page

email us Send to a friend feature print this page Display full width page Decrease font size Increase font size

Resources

HTML Stuff

W3C HTML 4.01
HTML5 (WHATWG)
HTML4 vs HTML5
HTML5 Reference
W3C Page Validator
W3C DOCTYPE

CSS Stuff

W3C CSS2.1
W3C CSS2.2
Default Styles
CSS3 Selectors
CSS 3 Media Queries
CSS 3 Colors

DOM Stuff

W3C DOM
W3C DOM 3 Core
W3C 3 Events

Accessibility

usability.gov
W3C - WAI
Web Style Guide
WebAim.org

Useful Stuff

Peter-Paul Koch
A List Apart
Eric Meyer on CSS
glish.com

Our Stuff

Our DOM Pages
DOM Navigation
Liquid Layout
CSS Short Cuts
CSS overview
CSS One Page

Javascript Stuff

ECMA-262

Site

CSS Technology SPF Record Conformant Domain
Copyright © 1994 - 2017 ZyTrax, Inc.
All rights reserved. Legal and Privacy
site by zytrax
Hosted by super.net.sg
web-master at zytrax
Page modified: October 11 2015.