2

While this question in general is quite common, I haven't found an answer addressing the specific constraints in this version.

I'm looking to implement the holy grail, with one important caveat: The columns must remain in order from left to right, L (left), C (center), R (right), without the use of absolute positioning.

In addition to the above major requirements, compatibility is pretty high on the list; mind you, I'm not trying to support anything ridiculous like IE6; at least IE7 would be preferable. (yes, I think it's ridiculous these days) Given this, the immediately obvious calc() CSS function is not applicable.

Left-to-right ordered columns

In the linked article, A List Apart has implemented this as C-L-R, citing "proper source order", and many have followed this trend arguing benefits of SEO as the main page content appears first in the source order. Also, it works, visually.

Unfortunately, SEO and accessibility are two different beasts. It has been brought to my attention that the majority of web accessibility tools (JAWS, for instance) will understandably read the page content in DOM order; top-down, left-to-right.

Here's some fairly standard L-C-R markup:

<div class="wrapper">
    <div class="container">
        <div class="column-l">
            <div class="cell">Column L</div>
        </div>
        <div class="column-c">
            <div class="cell">Column C</div>
        </div>
        <div class="column-r">
            <div class="cell">Column R</div>
        </div>
    </div>
</div>

And a snippet of CSS to go with it:

.wrapper {
    width: 100%;
}
.container {
    width: 90%;
    margin-left: auto;
    margin-right: auto;
}
.cell {
    padding: 1em;
}

Given the full width .wrapper and the 90%-width margin-centered .container, I'm trying to display .column-l, and .column-r as fixed width (say 300px), with .column-c as fluid.

By giving .column-l a float: left; property, and applying a margin-left of 300px to .column-c, those two columns fall into place:

.column-l {
    width: 300px;
    float: left;
}
.column-c {
    margin-left: 300px;
}

The problem is .column-r. It doesn't want to sit where I want it to. Applying a float: right; to .column-r places it under the other two (mind you, at least it's at the right). This is true even if I apply a margin-right: 300px; to the .column-c.

Charles
  • 50,943
  • 13
  • 104
  • 142
Dan Lugg
  • 20,192
  • 19
  • 110
  • 174

3 Answers3

1
.column-l {
    width: 300px;
    background: red;
    display:table-cell;
}
.column-c {
    background: green;
    display:table-cell;
}
.column-r {
    width: 300px;
    background: blue;
    display:table-cell;
}

Does this help? No floating, left and right have 300px width, center fills the rest, all have the same height.

