Forum Moderators: not2easy

Message Too Old, No Replies

Trying to convert specific table layout to CSS

         

madmartian

1:48 am on Sep 25, 2008 (gmt 0)

10+ Year Member



I am trying to convert a specific table layout that works in IE but not Firefox. I am hoping by converting the layout to CSS it will work in both.

Div Elements:

Top Nav Bar (entire width of browser window - always at top of window)
Center row (see below)
Bottom copyright bar (entire width of browser window - always at bottom of window)

The center row contains more elements, as follows:

Left column, fixed width, containing 3 rows:
1. top-left nav box
2. product list (scrolling - this section expands with browser window height)
3. bottom-left info box

Right column, remaining width of browser window, containing an iframe (where a picture loads when a product is clicked on)

That's it. Not terribly complex, but I don't know enough to do it.

swa66

9:17 am on Sep 25, 2008 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



If you already have trouble getting things to work cross-browser using tables, you're unfortunately in for a surprise. IE's CSS support is bad. All of us put a fight up with IE's bugs and "features".

Still it's commendable to step away from tables abused for layout.

But...

If you describe your page as a table (columns, rows, ...) you might not be ready to go for a "go with the flow" approach that works best in CSS.

Still it can be done.

E.g. start with the following:


<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>Untitled Document</title>
<style type="text/css">
* {
margin:0;
padding:0;
}
</style>
</head>
<body>
<div id="wrap">
<div id="nav">menu goes here</div>
<div id="copyright">Copyright goes here</div>
<div id="nav2">something</div>
<div id="info">information</div>
<div id="picture">images goed here</div>
<div id="products">
<ul>
<li>products go here</li>
<li>products go here</li>
<li>products go here</li>
<li>products go here</li>
</ul>
</div>
</div>
</body>
</html>

Not much to look at yet, but I've made your boxes that we'll throw on the page. We could have nested them in columns and/or rows but there's little need for that, and in fact in the long run it makes sense not to have the position on the page related to the position in the html.
Also overusing divs is just as evil as tables are.

We pull out our favorite standards compliant browser (i.e. anything but IE) [please don't look at it with IE while making it as it'll mess with your head]

So now it's decision time:
Let's go for a fixed width design that's centered on the page 770px should fit on most screens today:


#wrap {
width:770px;
margin:0 auto;
}

Should do that trick.

Auto margins left and right center the div, it originally had the width of the screen, so we reset that to our desired width.

All the divs in it sit there just for now, but they all are the 770px wide (for now) and they all align with the wrap one.
(add colors or backgrounds to see how large they are)

So how do we put these other boxes where we want them ?


#copyright {
position: absolute;
height: 20px;
width: 770px;
bottom: 0;
background-color: red;
}

Pushes that div out of the flow (see the others taking up the space it used to have?) and puts it at the bottom of the page. The width is needed if we want to position things inside the div later on (such as usign "text-align:center;" to center the text in there as absolutely positioned divs loose the width of their parent and collapse (leave off the width statement to see it happen)

I didn't change the left/right positioning cause it was already in the right spot (and cause I'd have no idea really where that centered div would have pushed me off to.

So let's do the same for the top one:


#nav {
position: absolute;
height: 50px;
width: 770px;
top: 0;
background-color: red;
}

Now that obscures some of the rest of them, it doesn't push them aside at all. That's what absolutely positioned elements do.

Since we're on a roll, lets add a few more such fixed sized boxes:


#nav2 {
position: absolute;
height: 100px;
width: 200px;
top: 50px;
background-color: blue;
}
#info {
position:absolute;
height: 200px;
width: 200px;
bottom: 20px;
background-color: blue;
}

The next one is a bit more tricky, it needs to scroll.


#products {
position: absolute;
top: 150px;
bottom: 220px;
background-color: green;
width: 200px;
overflow-y: scroll; /* this is actually CSS3 */
}

