Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Make a div containing CSS columns have unlimited width

Imagine a very common <header><article><footer> layout, where the header and footer are fixed heights and the article gets as tall as needed (the page scrolls vertically to accommodate). That's like most web pages.

What I'm trying to get is a layout just like that, but on its side so the article gets as wide as needed, and the page scrolls horizontally:

Horizontal scrolling

My initial attempts used flexbox:

Here is my first attempt on jsFiddle.

Relevant CSS:

body {
    display: flex;
    position: absolute;
    height: 100%;
}
header {
    background: green;
    width: 400px;
    flex: none;
}
article {
    background: #CCC;
    -webkit-columns: 235px auto;
    columns: 235px auto;
    -webkit-column-gap: 0;
    column-gap: 0;
}
footer {
    background: yellow;
    width: 450px;
    flex: none;
}

But I'm moving away from that as I try other things, like in this fiddle, which is a little closer. The problem with this attempt is that the article width is constrained to 100% of the viewport width, even though the text flows over to the right! (My article uses CSS columns which is absolutely important to my layout.)

My requirements are:

  • Header, Article, Footer to be 100% height (done)
  • Header to be 400px wide (done) and to left of content (done)
  • Footer to be 450px wide (done) and to right of the article (how?)
  • Article to be as wide as it needs to be without overlapping footer (how?)

So, I need help with the bolded goals. What can I do to keep the article from overlapping the footer to its right? Are there other ways to lay out this page so that the article width expands as the content does?

  • Should work in Chrome, Firefox, and Safari (IE and Opera a plus, but not necessary)
  • Preferably no JavaScript (or CSS features likely to be dropped from the spec)
  • Simple, clean CSS is ideal
like image 901
Matt Avatar asked Dec 29 '14 19:12

Matt


People also ask

How do you make a div full width in CSS?

The width property is used to fill a div remaining horizontal space using CSS. By setting the width to 100% it takes the whole width available of its parent. Example 1: This example use width property to fill the horizontal space. It set width to 100% to fill it completely.

How do I span all columns in CSS?

Assign column-span to an element inside of the multi-column layout to make it a spanning element. The multi-column layout will resume with the next non-spanning element. The value of column-span can either be all or none . Set an element with column-span: all to make it span the columns.

Can a div have a width?

This seems like the ideal candidate for transition from a table-based layout to a CSS layout. It makes sense: both DIVs and tables can be nested, have HEIGHT and WIDTH attributes set, contain borders, etc.


1 Answers

I've been working on this all afternoon and without JS it seems pretty impossible. I've also fiddled with @Grily's solution and I think I nailed it in Chrome at least.

Solution 1 Works on Firefox, Chrome and IE

However I got this to work, sort of. It's not completely to spec.

HTML

<div id="DIV-1">Header </div>
        .. in the Fiddle there's a lot of "Lorum ipsum here"
<div id="DIV-3">Footer </div>

CSS

@media only screen 
and (orientation : landscape) {

    body {
        position: absolute;
        display: block;
        box-sizing: border-box;
        white-space: normal;
        -webkit-columns: 235px auto;
        -moz-columns: 235px auto;
        columns: 235px auto;
        -webkit-column-gap: 0;
        -moz-column-gap: 0;
        column-gap: 0;
        height: 100%;
        float: left;
        width: calc(100% + 450px);
        min-width: -webkit-min-content; 
        padding-left: 400px;
    }

    #DIV-1{
        position: absolute;
        left: 0px;
        box-sizing: border-box;
        background-color: #2693FF;
        height: 100%;
        width: 400px;
        float: left;
    }

    #DIV-3 {
        position: relative;
        float: right;
        left: 205px;
        box-sizing: border-box;
        background-color: #FF7373;
        height: 100%;
        width: 450px;
        -webkit-column-span: all;
        -moz-column-span: all;
        column-span: all;

        -webkit-column-break-inside: avoid;
        page-break-inside: avoid;
        break-inside: avoid;

    }       

}

I've put the content container the columns directly into the body. (Can still be a div).

width: calc(100% + 450px);
min-width: -webkit-min-content; 

This bit actually (by magic) forces the browser to recognize that the body has a width that is broader than the viewport. The positioning of the header is simple. absolute and add padding to the body and it's in place. The content now flows nicely to the right. Exception is the footer. I got it in the right position on it's own by using column-span: all. Firefox is going it's own way with this and actually renders it correctly. Chrome and IE render the column inline and only the width of the column. That's the drawback of this approach.

I hope you can do something with it or somebody else could improve this so it actually appends the footer at the end of the page without shrinking it to the column's width.

The Fiddle: http://jsfiddle.net/5dtq47m3/

Solution 2 - Works on Chrome

Edited the work of Grily.

HTML

<header>
        <h1>Article Title (width 400)</h1>
</header>

<article>
     ........
</article>
<footer>Footer should be 450px wide and appear to the right of everything else.</footer>

CSS

* {
    padding: 0;
    margin: 0;
}
body {
    display: flex;
    position: absolute;
    height: 100%;
}
header {
    background: green;
    width: 400px;
    flex: none;
    float: left;
}
article {
    background: #CCC;
    -webkit-columns: 235px auto;
    columns: 235px auto;
    -webkit-column-gap: 0;
    column-gap: 0;
    color: rgba(0, 0, 0, .75);
    flex:none; /*added*/
    width: calc(100% + 10px); /*added*/
    max-width: -webkit-max-content; /*added*/
}
article p {
    padding: .2em 15px;
    text-indent: 1em;
    hyphens: auto;
}
footer {
    background: yellow;
    width: 450px;
    flex: none;
    float: right; /*added*/
}

http://jsfiddle.net/w4wzf9n6/8/

like image 139
Mouser Avatar answered Sep 21 '22 15:09

Mouser