Forum Moderators: not2easy

Message Too Old, No Replies

Easy when you know how

         

haydenc

6:32 am on Sep 30, 2009 (gmt 0)

10+ Year Member



Hi,

I've been going round the internet attempting to find solutions to my CSS misunderstandings and being none the wiser. I'm putting a . here and # there, and my brain's starting to hurt.

Here is what I'm trying to do:

Have one background image that would fill the page. No scrolling, no repeating. Possibly white space if someone enlarges too much.

On top of this have a frame in the middle (this has already been designed in photoshop). What size should this be?

There would be a menu on top of this frame. The text would be white usually and yellow on hover,active and visited. I have included a horizontal red strip within my frame design, where I want my menu items to be.

Within the frame there would be a container box for all my content for each page. Whilst the content within the box would change from page to page, the actual shape and size of the box would not.

The frame, menu and container box would be centered so that when the browser screen was enlarged or shortened it would remain in the middle

I've experimented with DIVs and stylesheets and am still not getting it all. I understand how to define something within a container such as color:white; and put those within {}, but it's the rest that's getting me.

I've done the google search and all I'm now seeing is code

And I've watched quite a lot of tutorials

My brain's spinning.

Any help would be much appreciated.

Thanks in advance

Hayden

Mr Bo Jangles

7:48 am on Sep 30, 2009 (gmt 0)

10+ Year Member



I'd like to correct your subject line haydenc, because CSS is waaaay from easy even if you know a bit of the 'how'. In fact it is closer to a magic than a science - but it's not 'happy magic', it's infuriatingly difficult magic.

*_*

swa66

10:13 am on Sep 30, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Sound like fun, let's do this tutorial step-by step.

Frist, as always with CSS: ditch IE. Yes, the browser your users will be using in 70+% of the cases: ditch it. It will only put you on the wrong foot, complicating your task uselessly. We'll only reopen it at the very end to work around issues it might have, for now don't worry about that browser.
So pick any browser you like aside of IE: firefox, safari, chrome, opera, ...

First we need to nail down the html we're going to use.
I'll start from this framework cause it's much easier to render in here, but in real life I would not put the CSS in the header but instead use a <link>-ed file.


<!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">
<head>
<title>Test</title>
<style type="text/css">
* {
padding:0;
margin:0;
}
</style>
</head>
<body>
</body>
</html>

Now content-wise we had a menu:


<ul class="menu">
<li><a href="#">home</a></li>
<li><a href="#">contact</a></li>
<li><a href="#">about</a></li>
</ul>

You get the idea.

The rest of the content is undertermined so far.

Now it's decision time:
Do we need a wrapper or not? In general I'm very hesitant (others will slap it on there without as much as a thought). In this case I'm going to do it, although it's not strictly needed at this time, (we can style html and body to do what you described easily enough) but we'll add it for the sake of future possibilities (to be able to add some subtle copyright footer outside of your content "box". e.g.)

So the html would boil down to:


<!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">
<head>
<title>Test</title>
<style type="text/css">
* {
padding:0;
margin:0;
}
</style>
</head>
<body>
<div id="content">
<ul class="menu">
<li><a href="#">home</a></li>
<li><a href="#">contact</a></li>
<li><a href="#">about</a></li>
</ul>
<p>content goes here</p>
</div>
</body>
</html>

At this point I consider the html "finished", all stylle will go in the CSS.

Now you have an photoshop design in mind, which is great: you know what you want it to look like, but that has one major drawback: you're thinking in terms of static size. The web is far more dynamic in size and hence you need to imagine what will happen with your content when those constraints become flexible instead of being static.
E.g. the height and width of the screen might be significantly too large or too small for your content.
E.g. the user might have enlarged the minimal font size the browser will use significantly, forcing your text to burst out of it's box.

And that box brings me to another thing: html and CSS and thinking about "boxes"
is constraining what CSS can do, esp. with floats having the ability to push aside content we can do far more complex shapes and concepts than a box. One example ong ago out here was somebody seeking text that flowed next to an image of a spine and follow that closely.
Enough of a rant I guess.

So here's the idea for now (I'm sure there are dozens of opinions on this, but I need a choice to be made in order to continue and we can always come back and correct this anyway.)

- We'll have the <html> cover all of the viewport,
- We'll have the <body> do the same, but push it a notch further: it'll have a minimum size of 770px (wide) by 577px (high) in order to force scrollbars on the browser should the viewport become too small.
- We'll have the div with id content to be 750px by 562 px and centered both vertically as well as horizontally in the body.

