Forum Moderators: not2easy

Message Too Old, No Replies

The importance of ordering the elements in HTML

content VS presentation

         

tata668

5:21 pm on Apr 26, 2006 (gmt 0)

10+ Year Member



Let's say I have 4 elements to display horizontally in the top section of my page:

[ELEMENT 1] [ELEMENT 2] [ELEMENT 3] [ELEMENT 4]

And let's say their logical order is really 1-2-3-4. It can't be 2-1-4-3 for example, it wouldn't be correct.

Now, lets say I want to align them to the right of my top section. Each element is a div, so I though about floating them to the right, inside the "top" div.

For them to be in the correct order (1-2-3-4) I needed to place them in the *reverse order* in my html! Indeed, [4] should be float:right before [3], [3] before [2] and [2] before [1].

What is sad about that is:

1) CSS should be about separing content and presentation, right? Now this is a simple example where I have to change my content to change its presentation (if I want to float the elements)

2) Users using a text-only browser will see my elements in *the wrong order*!

Any though, trick, idea?
Am I missing something?

Fotiman

6:25 pm on Apr 26, 2006 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Do a google search for One True Layout. There's an article on positioniseverything.net that does ANY order without requiring you to change the order in the source. It has to do with negative margins. Good luck.

tata668

8:21 pm on Apr 26, 2006 (gmt 0)

10+ Year Member



Thanks, I see what I'm trying to do is possible, yet not that easy to implement!

willybfriendly

9:17 pm on Apr 26, 2006 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member




.right
{
float:right;
}
.left
{
float:left;
}

<div class="right">
<div class="left">Element 1</div>
<div class="left">Element 2</div>
<div class="left">Element 3</div>
<div class="left">Element 4</div>
</div>

WBF

tata668

9:44 pm on Apr 26, 2006 (gmt 0)

10+ Year Member




.right
{
float:right;
}
.left
{
float:left;
}

<div class="right">
<div class="left">Element 1</div>
<div class="left">Element 2</div>
<div class="left">Element 3</div>
<div class="left">Element 4</div>
</div>

Yes, that's works! But one time on three Opera 8.5 does not display that correctly. I only see "Element 1"! The other Elements are pushed below even if their is plenty of space in the top div. If I zoom in or out the display immediately correct itself. It's acting as if sometimes the "right" wrapper in your example didn't expand enought!

Any idea why?

Thanks

doodlebee

11:58 pm on Apr 26, 2006 (gmt 0)

10+ Year Member



perhaps you need to clear your floats?


.right
{
float:right;
}
.left
{
float:left;
}
hr {
clear:left;
visibility:hidden;
}

<div class="right">
<div class="left">Element 1</div>
<div class="left">Element 2</div>
<div class="left">Element 3</div>
<div class="left">Element 4</div>
<hr />
</div>

tata668

12:25 am on Apr 27, 2006 (gmt 0)

10+ Year Member



Thanks for the idea but it didn't help.

Opera still only shows the first element once in a while! I zoom in or zoom out and all elements appear as they should.

Grrrr...

tata668

12:33 am on Apr 27, 2006 (gmt 0)

10+ Year Member



I can also press the tab key to trigger the correct display in Opera!

doodlebee

12:59 am on Apr 27, 2006 (gmt 0)

10+ Year Member



Thanks for the idea but it didn't help.

Opera still only shows the first element once in a while!

That's funny - I just tested out *both* versions (with my <hr> tag and without) and they both work fine in Opera 8.5 on PC. Comes right up just fine 'n dandy!

tata668

1:17 am on Apr 27, 2006 (gmt 0)

10+ Year Member



Here's the code that triggers the display problem in Opera 8.5 on my XP box. Be sure to place an 26px X 27px image in the same rep:


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<style type="text/css">

#top
{
width:780px;
background-color:Silver;
}

.right
{
float:right;
}

.left
{
float:left;
}

</style>
</head>
<body>

<div id="top">
abc
<div class="right">
<div class="left">
<img src="element1.jpg" /> <!-- existing 26px X 27px image -->
</div>
<div class="left">
ELEMENT 2
</div>
</div>
</div>

</body>
</html>

The first time the page loads, Opera displays the text, "ELEMENT 2", under the image! If you zoom in and zoom out, the text is correctly placed at the right side of the image.

doodlebee

12:14 pm on Apr 27, 2006 (gmt 0)

10+ Year Member



I see what you mean.

If you add a width to your .left floated elements, you don't have the problem anymore.

tata668

2:34 pm on Apr 27, 2006 (gmt 0)

10+ Year Member



