tags:

views:

656

answers:

3

I'll ask the basic question first and then go into excruciating detail as to why I'm asking. I have a bunch of similar floated block elements inside a <div> and I've set overflow:auto on the <div> so that its height expands to properly contain all of the elements inside it.

Is there any way, using CSS and HTML only, to set only the first floated element to the full height of the div?

Just to be clear: I want to grow the contained element to the height of the container, not the other way around.

I tried adding

 height: 100%

to the first floated element's CSS, but that has no effect.

On to the excruciating detail. And if a better overall approach comes to mind, which would eliminate this particular problem, I'm all ears.

I'm simulating a table with a bunch of floated <ul> elements inside a <div>. Each list is a column in the "table" and the first list is the row-label column. So, to render the following:

         col A     col B
row 1     foo       baz

row 2     bar       bat

I use this markup:

<div>
    <ul class='row-label'>
        <li>&nbsp;</li> *
        <li>row 1</li>
        <li>row 2</li>
    </ul>
    <ul class='data-col'>
        <li class='data-header'>col A</li>
        <li>foo</li>
        <li>bar</li>
    </ul>
    <ul class='data-col'>
        <li class='data-header'>col B</li>
        <li>baz</li>
        <li>bat</li>
    </ul>
</div>

* there's supposed to be a non-breaking space in the first item of the 'row-label' list but I can't get SO to show &nbsp;

Attentive readers may be wondering "Huh? Why not use a real table?" Two answers:

  • My fake-table approach is much more appropriate, semantically, for my data. The data is more closely related within each "column" than within each "row", but HTML tables assume the opposite. So I would need more complex PHP on the backend to convert the data into HTML tables, and the result wouldn't make as much sense. The "table" here really is more of a visual/presentation effect than anything.

  • I wanted to leave open the ability to manipulate individual columns in JavaScript (show them and hide them in response to user action, with transition effects). From what I could tell when I was researching it, there's no straightforward way to do this in a standard HTML table -- precisely because the row, not the column, is the basic unit of the HTML table. Please shoot me a counter-example if I'm wrong.

The CSS, simplified, looks like this:

div {
    overflow: auto;
}

div ul {
    float: left;
    list-style-type: none;
    padding: 0;
    margin: 0 0.5em;
}

A problem arises when a row has more columns than will fit in the width of the browser window. The columns wrap to the next line and I get this sloppy result:

         col A     col B     col C
row 1     foo       baz       bar

  col D     col E
   zab       oof

Ultimately I have a better solution in mind but the simplest immediate fix is to give the row-label column enough height to push those wrapped columns into line. If I do something like this:

ul.row-label {
     height: [lots of ems]
}

Then I get this result:

         col A     col B     col C
row 1     foo       baz       bar

         col D     col E
          zab       oof

But since there can be more of these simulated tables below the first one, and since there can be any number of rows in each "table", I can't rely on an absolute height.

+1  A: 
jrista
I'm already doing this, as mentioned in OP. It's the *contained* element that I need to grow to the height of the container, not the other way around. Thanks, though.
Ben Dunlap
I've updated my answer to be more relevant. I thought you were posting another very common question, and I read what I've read a thousand times. My apologies.
jrista
No worries, I likewise rephrased the question after I saw how it could easily be read the way you took it at first.
Ben Dunlap
The above example works great in Opera, pretty well in IE7/8...but Firefox is having a height issue with the wrapping div. Its taking up 100% of the height of the viewport...not sure why. Anyway, the above example should work with a few tweaks to fit your needs.
jrista
I'm still not seeing it, though. I want only *one* of the contained "ul" elements -- the first one -- to have a height of 100% of the height of the container. All the rest of the "ul"s need to retain their dynamically rendered height based on their own contents. I tried adding "display:block" and "overflow:hidden" to my first "ul" and "display:block" to its "li" children, but the "height: 100%" still doesn't take effect.
Ben Dunlap
I would need more context and probably exact html+css to help you further. There is probably something else interfering with the height. Do you require IE6 support, or are you able to use the CSS 2.1 and 3 advanced selectors?
jrista
Try adding several more columns to your HTML above. You can just copy the 'col B' ul and paste it a bunch of times. Then load the page in IE 7 and make your window narrower until the row wraps -- you should see what I'm seeing.
Ben Dunlap
Ah! I finally understand your problem...thats a tough one to describe. So you want the row-label to expand to the same height as the corresponding data-col blocks, even if they wrap. Thats a complicated problem, given that your data is primarily organized by column, not row. I'll see what I can figure out...can't guarantee a solution today however.
jrista
"you want the row-label to expand to the same height as the corresponding data-col blocks, even if they wrap" -- actually I think it's simpler than that. I just want the row-label column to expand to the full height of the container div, so that if any rows wrap, the wrapped parts don't intrude into the row-label column. If you look at the last snippet in my original post, you'll see what I'm describing. Or try adding "ul.row-label { height: 200px; }" to the CSS in your sample code above, and then adjust the window width.
Ben Dunlap
Well, I have experimented with this for hours, as it was an intriguing problem. To be quite honest, I don't think there is any way to make it work like you need it to. When there is no direct link between the columns and rows, they just can't be sized synchronously such that they render correctly in all scenarios. What it boils down to is you have tabular data...and you need a table to render it properly. You can still turn columns on and off with a table, it just takes a few lines of JS to do it.
jrista
A: 

Firstly, and as you pointed out, your REALLY SHOULD be using tables for tabular data. You can perform exactly the same manipulations on the elements in a table as you can anywhere else.

I dont know why you would want to do such a crazy thing, but your best bet is to just put the .data-col elements in a separate div, add a left margin, and position them to the left:

EDIT: code added for my sanity

ul, li {
  display: block;
  margin: 0px;
  padding: 0px;
}
ul {
  float: left;
  margin: 0px 5px;
}
li {
  height: 20px;
}
.data-cols {
  left: 0px;
  margin-left: 50px;
  overflow: hidden;
}

<div>
    <ul class='row-label'>
        <li> </li>
        <li>row 1</li>
        <li>row 2</li>
    </ul>
    <div class="data-cols">
        <ul class='data-col'>
            <li class='data-header'>col A</li>
            <li>foo</li>
            <li>bar</li>
        </ul>
        <ul class='data-col'>
            <li class='data-header'>col B</li>
            <li>baz</li>
            <li>bat</li>
        </ul>
    </div>
</div>
Matt
"You can perform exactly the same manipulations...in a table" -- really? Including showing and hiding individual columns in response to user interaction -- possibly with transition effects?
Ben Dunlap
Come to think of it, the other reason I used this markup is that it makes more sense for my data set than a table does -- and, correspondingly, requires much simpler PHP to generate. The "columns" in these tables are much more semantically related than the "rows" -- which is just the opposite of the way HTML tables work.
Ben Dunlap
I've updated my question to reflect this additional reason for avoiding HTML tables. Thanks for prompting me to think it through.
Ben Dunlap
regarding your first statement, you would just need to assign a class to each cell in that column - col-3 for example.
Matt
My solution of placing the .data-col elements in a seperate div will still work, btw.
Matt
re: 'class to each cell' - yeah, I thought of that too and as I remembered it I also remembered my other reason for not using HTML tables.
Ben Dunlap
The separate 'div' is a good workaround but I'm going to leave the question open for a while to see if there's a more direct solution.
Ben Dunlap
A: 

May be this would help with ideas? I just found this css framework myself:

http://www.blueprintcss.org/

Pat