Responsive 2-Column CSS Layout Including Sidebar with Fixed Width

Responsive 2-column CSS layout including sidebar with fixed width?

I think the approach with all those position: absolute is not the best one.

  1. You want to have a container element with a max-width and margin: 0 auto. Not sure why you might want a min-width as well; you can of course.

  2. Any block element that you put automatically takes all the width of the parent element. Hence, there's no problem with the header and footer, just position them in the right spot and they will render properly.

  3. As you correctly did, use a container element for your main section. Since the elements are rendered left to right, you might want to write the aside before the #primary.

  4. Apply float: left to the aside with your desired fixed-width.

  5. The main content #primary element will take the remaining space automatically (or just apply width: auto. Note: the remaining space is the remaining space of the parent element, so, if you set the min-width on the parent element, don't expect your #primary to be narrower!

  6. Now you will have a problem: the container element #main will not get the proper height. That's because of an issue with float. To force a parent element to get to the height of its floated children, use overflow: hidden.

You should be ready to go. Here is a slightly modified version of your code.

Two column layout, fixed right column

Not a very elegant solution, but its working. They key is to wrap the contents of the left column and add a margin-right equal to the width of the right column / sidebar. On the right column, set the width and a negative margin-left equal to its width.

.left {
float:left;
width:100%;
background-color: green;
}
.left-content {
margin-right:120px;
}
.right {
float:right;
width: 120px;
margin-left: -120px;
background-color: red;
}

Here's a working fiddle
http://jsfiddle.net/heyapo/9Z363/

2 column div layout: right column with fixed width, left fluid

Remove the float on the left column.

At the HTML code, the right column needs to come before the left one.

If the right has a float (and a width), and if the left column doesn't have a width and no float, it will be flexible :)

Also apply an overflow: hidden and some height (can be auto) to the outer div, so that it surrounds both inner divs.

Finally, at the left column, add a width: auto and overflow: hidden, this makes the left column independent from the right one (for example, if you resized the browser window, and the right column touched the left one, without these properties, the left column would run arround the right one, with this properties it remains in its space).

Example HTML:

<div class="container">
<div class="right">
right content fixed width
</div>
<div class="left">
left content flexible width
</div>
</div>

CSS:

.container {
height: auto;
overflow: hidden;
}

.right {
width: 180px;
float: right;
background: #aafed6;
}

.left {
float: none; /* not needed, just for clarification */
background: #e8f6fe;
/* the next props are meant to keep this block independent from the other floated one */
width: auto;
overflow: hidden;
}​​

Example here: http://jsfiddle.net/jackJoe/fxWg7/

Responsive 2-column layout trouble

The simple answer to your question is no. You can't make your sidebar move beneath the content in your breakpoint if the sidebar falls before the content area in your HTML. At least... Not without javascript and a bunch of craziness.

That said... Just move your sidebar below your main-content div. Semantically there is no reason for you not to.

<section class="container">
<div class="main-area">main content</div>
<div class="sidebar">sidebar</div>
</section>

Some CSS changes are required to achieve this however. It's not quite as simply done as you had it previously, but not especially difficult either.

.container {
position: relative;
}

.sidebar {
position: absolute;
top: 0;
right: 0;
width: 250px;
}
.main-area {
background: red;
margin-right: 250px;
}

Here is a JSFiddle demonstrating it working.

Feel free to add varying amounts of content to either the main-content area or the sidebar and you'll see that both still have varying heights that don't interfere with each other.

2 column layout (Left column fixed width, right fluid + clear:both)

Here's your altered CSS:

html, body {
background: #ccc;
}

.wrap {
margin: 20px;
padding: 20px;
padding-right:240px;
background: #fff;
overflow:hidden;
}

.main {
margin: 0 -220px 0 auto;
width: 100%;
float:right;
}

.sidebar {
width: 200px;
float: left;
height: 200px;
}

.main, .sidebar {
background: #eee; min-height: 100px;
}

.clear { clear:both; }
span { background: yellow }

Basically what I've done is change the way your layout is done, so that .main div is floated on the right. To do this, we had to add 2 things:

  1. A padding of 240px on the .wrap div, and
  2. A right margin on the .main div of -220px to properly align the fluid part of the page.

Because we've floated the .main div on the right, the clear: both; now only affects content inside the .main div, as you want.

You can see a demonstration here: http://jsfiddle.net/6d2qF/1/

Creating a fixed width sidebar with a responsive container for content next to it in CSS

You can accomplish this using the CSS calc function. For example:

.parent {
width: -webkit-calc(100% - 200px);
width: calc(100% - 200px);
}

See updated fiddle.

calc support.

If you don't want to use calc it can be accomplished with padding, although there are some considerations if you want to use this method. See fiddle.

Twitter Bootstrap Two Column Responsive Layout - Sidebar 100% height with fixed width

Check this out.