I can't add a width to those elements because they are dynamically generated by the server and their widths depend on few things: the current language used, the nickname of the user, etc.

Maybe I should use a table?

bedlam

2:51 pm on Apr 27, 2006 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



I can't add a width to those elements because...

Right. What you're trying to do is quite possible though. One question you might want to ask here is 'why float the dynamically generated elements at all'?

HTML

<ul id="foo">
<li>Dolor</li>
<li>Sit</li>
<li>Amet</li>
<li>Consectetuer</li>
</ul>

CSS

#foo { float:right; }
#foo li { display:inline; /* Take note: no need for superfluous classes on the list items... */ }

This may need to be adapted to your specific circumstances, but here's what to expect:

  • The floated ul will 'shrink wrap' the list items and be aligned at the left of the page
  • The list items, having been transformed into inline elements, will be only as wide as their contents.

You might also want to look into the various listamatic lists [google.com].

-b

tata668

3:27 pm on Apr 27, 2006 (gmt 0)

10+ Year Member




One question you might want to ask here is 'why float the dynamically generated elements at all'?

I tried the list trick and it works well. But:

1) Those 4 elements are not really *a list*, semantically speaking. Element (1) is an image for (2), Element (2) is a link, Element (3) is an Image for (4) and Element (4) is a select dropdown. They do not have the same "meaning", some are just decoration, one is a link, etc.

2) Isn't the float trick *supposed* to work?

3) The real problem I'm facing now is that IE displays the font-size too small inside those ul li! Even if the only CSS rule affecting IE in my code is body{font-size:81.25%;}..

But I guess this is a different story!

tata668

3:32 pm on Apr 27, 2006 (gmt 0)

10+ Year Member



Ok, I got the correct font-size in IE by adding:


#foo, #foo li
{
font-size:1em;
}

But I'm still not sure why I should use a list (Because it works? Tables work too!)

tata668

5:18 pm on Apr 27, 2006 (gmt 0)

10+ Year Member



Damn!

No one can say I'm not trying a tableless layout but there is so many things not working well..

I use a list (as bedlam suggested) because floating the div didn't work well in Opera 8.5. But now I'm unable to vertically align the elements inside that list! And I'm not speaking about "vertical-align:center" (I know that would be even more tricky), I'm talking about the elements to be aligned at the top of the list.. And then maybe adding some padding-top to them. That doesn't work.


#top ul li
{
display:inline ;
list-style-type: none;
vertical-align:top;
padding-top:10px;
}

Furthermore, Firefox doesn't behave the same as IE and Opera while aligning the images inside those list. IE and Opera align the TOP of the images with the top of the ul (this seems to me to be the correct behavior) but Firefox aligns the bottom of the images with the bottom of the other elements.

Again, be sure to use an existing image


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<style type="text/css">

#top
{
width:780px;
background-color:Silver;
}

#top ul
{
margin:0;
padding:0;
}

#top ul li
{
display:inline ;
list-style-type: none;
vertical-align:top;

}
</style>
</head>
<body>

<div id="top">
<ul>
<li>
<img src="element1.jpg" height="100px" />
</li>
<li>
abc
</li>
<li>
<img src="element1.jpg" />
</li>
</ul>
&nbsp;

</div>

</body>
</html>

So, using a list doesn't seem to be the way to place my elements in my top section because they don't have the same height.

[edited by: tata668 at 5:20 pm (utc) on April 27, 2006]

bedlam

5:18 pm on Apr 27, 2006 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



1) Those 4 elements are not really *a list*, semantically speaking...

So use a different arrangement like:

<div id="foo">
<span>Dolor</span>
<span>Sit</span>
<span>Amet</span>
<span>Consectetuer</span>
</div>

Isn't the float trick *supposed* to work?

