Forum Moderators: not2easy

Message Too Old, No Replies

Ugh. switching from tables to div tags and css

         

eulogy

5:05 am on Jul 11, 2009 (gmt 0)

10+ Year Member



I'm about at my wit's end. I've been trying for about 6 hours now to layout my webpage with DIV tags instead of using tables.

Basically what I'm going for is this; <>

The only thing I could do was use "left" and "top" to kind of give each div tag a coordinate, but that's definitely not what I want. I even got a div tag centered (using margins), but wanted it to be a container for the two rounded-corner images (also div tags), but I had no idea how to get those to go to opposite sides of the container.

I've known html for quite a while, but tables are giving me crap with this layout, being hard to set heights and widths and have them stick. Changing the width of one cell screws up another... it sucks.

If anyone can even point me in the right direction I'd greatly appreciate it. I've been reading all day, and while I understand most of it, I don't understand why it's not working for me.

[edited by: SuzyUK at 9:07 am (utc) on July 11, 2009]
[edit reason] no URIs per Charter [WebmasterWorld.com] [/edit]

marcel

8:00 am on Jul 11, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Welcome to WebmasterWorld [webmasterworld.com] eulogy!

In your case I would probably go with the following:

- A single containing div, centered and set to the correct width.

- For the Header/Main menu I would look into the 'sliding doors' technique (in case you want it resizable). But this technique will also work for non resizable elements

- For the content areas (left and right) I would recommend the 'Faux Columns' technique.

No code, just some pointers, hope it helps you out :)

eulogy

8:28 pm on Jul 11, 2009 (gmt 0)

10+ Year Member



Here's what I have so far, just trying to get a centered div container with 100% height.

CSS:


body {
margin: 0 auto;
width: 750px;
padding: 0;
height: 100%;
}
#container {
position: absolute;
padding: 0;
width: 750px;
height: 100%;
margin-left: auto;
margin-right: auto;
}

and the html is just calling out the container in the body tags.

What I'm getting seems correct for the most part. I'm having a little trouble understanding how to place a div inside of a container div, and then have it go to a place relative to the container (in this case I want a top-left rounded corner image, 11x11px, in the top-left corner of the container div).

Also, changing the body width (which seems necessary or it doesn't center the container div) doesn't seem to let me change the background color of the entire page.

I'm also trying to get a repeating-background image that's 728 (750, minus 11x2 for both corners) pixels long with a repeating background, in-between the two top corners... or just a 750x11 containing two other div's with the 1x11 background repeating and the 11x11 div's on each side.

I'm getting so confused. Tables were so much more simple, but change one thing and another cell may get destroyed... I could just give up and work with tables but I would rather learn this div business.

swa66

11:11 pm on Jul 11, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



That way of doing height:100% and position: absolute will haunt you.

First thing to do: forget that you're going to replace a <table> with <div>s it'll only lead you into more trouble.

I'll try to show a few basic things on how to get a 100% page with positioing on the main container into being.

First: ditch IE, yes the browser that most of your users will use. It'll only get you on the wrong foot and frustrate you.
Choose any other browser: firefox, opera, or safari, any of them will do.

Next get a basic html template e.g.:


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>test</title>
<style type="text/css">
* {
margin:0;
padding:0;
}
</style>
</head>
<body>
<div id="header">
<h1>Header</h1>
</div>
<div id="content">
<p>Content goes here</p>
</div>
<div id="footer">
<p>footer</p>
</div>
</body>
</html>

As you see I'm no big fan of wrappers (and I'm even hesitant to put a div around the header and footer in real life but I'll indulge the footer for a good reason and the header cause most real headers need more than a single h1 can provide.

In a real life situation, the CSS would be linked, not in the header, but that's for easy reproduction here.

At this point the html is almost "done". Yes I'm going to be very reluctant to add more in the html that isn't content. I'll make an expception to fix the IE trouble later on.

So let's get you a working fixed width centered body.


html {
background-color: grey;
}
body {
background-color: white;
width: 750px;
margin: 0 auto;
}

Yep it's that simple.

Now the trouble will come if we want to position thing inside this centered block, so we're going to give the body "position". Any block having position changes their children into not referencing a higher up parent or the viewport when having absolute position themselves.
All that is needed to give an element position is to set position:relative on it.


body {
position: relative;
}

On to stretching this to be 100% in height.
most often people get this part very wrong a few times before they figure it out.
First: 100% height gives an element the height of it's parent if it has an explicitly set height different from auto. (so not the height of the viewport most seek to have as a minimum). There is an expection: the root element has the height of the viewport.
So we do the following:


html {
height: 100%;
}
body {
min-height: 100%;
}

Note that the min-height is to allow the body to grow larger than the viewport (you'll need to add more content to see it in action.)

now there is a bit of a problem at this point we created for ourselves:
The measures like height and width work on the content, and padding, borders go around that making the element larger.
So in order to not make the elements larger we need to be very careful where we add padding and margins. e,g, a vertical padding on the body will now make it larger than the viewport causing scrollbars.

So how do we get padding on there ? We set it on the children ...

e.g.:


#header {
padding: 5px 5px 0 5px;
background-color: lime;
}

Ok, that footer in a 100% height design usually needs to stick at the bottom, so lets put it there using positioning:


#footer {
position: absolute;
bottom:0;
background-color: orange;
}

