Skip to main content
GameDev.net gamedev.net
🔒 Locked

[web] CSS *can* do this, right?

Started by Zahlman Jul 30, 2009 at 11:59 PM 8 replies 2.9k views
Original Post
Zahlman
Zahlman
I have a test layout as follows:

<body>
	<table style='position: fixed; left: 0px; top: 0px; width: 100%; height: 20px; border-collapse: collapse; table-layout: fixed'>
		<td style='display:table-cell; width: 100px; background-color: green'></td>
		<td style='display:table-cell; width: auto; background-color: black'></td>
		<td style='display:table-cell; width: 100px; background-color: green'></td>
		<td style='display:table-cell; width: auto; background-color: black'></td>
		<td style='display:table-cell; width: 100px; background-color: green'></td>
		<td style='display:table-cell; width: auto; background-color: black'></td>
		<td style='display:table-cell; width: 100px; background-color: green'></td>
		<td style='display:table-cell; width: auto; background-color: black'></td>
		<td style='display:table-cell; width: 100px; background-color: green'></td>
	</table>
</body>

As you can see, the net effect is that the table fills the screen width, placing 5 green rectangles of 100px each with equal spacing, such that one green rectangle is in the extreme top-left and another is in the extreme top-right. The question: how can I get this sort of effect without a table? I've tried every combination of div and span arrangements I can think of, with all sorts of display: properties. Everything either fails to fill the screen width (typically by making the "spacers" collapse - sometimes putting inexplicable padding between "cells" - and sometimes collapsing the 100px elements too!), or fails to put everything in one row (i.e. the "spacers" are assigned 100% of screen width and therefore have to go on a line by themselves, so every element ends up on its own row). But my content data isn't logically tabular, so I don't want to use the table. (In the real page, the content will probably go into a parent div with a set pixel size anyway, so I could hard-code everything, but I really don't want to - especially as that involves recalculating everything, or perhaps doing painful things with &#106avascript, if I decide to change the size.)
Codeka
Codeka
You might be able to do it with appropriately nested
s and display: table, but if you're going to do that, you may as well just stick with using a table...

Edit: this seems to work (but I would argue the table-based layout is better, because it's obvious what you're trying to do):
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"><html><head>	<style type="text/css">		div.menu {			width: 100%;			display: table;			height: 20px;		}				div.menu div {			display: table-row;		}				div.menu div div.green {			width: 100px;			display: table-cell;			background: green;		}				div.menu div div.black {			width: auto;			display: table-cell;			background: black;	</style></head><body>	</body></html>
Sander
Sander
What are you trying to display Zahlman? If it's table-based data, just use a table.
ToohrVyk
ToohrVyk
A very interesting problem [smile]

I can only see two things in the CSS 2.1 specification that can lead to this kind of even spacing : table cells and justified text alignment. Everything else evaluates width and position properties individually, which makes the even spacing impossible.

Going with justified text alignment, let's construct the following:
<ul>  <li>A</li><li>B</li><li>C</li><li>D</li><li>E</li>  <li class="spacer"></li></ul>
Then, I make the enclosing "ul" a normal block with justified text alignment:
ul{text-align:justify}
And I turn the "li" into inline blocks (they look inline from the outside and like blocks from the inside):
li{width:100px;display:inline-block;background-color:green}
And finally, since a line box is only justified if it is not the last one, I make the spacer too long to stay on its own line and hide it so that it doesn't do anything:
li.spacer{width:100%;height:0px;visibility:hidden}


This should space out the five lettered boxes evenly within the bounds of the
    element. However, there are some problems:
    • You have to handle the line height and vertical alignment for the line box created by the inline flow.
    • Internet Explorer does not seem to like this too well.


    In the end, I would probably suggest instead to rename "style.css" to "style.php" and write:

    li.spacer{width:<?=(TOTAL_WIDTH - NUM_BLOCKS * BLOCK_WIDTH) / (NUM_BLOCKS-1)?>px}
Zahlman
Zahlman
Quote:
Original post by Sander
What are you trying to display Zahlman? If it's table-based data, just use a table.


Because of an NDA I can't say what it's actually for (or I would have to begin with), but let's say for the sake of argument that I have a bunch of equal-sized photo thumbnails, and I want to display them in a grid in a containing div such that there is equal space between them. :)

Codeka: I could have sworn that I tried that approach, but now it's working, and I've apparently thrown away my test files so I can't see where I'd messed it up before. :( I think it was because of not having 'display: table' applied to the outer div. For some reason, this is necessary, but the inner 'display: table-row' div seems not to be?! Or is that browser-specific?

The same technique, applied vertically, only appears to work if each cell has non-zero-size contents. I don't really want anything in my vertical spacers but I guess I could always just put   or something. :/

ToohrVyk: Doesn't work for me. There's no space at all between the green blocks that way. I really am tempted to just do the calculation in code, though. :) Was just hoping for a way that didn't depend on a fixed-size containing div. (I suppose one could do something in &#106avascript to update the DOM when the window size changes, but... ugh.)
Sik_the_hedgehog
Sik_the_hedgehog
Quote:
Original post by Codeka
You might be able to do it with appropriately nested
s and display: table, but if you're going to do that, you may as well just stick with using a table...
From a visually enabled user viewpoint it may look like a table, but using a table when there isn't tabular data could make things hard for people who is relying in a speech program or something, or for search engines which wouldn't be able to figure out that the data isn't tabular at all.

So yeah, stay away from if it isn't tabular data.

Quote:
Original post by ToohrVyk
A very interesting problem [smile]

I can only see two things in the CSS 2.1 specification that can lead to this kind of even spacing : table cells and justified text alignment. Everything else evaluates width and position properties individually, which makes the even spacing impossible.

And I thought it was just me... No wonder CSS hates me quite often =|
Don't pay much attention to "the hedgehog" in my nick, it's just because "Sik" was already taken =/ By the way, Sik is pronounced like seek, not like sick.
Zahlman
Zahlman
Quote:
Original post by Sik_the_hedgehog
From a visually enabled user viewpoint it may look like a table, but using a table when there isn't tabular data could make things hard for people who is relying in a speech program or something, or for search engines which wouldn't be able to figure out that the data isn't tabular at all.

So yeah, stay away from if it isn't tabular data.


I don't actually have to worry about that for my particular situation, but I'd rather "do it right" anyway :)

Quote:
And I thought it was just me... No wonder CSS hates me quite often =|


Worse than that, there is apparently *no* way to do *arbitrary* spacing - although you can approximate it well enough with rational fractions (using several 'auto' spacers in each spot where space is needed, in the appropriate ratio)... ugh :(
Alpha_ProgDes
Alpha_ProgDes
Quote:
Original post by DarkHorizon
Use &#106avascript to calculate the size values and generate the CSS. It's not as difficult as it sounds.<!--QUOTE--></td></tr></table></BLOCKQUOTE><!--/QUOTE--><!--ENDQUOTE--><br>Yeah, if you're thoroughly familiar with &#106avascript and CSS, that is. [smile]</td></tr></table></blockquote>
Beginner in Game Development?  Read here. And read here.  
btower
btower
I'd do it like this. In my experience, display: table doesn't work too well in IE. float works in all the major browsers.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"><html><head>	<style type="text/css">		div.menu {			width: 500px;			clear: both;		}		div.menu div.block {			width: 100px;			height: 100px;			float: left;		}		div.menu div.green {			background: green;		}		div.menu div.black {			background: black;		}	</style></head><body>	</body></html>

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.