Sebastian Höffner
  • 1,864
  • 2
  • 26
  • 37
  • I'm tempted to mark this as the answer, however the `display: table-*;` property values aren't supported in IE7 (*and I've noticed weird behavior in IE8*) as per testing and http://caniuse.com/css-table. – Dan Lugg Nov 24 '13 at 22:36
  • Seems I ignore IE completely, I didn't even realize your constraint in the question, sorry. But I will try to figure out a solution. http://stackoverflow.com/a/12320221/3004221 could be a "if nothing else helps do it with dirty table hacks" - solution. But this is not what we want, of course. I was thinking about inline-block structures, but that also is limited for IE/ (http://quirksmode.org/css/css2/display.html) . I also found this nice answer http://stackoverflow.com/questions/7880854/css-table-and-table-cell-replacement-for-ie7 but it doesn't span or grows too large. Will continue – Sebastian Höffner Nov 25 '13 at 00:43
  • http://matthewjamestaylor.com/blog/perfect-3-column-blog-style.htm This is the best I can come up with at the moment. It has the order you use (there is also a "holy grail"-layout, which features the CLR-definition). --- But it also has some drawbacks: `overflow: hidden;` and percentages as sizes. --- So nothing special here, and it doesn't solve your problem with the fixed width. --- I'm sorry, I think it is not possible to make it work in all browsers (or let's say to make it work in IE7 (considering your comment 8?) and below) without some kind of "hack", trick, JS. – Sebastian Höffner Nov 25 '13 at 17:48
1

Set display:table on the container class and display:table-cell; on the columns

FIDDLE

Danield
  • 121,619
  • 37
  • 226
  • 255
  • Thanks @Danield, but refer to my comment on the other answer. – Dan Lugg Nov 24 '13 at 22:36
  • This works great in IE8+ and one can still have a [fixed width layout for IE7 from that code](http://jsfiddle.net/2Kq8p/12/embedded/result/) (here `980 - 300 - 300 = 380px` for C) – FelipeAls Nov 25 '13 at 22:28
1

This is a revised answer. Here's the original.

The following is a rather simple pattern, born out of assistance from folks in chat, and just tinkering for awhile. It meets the requirements described in my question, however it does use a single non-semantic <div> (which is one less than the old answer). Still, IDGAF because it's only occurring once (or a handful of times) on a given page. The non-semantic <div>'s can often be substituted for HTML5 semantic sectioning blocks, so pretty much a non-issue.

The bug described in my original answer, the center column shrinking in absence of content, has been eliminated.

Overview

This solution uses 3 columns, L (left) R (right) and C (center), with L and R being fixed width, and C being fluid.

The core of this solution relies on margins (positive and negative) and the .with-r/.with-l modifier classes.

The .with-l/.with-r modifier classes are applied to the .column-container. These add positive left and right margins respectively, each equal to the left and right columns respectively. (in my example, they're each 240px)

The left and right columns are each assigned their fixed width (again, 240px) as well as a negative margin equal to their width. The left column has the negative margin applied to the left, and the right to the right.

The awesome thing about this solution is, if I want to use a 2 column layout, with only the C and L columns, I just remove the R column and the associated modifier .with-r. Same goes for removing the L column.

JSFiddle

http://jsfiddle.net/5yq7J/ (same as below, just with Lorem Ipsum)

SCSS

/*************************/
/* quick and dirty reset */
/*************************/
* { 
    margin: 0;
    padding: 0;
    outline: 1px dotted #f00; 
}

/*************************/
/* some boilerplate crap */
/*************************/
%block {
    position: relative;
    display: block;
}

%clear {
    &:after {
        @extend %block;
        content: "";
        float: none;
        clear: both;
        width: 100%;
    }
}

%layer {
    @extend %block;
    @extend %clear;
}

/***********************************/
/* all the important stuff follows */
/***********************************/

.container { 
    @extend %layer;
    margin-left: auto;
    margin-right: auto;
    min-width: 960px;
    width: 90%;
}

.column-container {
    @extend %layer;
    &.with-l { margin-left: 240px; }
    &.with-r { margin-right: 240px; }
}

%column { 
    @extend %block;
    float: left; 
}

.column-l {
    @extend %column;
    width: 240px;
    margin-left: -240px;
}

.column-c {
    @extend %column;
    width: 100%;
}

.column-r {
    @extend %column;
    width: 240px;
    margin-right: -240px;
}

.cell { 
    @extend %layer;
    padding: 1em;
}

HTML

<h1>Columns L, C &amp; R</h1>
<div class="container">
    <div class="column-container with-l with-r">
        <div class="column-l">
            <div class="cell">
                <h2>Column L</h2>
                <p>Lorem ipsum dolor...</p>
            </div>
        </div>
        <div class="column-c">
            <div class="cell">
                <h2>Column C</h2>
                <p>Lorem ipsum dolor...</p>
            </div>
        </div>
        <div class="column-r">
            <div class="cell">
                <h2>Column R</h2>
                <p>Lorem ipsum dolor...</p>
            </div>
        </div>
    </div>
</div>

<h1>Columns L &amp; C</h1>
<div class="container">
    <div class="column-container with-l">
        <div class="column-l">
            <div class="cell">
                <h2>Column L</h2>
                <p>Lorem ipsum dolor...</p>
            </div>
        </div>
        <div class="column-c">
            <div class="cell">
                <h2>Column C</h2>
                <p>Lorem ipsum dolor...</p>
            </div>
        </div>
    </div>
</div>

<h1>Columns C &amp; R</h1>
<div class="container">
    <div class="column-container with-r">
        <div class="column-c">
            <div class="cell">
                <h2>Column C</h2>
                <p>Lorem ipsum dolor...</p>
            </div>
        </div>
        <div class="column-r">
            <div class="cell">
                <h2>Column R</h2>
                <p>Lorem ipsum dolor...</p>
            </div>
        </div>
    </div>
</div>

<h1>Column C</h1>
<div class="container">
    <div class="column-container">
        <div class="column-c">
            <div class="cell">
                <h2>Column C</h2>
                <p>Lorem ipsum dolor...</p>
            </div>
        </div>
    </div>
</div>
Community
  • 1
  • 1
Dan Lugg
  • 20,192
  • 19
  • 110
  • 174