Now wait, ... There are a few problems here: first of all it's not the full width, and if we add padding and width 100% it'll grow bigger than the parent.
Secondly since it's now absolutely positioned we can make the footer go over the content and not beign able to scroll out underneath it.

The solutions are simple enough once you tried a few:
The horizontal padding can go on the <p> inside the footer as not to interfere with the 100% width of the footer itself.

and if we know the height of the footer, we can pad the content div with enough to make sure it's got some black space of the height of the header on it's bottom to make sure it can clear the footer.

Adding in some padding in the vertical on the body this yields:


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>test</title>
<style type="text/css">
* {
margin:0;
padding:0;
}
html {
background-color: grey;
height: 100%;
}
body {
background-color: white;
width: 750px;
margin: 0 auto;
position: relative;
min-height: 100%;
}
#footer {
position: absolute;
bottom:0;
height: 1.2em;
width: 100%;
background-color: orange;
}
#footer p {
padding: 0 5px;
}
#content {
padding: 0 5px 1.2em 5px;
background-color: yellow;
}
#header {
padding: 5px 5px 0 5px;
background-color: lime;
}
</style>
</head>
<body>
<div id="header">
<h1>Header</h1>
</div>
<div id="content">
<p>Content goes here</p>
</div>
<div id="footer">
<p>footer</p>
</div>
</body>
</html>

So now let's assume we want a border on the body. Since it'll make the body heigher we cant really add it there, but we could add the top and bottom on the header and footer instead and just add the border on the body on the left and right (as it's the only element that goes all the way if the content is shorter than the viewport.)

So that would yield something like:


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>test</title>
<style type="text/css">
* {
margin:0;
padding:0;
}
html {
background-color: #ccc;
height: 100%;
}
body {
background-color: white;
width: 750px;
margin: 0 auto;
position: relative;
min-height: 100%;
border-left: 2px solid #555;
border-right: 2px solid black;
}
#footer {
position: absolute;
bottom:0;
height: 1.2em;
width: 100%;
background-color: orange;
border-bottom: 2px solid black;
}
#footer p {
padding: 0 5px;
}
#content {
padding: 0 5px 1.2em 5px;
background-color: yellow;
}
#header {
background-color: lime;
border-top: 2px solid #555;
padding: 5px 5px 0 5px;
}
</style>
</head>
<body>
<div id="header">
<h1>Header</h1>
</div>
<div id="content">
<p>Content goes here</p>
</div>
<div id="footer">
<p>footer</p>
</div>
</body>
</html>