Not only is it supposed to work, it actually does work (I've used variants on what you're attempting many times without the problem you're experiencing...probably there's some small error in your code, or you've triggered a small bug...), but the point was that there is not obviously any particular reason for using a float in this instance.

-b

[edit]We replied at the same time. Correct (i.e. to-spec) behaviour for alignment of images is to align the bottom of the image--since it's an inline element--with the baseline of the text in the parent box. This is true whether or not there is any text in the box with the image. Float the image inside the box or use 'vertical-align' with some value other than 'baseline'.[/edit]

tata668

5:24 pm on Apr 27, 2006 (gmt 0)

10+ Year Member




probably there's some small error in your code, or you've triggered a small bug

Please don't say there is errors in my code, my code is listed at msg #10.
If there are errors, where are they?

And if there is a bug in Opera, what is the workaround?

tata668

5:34 pm on Apr 27, 2006 (gmt 0)

10+ Year Member




Float the image inside the box

If I float the images (from code msg #16), then the text in the second li is not positionned correctly. Should I float it too? If so, is there really a difference between this code and code without any list (msg #10)?


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<style type="text/css">

#top
{
width:780px;
background-color:Silver;
}

#top ul
{
margin:0;
padding:0;
}

#top ul li
{
display:inline ;
list-style-type: none;
vertical-align:top;

}

#img1, #img2
{
float:left;
}

</style>
</head>
<body>

<div id="top">
<ul>
<li>
<img src="element1.jpg" id="img1" height="100px" />
</li>
<li>
abc
</li>
<li>
<img src="element1.jpg" id="img2" />
</li>
</ul>
&nbsp;

</div>

</body>
</html>


or use 'vertical-align' with some value other than 'baseline'.

I use "top", see msg #16.

tata668

5:47 pm on Apr 27, 2006 (gmt 0)

10+ Year Member




<div id="foo">
<span>Dolor</span>
<span>Sit</span>
<span>Amet</span>
<span>Consectetuer</span>
</div>

I'm not able to play with vertical alignment of those either.

Element 2, "abc", still stay aligned at the bottom of #top.


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<style type="text/css">

#top
{
width:780px;
background-color:Silver;
vertical-align:top;
}

#s2
{
padding-bottom:10px;
margin-top:-10px;
}

</style>
</head>
<body>

<div id="top">

<span id="s1">
<img src="element1.jpg" height="100px" />
</span>
<span id="s2">
abc
</span>
<span id="s3">
<img src="element1.jpg" />
</span>

&nbsp;

</div>

</body>
</html>

jannm

6:06 pm on Apr 27, 2006 (gmt 0)

10+ Year Member



Pardon me if this is a dumb question...

Could you not combine the 4 images into 1? You would guarantee their order and could use a map if you needed to create a link.

tata668

6:20 pm on Apr 27, 2006 (gmt 0)

10+ Year Member



It's not dumb jannm, but my elements are not 4 images..

Element 1: Image
Element 2: link
Element 3: Image
Element 4: dropdown

To resume, here's what I'm trying to do:

To horizontally align those 4 elements to the right (don't forget every element has an unknow/variable width). Once they are aligned horizontally, I want to be able to ajust the vertical alignment of every element, using margin or padding.

I though left-floating them inside a right-floated div would work (thanks willybfriendly) but it doesn't work well in Opera (see msg #10).

I'm really thinking about using tables here.

jannm

6:39 pm on Apr 27, 2006 (gmt 0)

10+ Year Member



OK then here's a dumb question - why does everyone hate tables so much? Lord knows how much time you've spent trying everything else. What's the downside of using tables that makes spending so much time worth it?

doodlebee

6:40 pm on Apr 27, 2006 (gmt 0)

10+ Year Member



Out of curiosity, what are you trying to accomplish? You say you can't use widths on the divs because it's dynamically generated content. To *me*, that sounds like it's tabular data. In which case, yes - use a table. That's what they're there for.

But there's things that you keep adding to the original idea, and I think, perhaps, that's what's skewing things out of whack.

I'm *assuming* you need a centered, two column layout, with some sort of right column that has images with descriptions - say, much like a photo gallery? In the right column? So far, what I'm getting from your code, that's what it seems to be to me.

In that case, you *are* going about it the wrong way a bit. Try this out and see if I'm assuming/reading into what you're trying to do.


<!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">

<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />

<style type="text/css">

*{
margin:0;
padding:0;
border:0;
}

#body {
text-align:center;
}

#container {
width:780px;
background:#DDD;
margin:0 auto;
text-align:left;
border:solid 1px #000;
}

#main {
width:460px;
float:left;
padding: 10px;
}

#sidebar
{
width:250px;
float:right;
padding:10px 25px;
}

img.left {
float:left;
margin:0 7px;
}

div.right {
float:right;
width:200px;
}

p {
margin-bottom:10px;
}

hr {
clear:both;
display:block;
visibility:hidden;
}

</style>

</head>

<body>

<div id="container">

<div id="main">
<p>Test text here. Test text here. Test text here. Test text here. Test text here.
Test text here. Test text here. Test text here. Test text here. Test text here.
Test text here. Test text here. Test text here. Test text here. Test text here.
Test text here. Test text here. Test text here. Test text here. Test text here.
Test text here. Test text here. Test text here. Test text here. Test text here.
Test text here. Test text here. Test text here. Test text here. Test text here. </p>
<p>Test text here. Test text here. Test text here. Test text here. Test text here. </p>
<p>Test text here. Test text here. Test text here. Test text here. Test text here. </p>
</div>