Now where did I get those sizes:
770px wide is as wide as you can safely go on a 800x600 sized monitor, there are still people on that (and even smaller: think the iphone), most will have a bigger screen, but don't forget those with really large screens will not use their screen with a browser full screen and instead only give you about half of the screen, putting you right back at that 800px width. You can go wider if you need to of course.
The height is just arbitrary at a 3/4 aspect ratio to allow you to find space for your content, and the nice effect is that it isn't all too large for most screens as well.
Again it can be increased if you need to.

Note vertical centering is somewhat of a holy grail for some, it's quite doable here cause you promised there would not be different sized content.

So let's get started: first we need to get the body and the html to stretch all the way down the page (the body doesn't do that on it's own):


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

Now a word of explanation is needed: height: 100% is a strange beast at first: it sets the height of the element to the height of the direct parent provided the parent has an explicitly set height different from "auto" (which is also the default value). The exception is the root element: it has the height of the viewport.

So setting this makes the body and the html both have the height of the viewport (the window).

Now we wanted to be sure the body had some minimal dimension, so we add that:


body {
min-height: 577px;
min-width: 770px;
}

Try it in a browser and resize the window: you'll see the scrollbars appear if you make it too small.
(tip: add some background colors to both the html and body (different colors) to see where they are. Yep, you only see the body (if you want, for fun: add a max size as well: now you'll see the html if you go big enough)

The content needs its size too:


#content {
height: 562px;
width: 750px;
}

Since your head started to hurt when you saw # and . :
- an element with a class="foo" on it can be referenced as ".foo" in CSS
- the only element with id="bar" can be referenced as "#bar".
Easy as that.

Now we need to see that div for further positioning, so we'll add a contrasting background color for now (we can remove it later).

And we'll use absolute positioning to center the #content in the body (remember the body isn't always the same size as the viewport: when the viewport is too small the body becomes larger due to it's min-width and min-height.)

We do this with absolute positioning:
and we'll use the property that auto margins will balance out to be the same size if all other constraints are set


body {
position: relative;
}
#content {
background-color: orange;
position: absolute;
top:0;
right:0;
bottom:0;
left:0;
margin: auto;
}

So what's going on there:

body is given position:relative (giving it "position"): this means that it's children (not needing to be direct children) will now use the body as a reference for their absolute positioning.

the content div is given absolute positioning and it's left and right side are put on the sides of the body (which remember is at least 20px wider than the #content itself, but since all 4 margins are set to be auto margins it means the margins can divide the difference among them and center the #content.)
Same thing happens vertically.

Since we can't be 100% sure a visitor doesn't have gigantic fonts as a minimum etc it's best to be safe on what happens should the content in the #content div be larger than it has space for anyway.

We're going to use overflow:auto for that.

Try it with adding a bunch of content in the content div to see what happens (look for a scrollbar).

Other options exist as well, but this is the most friendly I think to those needing a larger font or so.

So we're now using:


<!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">
<head>
<title>Test</title>
<style type="text/css">
* {
padding:0;
margin:0;
}
html {
height: 100%;
}
body {
height: 100%;
background-color: silver;
min-height: 577px;
min-width: 770px;
position: relative;
}
#content {
background-color: orange;
height: 562px;
width: 750px;
position: absolute;
top:0;
right:0;
bottom:0;
left:0;
margin: auto;
overflow: auto;
}
</style>
</head>
<body>
<div id="content">
<ul class="menu">
<li><a href="#">home</a></li>
<li><a href="#">contact</a></li>
<li><a href="#">about</a></li>
</ul>
<p>content goes here</p>
</div>
</body>
</html>

Let's move on to the menu:

You wanted a horizontal menu with a red strip and white and yellow text ?

There are a few more things to know, like what you were you want the menu horizontally, but I'll take the most difficult one: centered.

Let's start with a dark red background:


.menu {
background-color: #a00;
}

The .menu refers to any element with the class="menu" attribute.

The color #a00 is just one of many possible ways to write a color, alternatives are #aa0000 (which is how photoshop would write it), or even rgb(170,0,0).

Although we can't see them right now, there are bullets on a list, so we remove them before they show up somewhere unexpectedly:


.menu {
list-style: none;
}

No wit's still we need it to be al on one line that we can center.
most (if not all) of the menu examples you'll find at this point will float the <li> elements, but that rules out centering, so we'll make the <li>'s inline elements (make them act like text instead of like blocks.)