The overflow property dictates what happens when there's more content than the box has place. I'm using a fairly well supported piece of CSS3 (too early, but it yields what I seek in browsers such as Firefox, safari, and opera (I tested it at this point to make sure i didn't break it for them)
The CSS validator will complain about me already using CSS3, but I can live with that.

I didn't tell the browser how tall the box, is (cause I've no idea how tall it is), but I did tell it what I know: top and bottom position.

On to the picture.

This one is harder. If you remember I don't know where the left/right position is. And on top of that, the divs collapse their width, so I need a way to push them away from the left instead of being able to tell it to keep it's right side where it was originally.

Fortunately abo#*$!ely positioned elements don't let their margins collapse so I can push off of the left side:


#picture {
position: absolute;
width: 570px;
margin-left:200px;
top: 50px;
bottom:20px;
background-color: orange;
}

Now I've not yet looked at this little monster in any version of IE ...

But this is it for now:


<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>Untitled Document</title>
<style type="text/css">
* {
margin:0;
padding:0;
}
#wrap {
width:770px;
margin:0 auto;
}
#nav {
position: absolute;
height: 50px;
width: 770px;
top: 0;
background-color: red;
}
#copyright {
position: absolute;
height: 20px;
width: 770px;
bottom: 0;
background-color: red;
}
#nav2 {
position: absolute;
height: 100px;
width: 200px;
top: 50px;
background-color: blue;
}
#info {
position:absolute;
height: 200px;
width: 200px;
bottom: 20px;
background-color: blue;
}
#products {
position: absolute;
top: 150px;
bottom: 220px;
background-color: green;
width: 200px;
overflow-y: scroll; /* this is actually CSS3 */
}
#picture {
position: absolute;
width: 570px;
margin-left:200px;
top: 50px;
bottom:20px;
background-color: orange;
}
</style>
</head>
<body>
<div id="wrap">
<div id="nav">menu goes here</div>
<div id="copyright">Copyright goes here</div>
<div id="nav2">something</div>
<div id="info">information</div>
<div id="picture">images goed here</div>
<div id="products">
<ul>
<li>products go here</li>
<li>products go here</li>
<li>products go here</li>
<li>products go here</li>
</ul>
</div>
</div>
</body>
</html>

I now check it all works properly in firefox, safari.

After that I'll test it in IE6 and IE7 and use conditional comments to fix issues (I expect a few, and I'm not sure I'll be able to fix them) ; but I've gotta run now ... so It'll be for another post.

swa66

4:48 pm on Sep 25, 2008 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



On to testing in IE7. Does surprisingly well.

Oh-oh, this fails badly in IE6.

  • The horizontal centering is gone (that's an easy one).
  • The absolutely positioned blocks stretched by giving them top and bottom position don't stretch.
  • The CSS3 overflow-y seems to trigger a vertical scrollbar, but no scrolling since the block keeps its collapsed height.

I don't do much absolute positioning in real life so there might be easy IE6 solutions to this (or not)

The easiest part is the centering of the #wrap, but I'll warn you: I'm taking it out again a bit further.

A conditional comment like this will fix it:

 
<!--[if IE 6]>
<style type="text/css">
body {
text-align:center;
}
#wrap {
text-align:left;
}
<![endif]-->

Now let's focus on the blocks that don't stretch, it might well be related to IE6 not understanding bottom, so let's make sure it's got the needed assets by adding the IE7.js script:


<!--[if IE 6]>
<script src="http://ie7-js.googlecode.com/svn/version/2.0(beta3)/IE8.js"
type="text/javascript"></script>
<![endif]-->

Unfortunately this seems to undo our prior fix for the centering, and it gets much worse if we rip out the fix itself (it seems the right edge now wants the middle of the screen).
After some fiddling and resizing it seems shifting the body with its entire width to the right does the trick:

body {
padding-left: 770px;
}

Note that I only combat symptoms, I don't seek reasons, better code or any like it. As proven by different rendering, engines my CSS is reasonable, so I'm just working around bugs in IE, and all other browsers won't parse the code (to them it's a comment).

Now we've another problem that the bottom scrollbar appears and then disappers but leaves our #copyright up to high on the screen. Don't you just *love* IE ?

I tried a few things but it just didn't want do drop down, so I tried to make the scrollbar stay there at all times:


body {
overflow-x: scroll;
}