Alternatively if we wanted rounded corners in browsers that do support the pre-CSS3 rounded corners that could be done too ...


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>test</title>
<style type="text/css">
* {
margin:0;
padding:0;
}
html {
background-color: #ccc;
height: 100%;
}
body {
background-color: white;
width: 750px;
margin: 0 auto;
position: relative;
min-height: 100%;
}
#footer {
position: absolute;
bottom:0;
height: 1.2em;
width: 100%;
}
#footer p {
padding: 0 5px;
}
#content {
padding: 0 5px 1.2em 5px;
}
#header {
padding: 5px 5px 0 5px;
}
body, #header, #footer {
-moz-border-radius:11px;
-webkit-border-radius:11px;
border-radius:11px;
}
</style>
</head>
<body>
<div id="header">
<h1>Header</h1>
</div>
<div id="content">
<p>Content goes here</p>
</div>
<div id="footer">
<p>footer</p>
</div>
</body>
</html>

It'll give some errors when validating against CSS2.1 validators of course.

So what's now left to do: test it in other browsers and fix the problems it'll cause in legacy IE browsers using a conditional comment or two (left as an exercise for now)

eulogy

7:33 am on Jul 12, 2009 (gmt 0)

10+ Year Member



Thank you so much, Swa66 (and Marcel as well), I've gotten a much better grasp of the concept of using css for layout purposes. Though your posts weren't the exact code I needed, I learned a lot from them (which is more important).

I'm really close to what I'm going for. I'm sure there's something I'm not doing perfectly, but it's working. The only thing that's bothering me how it is now is that the last row of divs, #contentspacing, #lightcontent, and #darkcontent stretch beyond the 100% of the viewport I was aiming for, and instead makes me scroll down (regardless of window size). I'm suspecting that the divs on top of those 3 are pushing it down the 70 pixels they take up, and still going the whole 100% in addition to that.

Here's my code if you have time to help with that issue, and please chew me out if I did anything lazy or wrong. I want to be as professional as I can be. Also, instead of throwing in a bunch of br tags before the divs (which does work), can I move all of them down just a tad? I'm sure it has to do with placing a margin-top somewhere but I'm not sure where at this point, and I'm scared of screwing up this fragile-feeling house of cards that I've built.


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>Test</title>
<style type="text/css">
* {
margin: 0;
padding: 0;
}

html {
background-color: #6a6a6a;
height: 100%;
}

body {
background-color: 6a6a6a;
min-height: 100%;
width: 750px;
margin: 0 auto;
position: relative;
height: 100%;
}

#topbar {
padding: 0;
float: left;
width: 728px;
height: 11px;
background-image: url(../portfolio%20slices/custom%20slices/topbar_bg.jpg);
}

#topbar_topleft {
padding: 0;
float: left;
width: 11px;
height: 11px;
background-image: url(../portfolio%20slices/custom%20slices/topbar_topleft.jpg);
}

#topbar_topright {
padding: 0;
float: right;
width: 11px;
height: 11px;
background-image: url(../portfolio%20slices/custom%20slices/topbar_topright.jpg);
}

#menubar {
padding: 0;
height: 50px;
text-align: center;
background-image: url(../portfolio%20slices/custom%20slices/menubar_bg.jpg);
}

#menubar_bottomline {
padding: 0;
height: 1px;
background-image: url(../portfolio%20slices/custom%20slices/menubar_bottomline.jpg);
}

#menubar_shadowdark1 {
width: 27px;
float: left;
padding: 0;
height: 8px;
background-image: url(../portfolio%20slices/custom%20slices/menubar_shadowdark.jpg);
}

#menubar_shadowlight {
width: 202px;
float: left;
padding: 0;
height: 8px;
background-image: url(../portfolio%20slices/custom%20slices/menubar_shadowlight.jpg);
}

#menubar_shadowdark2 {
width: 521px;
float: left;
padding: 0;
height: 8px;
background-image: url(../portfolio%20slices/custom%20slices/menubar_shadowdark.jpg);
}

