0

I have been told several times that I shouldn't be using tables for layout design but I constantly find myself going back to them when I can't figure out how to do something.

I need to create a two column layout. The left column is 300px width and the right column takes up the rest of the width on the page. I can't figure out how to properly do this with plain HTML and I can't even quite figure out how to do it with a table either.

In order to have the right column take up the rest of the width it seems that I would need to specify the left column's width with a percentage so that the right column's width can be 100% less the percentage of the left column. But I need the left column to be 300px exactly.

The only thing I can think to do is calculate the right column's width at runtime with JS. Any ideas how I can accomplish this without tables and/or without Javascript?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
CatDadCode
  • 58,507
  • 61
  • 212
  • 318
  • 2
    My go-to in the past: http://matthewjamestaylor.com/blog/ultimate-multi-column-liquid-layouts-em-and-pixel-widths – Matt Ball Jan 31 '13 at 21:02
  • 2
    You shouldn't be using tables for layout design – Madbreaks Jan 31 '13 at 21:02
  • 3
    @Madbreaks thank you for this valuable information... care to explain rather than repeat what I've obviously already been told? – CatDadCode Jan 31 '13 at 21:03
  • Have you tried CSS float? – Aaron Kurtzhals Jan 31 '13 at 21:04
  • @AlexFord I did provide an answer. No offense intended, just wanted to reiterate that which you already know to be correct. ;) – Madbreaks Jan 31 '13 at 21:14
  • I appreciate it, but until someone explains to my why I shouldn't be using tables with some tangible reasons then I don't _already know it to be correct_. I just know that's what people keep telling me. – CatDadCode Jan 31 '13 at 21:15
  • 1
    @AlexFord It is much easier to create fluid layouts with tables. The two problems with using tables is the fact that it's not semantic (tables should contain data), and that it adds bloat to the HTML. However, with CSS 3, you can use regular divs and make them behave like table cells http://www.onenaught.com/posts/201/use-css-displaytable-for-layout If you can't rely on CSS 3 you're going to have to fight your way through floats and margins and a less bloat then tables, but it'll be semantic HTML, or you can just http://giveupandusetables.com/ – Ruan Mendes Jan 31 '13 at 21:22
  • percentages are really the best solution, even though it is initially harder to work with them...You should look at using percentages and em's more because that is the future and they both work as a standard already. – Ilan Biala Jan 31 '13 at 21:31
  • I've used percentages a lot and it's usually fine, but in my specific case I am mandated that the left column be 300 pixels. No more, no less. – CatDadCode Jan 31 '13 at 21:32

4 Answers4

2

Columns are pretty straight forward with floats. The difficulty lies in having the parent container clear the floated children.

HTML:
<div class="container">
  <div class="column column-a">
    ...
  </div>
  <div class="column column-b">
    ...
  </div>
</div>
CSS:
.container {
  background-color: red;
  color: white;
  width: 520px;
  zoom: 1;
}
.container:before,
.container:after {
  content: '';
  display: table;
}
.container:after {
  clear: both;
}
.column-a {
  background-color: blue;
  float: left;
  width: 300px;
}
.column-b {
  background-color: green;
  float: right;
  width: 200px;
}

You should note that the shorter of the two columns will not extend to the bottom of the container. Typically the background of both columns is repeated vertically on the containing element.

If you need to pad the columns, I typically add div.inner elements within each .column element, but if you want to avoid "divitis", you can simply add:

.column {
    box-sizing: border-box;
    padding: 20px;
}

For fluid-width columns, all you have to do is make sure your widths add up to 100%:

.column-a {
    width: 80%;
}
.column-b {
    width: 20%;
}
Community
  • 1
  • 1
zzzzBov
  • 174,988
  • 54
  • 320
  • 367
  • Great answer, though "straightforward" isn't the word choice I would exactly use :P – CatDadCode Jan 31 '13 at 22:39
  • You could also use `overflow: auto;` on the container to size it to it's floated children. It is a bit less hacky. http://codepen.io/anon/pen/aizrB. Good solution! – Jan Jan 31 '13 at 22:49
  • @AlexFord, the complicated part is the clearfix, and if you're using a CSS preprocessor (I'm using LESS in the linked example) you can abstract it into a simple mixin. The advantage over positioning is that subsequent content can be placed after the container in a reasonable manner. Someday in the future, flexbox will hopefully be finalized and supported, and all of these ridiculous answers will be made obsolete. – zzzzBov Feb 01 '13 at 00:30
  • 1
    This doesn't work in the example the OP posted, that is the right column has to take up the remaining space. – Ruan Mendes Feb 01 '13 at 00:48
  • @JuanMendes, ok, [so don't float the right column, and instead give it some static left padding](http://codepen.io/zzzzBov/pen/LevIg), happy now? – zzzzBov Feb 01 '13 at 02:17
  • 1
    @zzzzBov Yes, happy now! You get my upvote, shouldn't you add that to the answer since that was what the OP was asking? – Ruan Mendes Feb 01 '13 at 02:44
1

<div> elements fundamentally fill their container's width, or what remains of it. So if you have a 300px wide div, then a div next to it with no width specified, the 2nd div will fill the rest of the container.

Madbreaks
  • 19,094
  • 7
  • 58
  • 72
  • I've tried that. Once the two divs are floating left they no longer take up the width of their container, rather they are wide enough to fit their content only. – CatDadCode Jan 31 '13 at 21:06
  • Sometimes when I do that it influences potential answerers to focus on the little code snippet rather than provide me their favorite solutions to solve the central problem. That is why I did not include it. I apologize. – CatDadCode Jan 31 '13 at 21:09
  • I can understand that, but you don't want to waste peoples' time having them type up something you've already tried w/o know that you've tried it. Won't gain you any up-votes anyway. Anyway, no worries! – Madbreaks Jan 31 '13 at 21:16
  • I guess I just figured that my attempt at floats was a pretty noobish attempt and that it was useless to others who I assumed would know better. lol, I guess it's good to know I'm not too far off from what others would try. – CatDadCode Jan 31 '13 at 21:18
1

Until we have flexbox layout I would use absolute positioning:

Html:

<div id="container">
    <div id="left">left one</div>
    <div id="right">right one</div>
</div>

CSS:

#container {
    position: relative;
    height: 150px;
}