<div id="sidebar">
<img class="left" src="element1.jpg" />
<p>Descriptive text here to go with the image. This text will wrap around the image, covering
it on the right side and bottom of the image.</p>

<img class="left" src="element1.jpg" />
<div class="right"><p>Alternatively, if you don't want the text to wrap around the image, then you
can add in a div so it will stay cleared out beneath the image itself. The
length will expand, but the width will remain the same.</p></div>
</div>

<hr />

</div>

</body>
</html>

tata668

7:30 pm on Apr 27, 2006 (gmt 0)

10+ Year Member




OK then here's a dumb question - why does everyone hate tables so much? Lord knows how much time you've spent trying everything else. What's the downside of using tables that makes spending so much time worth it?

Well, this is a tableless layout test. I wanted to give CSS-P another chance. But with all those problems, there are good chances I'm gonna use tables at the end.


Out of curiosity, what are you trying to accomplish? You say you can't use widths on the divs because it's dynamically generated content. To *me*, that sounds like it's tabular data. In which case, yes - use a table. That's what they're there for.

No, this is not tabular data! It's four element horizontally aligned, that's it.

The layout you are suggesting is not at all what I'm trying to do.

What I want is that:

[IMAGE] [LINK] [IMAGE] [DROPDOWN]

- All on one "row", right aligned.
- Width NOT fixed for each element
- possibility to ajust the vertical alignment of each element

This is not a complete layout, it'a only for my "top" section (small "header" if you wish).

sldesigns

8:39 pm on Apr 27, 2006 (gmt 0)

10+ Year Member



possibly silly, but...

wasn't your original problem layout not on screen, but for text-only viewers? And if that's the case, they wouldn't see the images anyway, right? so the only real issue is the link comes after the drop down in that case.

You could set up a separate css file for those browser types.

doodlebee

10:23 pm on Apr 27, 2006 (gmt 0)

10+ Year Member



No, this is not tabular data! It's four element horizontally aligned, that's it.

The layout you are suggesting is not at all what I'm trying to do.

What I want is that:

[IMAGE] [LINK] [IMAGE] [DROPDOWN]

- All on one "row", right aligned.
- Width NOT fixed for each element
- possibility to ajust the vertical alignment of each element

This is not a complete layout, it'a only for my "top" section (small "header" if you wish).

Apologies for trying to help.

Your initial question seemd like one of interest in the issue, and it has now strayed into something specific. It seems these specifics are a closely guarded secret and we need to play guessing games to get information from you so we can help.

Your inital code (message #10) *also* included text and what seemed to be a sidebar, so it appeared to me you needed help with a certain layout. So apologies for not understanding your tidbits and clues here and there, and attempting to decipher them and assist you anyway. I also saw another message where someone suggested other code you have in there *could* be affecting other things (message #17), and you insisted that the code posted in #10 was *it* (message #18) - which is what we've been basing our assumptions from. But now you are saying the code in #10 is only for the header...so since you're not willing to post further code and let us see what you've done (and see if there's possibly some conflicting elements) we are left to further guesswork.

But now that I know you simply want a header fix, and it's only 4 items in a header, then maybe with this bit of clarification we can help you further. (And for the record the *only* elements in my previously suggested code were for the left text area and the sidebar content. Everything else had automatic width.)

So *assuming* I'm understanding you correctly, try the following:


<!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">

<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />

<style type="text/css">

*{
margin:0;
padding:0;
border:0;
}

#body {
text-align:center;
}

#container {
width:780px;
background:#DDD;
margin:0 auto;
text-align:left;
border:solid 1px #000;
}

#header {
width:780px;
background-color:#BBB;
}

#box {
float:right;
}

hr {
clear:both;
display:block;
visibility:hidden;
}

h1 {
display:inline;
float:left;
}

img {
vertical-align:bottom;
}

a, a:link, a:visited {
padding-top:5px;
}

select {
vertical-align:top;
margin-top:5px;
}

</style>

</head>

<body>

<div id="container">

<div id="header">
<h1> Header text here</h1>

<div id="box">
<img class="left" src="element1.jpg" />
<a class="left" href="#">Link</a>
<img class="left" src="element1.jpg" />
<select name="login">
<option value="">Please Select &nbsp;</option>
<option value="option 1">Option 1</option>
<option value="option 2">Option 2</option>
</select>

</div>
<hr />
</div>

</body>
</html>

tata668