#contentspacing {
width: 27px;
padding: 0;
float: left;
background-color: #444444;
min-height: 100%;
margin: 0 auto;
}

#lightcontent {
width: 202px;
float: left;
padding: 0;
background-color: #949494;
min-height: 100%;
margin: 0 auto;
}

#darkcontent {
width: 521px;
padding: 0;
float: left;
background-color: #444444;
min-height: 100%;
margin: 0 auto;
}
</style>
</head>
<body>
<div id="topbar_topleft"></div><div id="topbar"></div><div id="topbar_topright"></div>
<div id="menubar"></div>
<div id="menubar_bottomline"></div>
<div id="menubar_shadowdark1"></div><div id="menubar_shadowlight"></div><div id="menubar_shadowdark2"></div>
<div id="contentspacing"></div><div id="lightcontent"></div><div id="darkcontent"></div>
</body>
</html>

swa66

10:19 am on Jul 12, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Ok, in the spirit of learning:

background-color: 6a6a6a;

is a syntax error (missing #), and not needed as the html underneath has the same color.
You can minimize these by validating the CSS e.g. at [jigsaw.w3.org...]

The padding:0 statements you have all over are also not needed: there is a

* {padding:0;}
that turns off padding for all elements that would have it by default.

slices ... I'm pretty sure the trend is the opposite way away from slices and into CSS sprites: basically it stops chopping up pictures and instead merges them, even unrelated one ones are merged and then used as background images.

height: 100% on the body will hurt you. If you add it for IE6, I strongly suggest you hide it from other browsers using a conditional comment.
If you added it to have your columns to get a reference to get their min-heigt from that means they get the height of the body which is your problem ...

Next you seem to be trying to have 3 columns fill the needed space and at least stretch your design to fill the screen.

This approach simply won't do it I'm afraid.

The trick is to first look at your columns in this case cause I doubt a 27px wide col will get content (get rid of it, you're not using tables, you can be much more flexible than just stacking rectangles ...)

I'd do faux columns: set a background on the body to create the look of the columns you seek and then -floats aren't part of the flow, so parents are not supposed to stretch to encompass them) make it stretch by either adding a not cloated element under the columns that has the clear property or use a "clearfix" solution (take care not to get hacks along with it that you don't need).

eulogy

4:45 pm on Jul 12, 2009 (gmt 0)

10+ Year Member



Thank you again for all of your help!

I haven't yet put in the content boxes, but the faux_bg.jpg is a 750x1 image that repeats all the way down the page, appearing as if the columns stretched all the way down. This sorta feels like a waste, since it's really only 3 colors and could just be done with hexadecimal in the code... but I guess that's why it's a "cheat".

I did some reading on CSS sprites, and from what I gathered you use one master image and just have elements that have a background of that image, but only displaying the proper part of it to appear as a separate image. I figure it's just plugging in the top-left corner 'coordinate' of the master image and having the width and height determine what is displayed. Am I far off?

Other than not using CSS sprites, are the way I use the div elements, for the cosmetic images and menu box, good to go? All I'd have to change if I was switching from slices to sprites is the background image url and add in however you pick the section of that image, correct?

Should I do cosmetic images the way I had it above (separate floating elements), or like this?;


#header {
height: 11px;
background:url(custom%20slices/topbar_bg.jpg) repeat-x bottom;
}

#topbar_topleft {
position: relative;
top: 0;
left: 0;
height: 11px;
width: 11px;
}

#topbar_topright {
position: relative;
top: 0;
left: 728px; /* 750px - 11px on each side */
height: 11px;
width: 11px;
}


<div id="header">
<img id="topbar_topleft" src="custom%20slices/topbar_topleft.jpg"><img id="topbar_topright" src="custom%20slices/topbar_topright.jpg">
</div>

swa66

9:43 pm on Jul 12, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



I'd use

#topbar_topleft {
position: absolute;
top: 0;
left: 0;
height: 11px;
width: 11px;
}
#topbar_topright {
position: absolute;
top: 0;
right: 0;
height: 11px;
width: 11px;
}