#left, #right {
    position: absolute;
    top: 0px; 
    bottom: 0px;
}

#left {
    left: 0px; 
    width: 300px;
    background: red;
}

#right {
    left: 300px; 
    right: 0px;    
    background: green;
}

jsfiddle

There are alternatives if you want the layout to adapt to the content instead of the container. If your right column has more content you could use:

#container {
    position: relative;
}

#left {
    position: absolute;
    left: 0px; 
    width: 300px;
    top: 0px; bottom: 0px;
    background: red;
}

#right {
    margin-left : 300px; 
    background: green;
}

jsfiddle

If your left column has more content, use:

#container {
    position: relative;
}

#left {
    width: 300px;
    background: red;
}

#right {
    position: absolute;
    left: 300px; 
    right: 0px;
    top: 0px; bottom: 0px;
    background: green;
}

jsfiddle

Jan
  • 8,011
  • 3
  • 38
  • 60
  • 2
    This does accomplish my needs. Can someone explain why it has 2 downvotes? – CatDadCode Jan 31 '13 at 21:10
  • I take it back. http://codepen.io/Chevex/pen/hCrot. Same problem as the floats. Once absolutely positioned the right column no longer takes up the remaining space, it is only as wide as its content. – CatDadCode Jan 31 '13 at 21:22
  • 2
    add `right: 0px` to the right column. All properties I added in my example are there for a reason. http://codepen.io/anon/pen/jAeux – Jan Jan 31 '13 at 21:24
  • 2
    @AlexFord Because absolute positioning should only be used when absolutely necessary (no pun intended). It comes with potential maintenance issues and side-effects. – Shmiddty Jan 31 '13 at 21:27
  • 2
    @Shmiddty: So does laying this out with floats. This is just an unnatural layout for current CSS which is designed to layout documents, not apps. Every app layout is a hack and comes with tradeoffs. The only way to do this right is using `flexbox`. But it isn't widely supported yet. – Jan Jan 31 '13 at 21:33
  • I like this better than floats. Every time I use floats it feels wonky. – CatDadCode Jan 31 '13 at 21:53
  • 1
    Absolute positioning is a good way to quickly ruin page flow and automatic sizing. Using it for columns is a poor choice. Use flexbox or floating, but not absolute positioning. Good luck trying to get a sticky footer without JavaScript. – zzzzBov Jan 31 '13 at 22:01
  • @zzzzBov What is so hard about it? It's fine if you understand its ramifications, here's a very simple example of the same code, plus a header and a footer http://jsfiddle.net/V4etF/8/ You just have to understand that something that is absolute is not in the flow of the document. Sure it can get tricky if try you do too much, yes it makes it easier to do some things, but it's also a lot easier to do other things with absolute positioning. This answer deserves more upvotes, it's simple and works! – Ruan Mendes Feb 01 '13 at 00:41
  • @JuanMendes, that's not a [sticky footer](http://stackoverflow.com/questions/12239166/footer-at-bottom-of-page-or-content-whichever-is-lower/12253099#12253099), that's a fixed footer. – zzzzBov Feb 01 '13 at 00:46
  • @zzzzBov Learning a bunch from you today, I wasn't aware of what the term sticky footer meant. – Ruan Mendes Feb 01 '13 at 02:47
0

Set the left column to 300px, set the right column to 100%... done. To avoid any cross browser weirdness, follow Matt Ball's link to... http://matthewjamestaylor.com/blog/ultimate-2-column-left-menu-pixels.htm . He is using a mysterious 2nd wrapper that I'd deem unnecessary, but baby steps :)

Once you're in the wrapper, to get the column heights = you need to set min-height to 100% I believe. You can adjust the overflow css property to deal with any text overflows. Pretty straight forward stuff, I remember having a hell of a time finding how to do equal columns, the wrapper is the key. Also, don't use JS for this, people who use JS are either doing something more advanced, or are completely new to html/css.

RandomUs1r
  • 4,010
  • 1
  • 24
  • 44
  • Nope. Setting the right column to 100% makes it take up 100% of it's container (the page) so it's width becomes the width of the page, which means that it bleeds to the right by 300px. Or in the case of the floating elements, it drops down below the first one. http://codepen.io/Chevex/pen/JDLBc – CatDadCode Jan 31 '13 at 21:14