12:13 am on Apr 28, 2006 (gmt 0)

10+ Year Member




Apologies for trying to help.

Your help is really appreciated! Didn't want to sound rude! And sorry if my messages weren't clear enough.

I tried your code and it works well! But I have the same problem with it than with the list version, I'm not able to play with the vertical alignment of some elements using margin or padding.

Take the link: <a class="left" href="#">Link</a>
How can I give it, let's say, a margin-top of 10px from the top?

This doesn't work:


a, a:link, a:visited {
margin-top:15px;
vertical-align:top;
}

But I also still like to know what is wrong with my code (msg #10)... Why does Opera display it like that?

Also, I'd like to know why you used a #container, is it needed or could you only have #header for wrapping everything? Is #container needed for some kind of wanted behavior?

Thanks for the help..

tata668

12:21 am on Apr 28, 2006 (gmt 0)

10+ Year Member




possibly silly, but...

wasn't your original problem layout not on screen, but for text-only viewers? And if that's the case, they wouldn't see the images anyway, right? so the only real issue is the link comes after the drop down in that case.

You could set up a separate css file for those browser types.

Yes, my first question was about the order of the elements inside the html.. I wanted them to be in a logical order in the html while being able to float them to the right. willybfriendly's suggestion did the trick but now my problem has evolved into how to display my 4 elements in a row while being able to play with their vertical alignment..

Thanks for the help anyway!

doodlebee

3:55 pm on Apr 28, 2006 (gmt 0)

10+ Year Member



Your help is really appreciated! Didn't want to sound rude! And sorry if my messages weren't clear enough.

I apolgize for sounding terse. I'm having a seriously bad week.

I'm not able to play with the vertical alignment of some elements using margin or padding.

Well, first off, vertical alignment in CSS2 is a seriously hard thing to accomplish. You can only do so much with margins and padding. When it comes to text, you *can* vertically center it with a simple trick: simply make a line-height and a height specification for your stuff, and make both the same. For example:

<li style="line-height:2em;height:2em;>text here</li>

And the "text here" would automatically vertically center. However, this only works on text.

Another way is to use the "display:table" and "display:table-cell" calls (to make a simple analogy to these calls, they sort of that your divs and turn them into table cells - and you can vertically align to your heart's content, as you would in a table). These work very well in Firefox, Opera and other standards-compatible browsers. However IE completely ignores it. Therein lies the issue.

Vertical centering (or just aligning, really) items like images and block-displaying elements become seriously more difficult. There *are* ways to do it, but it takes some heavy-handed coding to get it to work cross-browser. Again, using line-height and table-cell calls will aid you in your dream of veritcal alignment, but one works only with text, and the other doesn't work for IE at all.

Take the link: <a class="left" href="#">Link</a>
How can I give it, let's say, a margin-top of 10px from the top?

If you note in the last code I posted, I have the image set to "vertical-align:bottom" - that's what it took to get the text to move to the top of the image next to it. (Remove that line, and you'll see what I mean.) You can adjust the margins and padding of the *text* if you work on the "margin-bottom" - I don't know why, but you have to work from the bottom up, not the other way around.

But I also still like to know what is wrong with my code (msg #10)... Why does Opera display it like that?

The easy answer would be because it's the most simplified version of things. There's no extra attributes to it to make adjustments. Also, the floats weren't cleared, which was helping with the issue (but clearing the floats alone didn't fix it).

Also, I'd like to know why you used a #container, is it needed or could you only have #header for wrapping everything? Is #container needed for some kind of wanted behavior?

Actually the #container is left over from the code I posted prior. So, no, it's not really necessary. But whatever *your* code for the site is, you need to make that change if needed. The #container div is what sets the width, basically, for everytyhing else - the #container is your 780px wide, and the #header is 100% wide (which also help in allowing for the position of the right floated stuff). If your site layout already has a wrapping container area, then you don't need mine.

Basically, with the padding and margins, it's just going to take some playtime. If you're not worried about IE displaying the margins perfectly, then I would go ahead and use "display:table" for the #box div, and use "display:table-cell; vertical-align:middle" (or whatever margins you want) for the image and text link (and select) items. But remember, IE will ignore it. There *are* ways to do it though - if you google for "vertical alignment CSS", look down about 5 links to the site "jakpsatweb.cz", and you'll see the best tutorial I've seen so far on vertical aligment of things (making it look like IE accepts the "diplay:table" call). To get it to work in something as small as you've got, it takes seom tweaking, but I've used that tutorial a *lot* to get it done when I really need it.

This 41 message thread spans 2 pages: 41