Now there's still one more thing wrong: the scrollbar on #products sticks out to the right, after a few experiments to find the right width, it seems making #products only 183px wide solves that somewhat.

Putting it all together:


<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>Untitled Document</title>
<style type="text/css">
* {
margin:0;
padding:0;
}
#wrap {
width:770px;
margin:0 auto;
}
#nav {
position: absolute;
height: 50px;
width: 770px;
top: 0;
background-color: red;
}
#copyright {
position: absolute;
height: 20px;
width: 770px;
bottom: 0;
background-color: red;
}
#nav2 {
position: absolute;
height: 100px;
width: 200px;
top: 50px;
background-color: blue;
}
#info {
position:absolute;
height: 200px;
width: 200px;
bottom: 20px;
background-color: blue;
}
#products {
position: absolute;
top: 150px;
bottom: 220px;
background-color: green;
width: 200px;
overflow-y: scroll; /* this is actually CSS3 */
}
#picture {
position: absolute;
width: 570px;
margin-left:200px;
top: 50px;
bottom:20px;
background-color: orange;
}
</style>
<!--[if IE 6]>
<style type="text/css">
body {
padding-left: 770px;
overflow-x: scroll;
}
#products {
width:183px;
}
</style>
<script src="http://ie7-js.googlecode.com/svn/version/2.0(beta3)/IE8.js"
type="text/javascript"></script>
<![endif]-->
</head>
<body>
<div id="wrap">
<div id="nav">menu goes here</div>
<div id="copyright">Copyright goes here</div>
<div id="nav2">something</div>
<div id="info">information</div>
<div id="picture">image goes here</div>
<div id="products">
<ul>
<li>products go here</li>
<li>products go here</li>
<li>products go here</li>
<li>products go here</li>
</ul>
</div>
</div>
</body>
</html>

madmartian

8:38 pm on Sep 25, 2008 (gmt 0)

10+ Year Member



You rock! This works much better than my own experiments. I tested it on the latest ie/ff/safari and it looks the same on all three! woohoo! I have to put an old machine together to test the older versions. A couple changes I need to make. I tried making them but messeed things up, of course. Still learning how CSS works for layout.

The "info" and "nav2" section heights should fit the text in them rather than being fixed on a number. The text in these sections will vary depending on what is clicked on in nav2 (which contains categories).

The other thing is I'd like the width to stretch to the width of the browser window, rather than being fixed. "nav2", "info", and "products" are fixed width, but "nav", "picture", and "copyright" should get increasingly wide as the browser window is stretched.

Thanks much!

swa66

11:04 am on Sep 26, 2008 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Pure CSS has no way of letting one block change it's position or size depending on the dynamic size of another block. You can either stick to more normal layout (where the :flow" does part of this for you, but then you need to loose the position:absolute parts, which are a bit essential in your layout.

But since you're using javascript anyway to change the content of those blocks, javascript could also be used to maintain the layout dynamically. (I'm not a big fan of javascript, but it's possible)

Making the width variable: the 200px width could easily be replaced with a %width, (you need to loose the width on the wrapper first), and you need to take care with the width of the pictures to make sure it adds back up to 100%. Also you can loose the margin there now as you'll know where the right side needs to be.

Changing this will invalidate some of the IE fixes, so they should be watched very carefully and tackled anew.

madmartian

7:58 pm on Sep 26, 2008 (gmt 0)

10+ Year Member



Ok, I'll give up on dynamic height for "Nav2" and "info". I'll just have to adjust accordingly for each page.

I'm having a heck of a time getting the photo box to work as intended. Apparently height=100% does not work for iframes in IE when used in CSS (but works fine when used in a table). The result is I get what I want in FF and Safari, but not IE. I found a couple javascript solutions for dynamically adjusting the iframe height, but they didn't work.

<div id="picture">

<iframe src="products/prod_angle.htm" width=100% height=100% frameborder="0" scrolling="auto" name="show"></iframe>

</div>

madmartian

5:41 am on Sep 27, 2008 (gmt 0)

10+ Year Member



Argh! This is so frustrating. I got it working on IE6 just fine! Only IE7 is failing. :(