.menu li {
display: inline;
}

See the ".menu li" selector: that going to select all <li> elements that have a parent (not needing to be a direct parent) with a class="menu" attribute on it.

Now let's get rid of that underlined blue on red that's hurting my eyes:


.menu a {
text-decoration: none;
color: white;
}

Again the selector ".menu a" latches on to all the <a>'s in an element with class="menu" (and as obvious here there is no need for that element to be the direct parent of the <a>.

Now you wanted it to be yellow n certain cases, and those were hover, visited and active ... from a usability aspect I have doubts that's intuitive to most users but we can do that:


.menu a:visited, .menu a:hover, .menu a:active {
color: yellow;
}

This is a comma separated list of selectors.
Each has the more or less the same except of that pseudo state on it.
The stuff plied to the <a> above remains applied unless there is a conflict between the values of what's in this rule vs. what was in the normal rule, as in that case, the more specific rule wins (and a psuedo class counts for as much as a real class in the specificity calculation.)
[Don't worry about specificity too much just yet, just know it exists and this is where it comes into play, do learn it eventually, it's a care aspect of understanding CSS fully, but not needed for simple things like this just yet]

Now I'm sure I'm going to get flak from old school purists as they use a mnemonic to get the link, visited, hover and active pseudo states into the CSS in separate entries.
Yet if you have a somewhat modern browser that obeys the cascade and you know a few things about CSS's specificity, you know this will work too.
But if you really want, it's ok to write it as :


.menu a {
text-decoration: none;
color: white;
}
.menu a:link {
color: white;
}
.menu a:visited {
color: yellow;
}
.menu a:hover {
color: yellow;
}
.menu a:active {
color: yellow;
}

It's just not useful in this case.
BTW: the mnemonic is LoVe-HAte, but since there's soon to be more pseudo states available for us via CSS3, the mnemonic ant the associated "rule" have had their time IMHO.

now if you just want the yelow on hover, I'd do it as follows:


.menu a {
text-decoration: none;
color: white;
}
.menu a:hover {
color: yellow;
}

Centering the menu. You saw how we centered the block element #content, but this is inline, text, and we'll center it using simply:


.menu {
text-align: center;
}

Leaving us with:


<!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">
<head>
<title>Test</title>
<style type="text/css">
* {
padding:0;
margin:0;
}
html {
height: 100%;
}
body {
height: 100%;
background-color: silver;
min-height: 577px;
min-width: 770px;
position: relative;
}
#content {
background-color: orange;
height: 562px;
width: 750px;
position: absolute;
top:0;
right:0;
bottom:0;
left:0;
margin: auto;
overflow: auto;
}
.menu {
background-color: #a00;
list-style: none;
text-align: center;
}
.menu li {
display: inline;
}
.menu a {
text-decoration: none;
color: white;
}
.menu a:visited, .menu a:hover, .menu a:active {
color: yellow;
}
</style>
</head>
<body>
<div id="content">
<ul class="menu">
<li><a href="#">home</a></li>
<li><a href="#">contact</a></li>
<li><a href="#">about</a></li>
</ul>
<p>content goes here</p>
</div>
</body>
</html>

Now we need to make it prettier.

Let's make that menu look a bit more like buttons one would press:


.menu {
font: normal 14px/2em verdana, helvetica, sans-serif;
text-transform:capitalize;
}
.menu a {
padding: 2px 5px;
margin: 0 1px;
border-top: 1px solid #800;
border-left: 1px solid #800;
background-color: #c00;
}