<div class="row">
<div class="span3" style="position:fixed;background-color:#46a546;height:100%;top:0px;" id="leftmargin">
position fixed navbar (out of .container)
</div>
</div>
<div class="container">
<div class="row">
<div class="span9 offset3" style="background-color:#049cdb;">
bla bla bla<br>bla bla bla<br>bla bla bla<br>bla bla bla<br>bla bla bla<br>
bla bla bla<br>bla bla bla<br>bla bla bla<br>bla bla bla<br>bla bla bla<br>
bla bla bla<br>bla bla bla<br>bla bla bla<br>bla bla bla<br>bla bla bla<br>
bla bla bla<br>bla bla bla<br>bla bla bla<br>bla bla bla<br>bla bla bla<br>
bla bla bla<br>bla bla bla<br>bla bla bla<br>bla bla bla<br>bla bla bla<br>
bla bla bla<br>bla bla bla<br>bla bla bla<br>bla bla bla<br>bla bla bla<br>
</div>
</div>
</div>

And a bit of jQuery

function sizing() {
var windowwidth=$(window).width();
var containerwidth=$('.container').width();
if(windowwidth<1200) {
var diff=windowwidth-containerwidth+40;
}
else {
var diff=windowwidth-containerwidth+60;
}
$('#leftmargin').text("window="+ windowwidth+",container="+containerwidth);
if(windowwidth<=767) {
$('#leftmargin').css('margin-left', '0px');
$('#leftmargin').css('position', 'relative');
}
else {
$('#leftmargin').css('position', 'fixed');
if(diff>0) {
$('#leftmargin').css('margin-left', (diff/2) +'px');
} else {
$('#leftmargin').css('margin-left', '20px');
}
}
}
$(document).ready(sizing);
$(window).resize(sizing);

http://jsfiddle.net/NzqfL/3/

inspired by my previous post https://stackoverflow.com/a/10972425/1416911

How to build a 2 Column (Fixed - Fluid) Layout with Twitter Bootstrap?

- Another Update -

Since Twitter Bootstrap version 2.0 - which saw the removal of the .container-fluid class - it has not been possible to implement a two column fixed-fluid layout using just the bootstrap classes - however I have updated my answer to include some small CSS changes that can be made in your own CSS code that will make this possible

It is possible to implement a fixed-fluid structure using the CSS found below and slightly modified HTML code taken from the Twitter Bootstrap Scaffolding : layouts documentation page:

HTML

<div class="container-fluid fill">
<div class="row-fluid">
<div class="fixed"> <!-- we want this div to be fixed width -->
...
</div>
<div class="hero-unit filler"> <!-- we have removed spanX class -->
...
</div>
</div>
</div>

CSS


/* CSS for fixed-fluid layout */

.fixed {
width: 150px; /* the fixed width required */
float: left;
}

.fixed + div {
margin-left: 150px; /* must match the fixed width in the .fixed class */
overflow: hidden;
}

/* CSS to ensure sidebar and content are same height (optional) */

html, body {
height: 100%;
}

.fill {
min-height: 100%;
position: relative;
}

.filler:after{
background-color:inherit;
bottom: 0;
content: "";
height: auto;
min-height: 100%;
left: 0;
margin:inherit;
right: 0;
position: absolute;
top: 0;
width: inherit;
z-index: -1;
}

I have kept the answer below - even though the edit to support 2.0 made it a fluid-fluid solution - as it explains the concepts behind making the sidebar and content the same height (a significant part of the askers question as identified in the comments)



Important

Answer below is fluid-fluid

Update
As pointed out by @JasonCapriotti in the comments, the original answer to this question (created for v1.0) did not work in Bootstrap 2.0. For this reason, I have updated the answer to support Bootstrap 2.0

To ensure that the main content fills at least 100% of the screen height, we need to set the height of the html and body to 100% and create a new css class called .fill which has a minimum-height of 100%:

html, body {
height: 100%;
}

.fill {
min-height: 100%;
}

We can then add the .fill class to any element that we need to take up 100% of the sceen height. In this case we add it to the first div:

<div class="container-fluid fill">
...
</div>

To ensure that the Sidebar and the Content columns have the same height is very difficult and unnecessary. Instead we can use the ::after pseudo selector to add a filler element that will give the illusion that the two columns have the same height:

.filler::after {
background-color: inherit;
bottom: 0;
content: "";
right: 0;
position: absolute;
top: 0;
width: inherit;
z-index: -1;
}

To make sure that the .filler element is positioned relatively to the .fill element we need to add position: relative to .fill:

.fill { 
min-height: 100%;
position: relative;
}

And finally add the .filler style to the HTML:

HTML

<div class="container-fluid fill">
<div class="row-fluid">
<div class="span3">
...
</div>
<div class="span9 hero-unit filler">
...
</div>
</div>
</div>

Notes

  • If you need the element on the left of the page to be the filler then you need to change right: 0 to left: 0.


Related Topics



Leave a reply



Submit