position relative:
- gives the element "position" (use as a reference by children having absolute positioning
- allows to "nudge" the element using top/left/right/bottom statements
- leaves a spot where the element used to sit in the flow

position absolute:
- removes the element from the flow
- puts it where you specify using top/bottom/left/right in relation to the closest parent that has position and in the absense of such a parent in relation to the viewport
- makes the element gain position

position: static:
- the default

position: fixed:
- removes from the flow
- stuck to a specified spot on the viewport (not scrolling along with the page)

BTW: if we're going to be extremely correct: names should be what the element is, not how it's rendered (it'll last longer upon changes to style not to have anything in the html reflect how it's rendered).

eulogy

11:24 pm on Jul 12, 2009 (gmt 0)

10+ Year Member



I was having some troubles but I realized I hadn't set the body to relative position. Everything seems to be working now. Also, is there any way to shove the header down a bit, and not have the background repeat til below the header?

I don't want my rounded-box to start directly at the top of the browser window, but I don't want the faux columns background to show above it. Would creating a grey div box to cover that up be an acceptable solution? Messing with body margins doesn't stop the background from repeating.

Or is there something I can do to this line in the body css?

background: #6a6a6a url(custom%20slices/faux_bg.jpg) repeat-y center;

Sorry for posting so much code but when I was looking around this site I felt it'd be more helpful to get the whole thing in code.

CSS;

* {
margin: 0;
padding: 0;
}

Body {
position: relative;
text-align: center;
background: #6a6a6a url(custom%20slices/faux_bg.jpg) repeat-y center;
width: 750px;
margin: 0 auto 0 auto;
}

#header {
position: absolute;
top: 0;
height: 11px;
width: 750px;
background:url(custom%20slices/topbar_bg.jpg) repeat-x bottom;
}

#topbar_topleft {
position: absolute;
top: 0;
left: 0;
height: 11px;
width: 11px;
}

#topbar_topright {
position: absolute;
top: 0;
right: 0;
/*left: 728px; /* 750px - 11px on each side */
height: 11px;
width: 11px;
}

#menubar {
position: absolute;
top: 11px;
left: 0;
height: 50px;
width: 750px;
background:url(custom%20slices/menubar_bg.jpg)
}

#menubar_bottomline {
position: absolute;
top: 61px;
left: 0;
height: 1px;
width: 750px;
background:url(custom%20slices/menubar_bottomline.jpg);
}


HTML;

<body>

<div id="header">
<img id="topbar_topleft" src="custom%20slices/topbar_topleft.jpg"><img id="topbar_topright" src="custom%20slices/topbar_topright.jpg">
</div>
<div id="menubar"></div><div id="menubar_bottomline"></div>

</body>

I haven't got the content boxes in yet, I'm just worrying about the header area first. But everything appears to be ready to make those.

eulogy

8:18 am on Jul 13, 2009 (gmt 0)

10+ Year Member



I've started from scratch yet again with a much simpler (and better looking) design.

Right now I'm using the faux-columns to set up a header, navigation column, a content column, and a footer.

The only problem with that is, I have the content column holding 3 more columns so that I can fit more pictures, I figure I can fit more on the screen this way and prevent having to scroll too much.

However, while it seems in great working shape, I wouldn't want text to push down the next image so that it isn't in line with the adjacent pictures.

Basically, I need it to act like a table, I know there are some display:table properties but I really wouldn't know where to start with that. I just want to avoid making a custom amount of div boxes depending on how many pictures are on the current page.

Oh, and I found a pretty neat trick to automatically make pictures in certain areas resize to specific widths while keeping aspect ratio intact, so that helps for this. I suppose I could make a sprite sheet for all thumbnails, but god that'd be a pain, especially if I wanted to add more. The pics aren't all the same ratio, too.

SuzyUK

10:00 am on Jul 13, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



maybe Inline-Blocks [webmasterworld.com] would work for this? It should work no matter many images are on the page.