Let's explain them a bit:
font: is a shorthand notation. In this case it's setting the font
- to be normal weight (not bold)
- to be 14px tall (now there's much to be said about this, and some would certainly prefer another way of setting it, but I'm also taking into account your fixed sized box for the rest of your content in this.
- The line height is set to be twice the with of the letter M (that's what 2em means)
- the font family is a list of fonts (in priority) that the browser should try to use (if it's available on the system). The last one has to be a generic font (sans-serif is such one, it's always available (otherwise the threat of browsers is that they use courier)

text-transform:capitalize is inherited by the children, so all the <a>s that have content will use this

I make the <a> look a bit more like a button with some color use and borders and the like. If you need explanations on this, just ask.

So now we move on to images (which I can't have). A lot of it depends on what you have/want on them.
But lets assume they are large and the important bit is at the top center (so the bits to fall of the screen if too narrow or both left and right and the bottom if the screen is not tall enough. This is mostly important in positioning it on the background.

So we take off the range background of the #content (that was there just to see where the #content was), and let it become transparent again.

And we do the same with the silver background on body, but replace it with:


body {
background: white url('1.jpg') no-repeat center top;
}

What does this do ?
- Sets the background color itself to white (change to any color you like better to continue your image should the element be larger than the image)
- load an image as a given URL as background (note: this is relative to wher ethe CSS is, not to where the HTML is if they are on different paths),
- make the image not repeat
- position it vertiallly at the top and center it horizontally on the element.

If your image has it's important bit in the center vertically also, replace the top with center: ives a real neat effect when resizing, but you really need to design the image to have all 4 of its edges cut off to do that.

Could seem to be done, but it's not, when the viewport is too small the background is centered on the viewport not on the body!

There's a special thing about backgrounds on html and body: when only one of them has a background it is always applied to the viewport, not to the element itself (I guess for backwards compatibility). So we need to break that rule and make sure the background is applied to our carefully positioned and sized body by simply adding a background to the html that will not be seen as our body is always as least as large as the html ...

So that gives:


<!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">
<head>
<title>Test</title>
<style type="text/css">
* {
padding:0;
margin:0;
}
html {
height: 100%;
background-color: silver;
/* to prevent the background of the body to be applied on the html */
}
body {
height: 100%;
background: white url('1.jpg') no-repeat center top;
min-height: 577px;
min-width: 770px;
position: relative;
}
#content {
height: 562px;
width: 750px;
position: absolute;
top:0;
right:0;
bottom:0;
left:0;
margin: auto;
overflow: auto;
}
.menu {
background-color: #a00;
list-style: none;
text-align: center;
font: normal 14px/2em verdana, helvetica, sans-serif;
text-transform:capitalize;
}
.menu li {
display: inline;
}
.menu a {
text-decoration: none;
color: white;
padding: 2px 5px;
margin: 0 1px;
border-top: 1px solid #800;
border-left: 1px solid #800;
background-color: #c00;
}
.menu a:visited, .menu a:hover, .menu a:active {
color: yellow;
}
</style>
</head>
<body>
<div id="content">
<ul class="menu">
<li><a href="#">home</a></li>
<li><a href="#">contact</a></li>
<li><a href="#">about</a></li>
</ul>
<p>content goes here</p>
</div>
</body>
</html>

Test it in all standards complaint browsers.

FF: check
Safari: check
Opera: check

So at this point I'd declare it DONE.

Yes it's not tested in IE (and it will break miserably in IE6 for sure), but the changes needed for that browser will only go in a conditional comment and not affect my code for all the other browsers.

So that leaves testing in IE8, IE7, and worst of all: IE6 if you still care about that browser.

I'm goign to take a break here (it's a long post already), and I'd rather fix misunderstandings before I mess with IE as the fixes needed in IE might not be needed anymore as we change what we have in place.

So is this what you were looking for and did you grasp it all (if not, don't be shy. But please don't use that last code dump without understanding what it all does, and why it is all in there. There''s no shame in not knowing something.

swa66

10:29 am on Sep 30, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Note that I used quite a few rather fancy techniques in there I realize this is maybe too much like trying to drink from the firehose. So really: feel free to ask more where you've trouble grasping the concepts.

swa66

10:48 am on Sep 30, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



I'd like to correct your subject line haydenc, because CSS is waaaay from easy even if you know a bit of the 'how'. In fact it is closer to a magic than a science - but it's not 'happy magic', it's infuriatingly difficult magic.

I think that's the too little knowledge to do it right, too much knowledge not to mess with it syndrome :)

There is but one way out of it: learn more. CSS _is_ simple as long as you're ready to learn all the concepts in there.

The black magic only comes when you have to deal with the evil curse: IE (and esp. the legacy versions of it). The solution that keeps you sane is to ignore IE till the very last and then isolate the workarounds it needs in a conditional comment. It stops you from needing to understand the twisted stuff in IE and you can just focus on making it look acceptable enough in that browser.
Since IE (even IE8) is years behind what other browser routinely can do, there is a point to be made to not even try to make it look the same anymore.

haydenc

11:13 am on Sep 30, 2009 (gmt 0)

10+ Year Member



I thought I'd say a quick thanks now for your help, before I've even read it as I think it's gonna take a while. I do quite like magic. Also, I always thought Microsoft were the bastions of simplicity ;-)

When the questions and issues arise, I'll repost

Thanks again