How can we create a 3-column layout, Fluid - Fixed - Fluid, as shown in the picture below. Is there more than one option? If so, what are the pros and cons of each?
Note: Feel free to add more answers if they are different to the three I've already posted. Also, I know this has been asked before, but I can't find anywhere with all three answers that is up to date.
Options
There are three four ways of doing this, all using different CSS and having different levels of complexity and browser compatibility. In all three four, we start with three divs which create our three columns.
Method 1 - Most compatible, longest code.
Method 2 - Medium compatible, medium code.
Method 3 - Least compatible, shortest code.
All three four will produce what we want, as shown in the screenshot below:
EDIT:
There is a Method 4, suggested by vals, which uses the CSS Flexbox Model. See his answer for details.
Method 1 - Extra Inner div
Insert an extra div inside the left and right fluid columns.
Pros: This method has the best compatibility, even back to IE6.
Cons: We have to insert an extra div, and the CSS is the longest of all three methods.
Working Fiddle
HTML:
<div class="wrap">
<div class="fluid left">
<div class="inner">
Fluid Box
</div>
</div>
<div class="fixed">
Fixed Box
</div>
<div class="fluid right">
<div class="inner">
Fluid Box
</div>
</div>
</div>
CSS:
.wrap {
overflow:hidden;
}
.wrap div {
height:300px;
float:left;
}
.fixed {
background-color:lightblue;
width:500px;
}
.fluid {
background-color:orange;
width:50%;
}
.left {
margin-left:-250px;
}
.left .inner {
margin-left:250px;
}
.right {
margin-right:-250px;
}
.right .inner {
margin-right:250px;
}
Method 2 - Use box-sizing CSS Styling
If you are willing to use some CSS3, you can set the left and right fluid columns to have box-sizing:border-box;. This lets use take the margin from the Method 1's inner divs, and place it as padding in the outer divs, without interfering with their widths. box-sizing isn't supported by all older browsers though.
Pros: The code is cleaner, because we don't have an extra inner div. The CSS is slightly cleaner as well.
Cons: Browser compatibility. We are going to lose IE6 and IE7.
Working Fiddle
HTML:
<div class="wrap">
<div class="fluid left">
Fluid Box
</div>
<div class="fixed">
Fixed Box
</div>
<div class="fluid right">
Fluid Box
</div>
</div>
CSS:
.wrap {
overflow:hidden;
}
.wrap div {
height:300px;
float:left;
}
.fixed {
background-color:lightblue;
width:500px;
}
.fluid {
background-color:orange;
width:50%;
-webkit-box-sizing:border-box;
-moz-box-sizing:border-box;
box-sizing:border-box;
}
.left {
margin-left:-250px;
padding-left:250px;
}
.right {
margin-right:-250px;
padding-right:250px;
}
Method 3 - Use calc() for width
Following the trend, we can use a method which involves even newer CSS, for even cleaner but less backward-compatible code. If we calculate the width of the left and right fluid columns using width:calc(% - px), we don't need box-sizing, or extra divs.
Pros: The CSS is even cleaner and shorter than in method 2.
Cons: Browser compatibility. Not only do we lose older versions of IE, we lose all but the very newest versions of most mobile browsers..
Working Fiddle
HTML:
<div class="wrap">
<div class="fluid">
Fluid Box
</div>
<div class="fixed">
Fixed Box
</div>
<div class="fluid">
Fluid Box
</div>
</div>
CSS:
.wrap div {
height:300px;
float:left;
}
.fixed {
background-color:lightblue;
width:500px;
}
.fluid {
background-color:orange;
width:-webkit-calc(50% - 250px);
width:-moz-calc(50% - 250px);
width:calc(50% - 250px);
}
Summary
Method 1 - Most compatible, longest code.
Method 2 - Medium compatible, medium code.
Method 3 - Least compatible, shortest code.
Method 4 - Flex Model
Similar to Method 3 in AndyM's post, this method relies on CSS3 and will only work in modern browsers. However, as it's name would suggest, it's flexible, and easy to implement. We use three new CSS properties: display:flex; flex-grow:;, and flex-basis:;.
We add the first to #wrap, which tells the browser that the items inside are going to be laid out using the flex model. The second two tell the browser whether or not an item will grow (is flexible), and what is the initial width.
Pros: The CSS is clean and short, and very easy to change later. Unlike Method 2 & 3, the fixed width only needs to be declared once.
Cons: Browser compatibility. This has just slightly better compatibility than calc(), but not by much. We can use it now, but we lose basically all but the newest versions of most mobile browsers, and of Internet Explorer.
Working Fiddle
HTML:
<div class="wrap">
<div class="fluid">
Fluid Box
</div>
<div class="fixed">
Fixed Box
</div>
<div class="fluid">
Fluid Box
</div>
</div>
CSS:
.wrap {
display: flex;
height:300px;
}
.fixed {
background-color:lightblue;
flex-grow: 0; /* Does this box grow? 0 means no. */
flex-basis: 500px;
}
.fluid {
background-color:orange;
flex-grow: 1;
flex-basis: 0px;
}
I've edited this to make the example as close as possible to the examples in Methods 1-3, for easier comparison of the methods. All kudos to vals for the initial post, I had never heard of this method. - AndyM
Original Fiddle
Related
What I am trying to do is create 2 or more text boxes, side by side rather than stacked vertically.
I have tried using floats, which is fine for 2 boxes side by side, but isn't good for 3. Also, floats make the page look messy on mobile.
Is there any other way to do this?
You can use the CSS property display: inline-block but you should also use Media Queries to adjust the width of the inline boxes depending on the screen size of the device reading the page.
You can also use a framework such as Twitter Bootstrap which has a build in responsive framework based on a grid system.
.box-container{
display:inline-block;
width:450px;
}
.box{
display:block;
width:33%;
float:left;
background:#000;
color:#fff;
margin-left:0.3%;
text-align:center;
}
<div class="box-container">
<div class="box">box</div>
<div class="box">box</div>
<div class="box">box</div>
</div>
You might even don't media queries:
Fiddle 1
.box {
display: inline-block;
width: 180px;
height: 180px;
background: #ddd;
}
And Fiddle 2 with floats.
And just the size of result window: what's wrong with it? What is currently not working properly and what are you trying to achieve (both on desktop and mobile)?
I've done the layout for my website which seems to be working fine, but I wanted to make sure I didn't overcomplicated it or used rubbish technique.
So this is how it works, within the DIV I have another div that is a table, and within it I have another 3 divs that are table-cells
<div id="container-main">
<div id="columns-3">
<div class="main-col-left-s"></div>
<div class="main-col-center-s"></div>
<div class="main-col-right-s"></div>
<hr>
<div class="main-col-left-s"></div>
<div class="main-col-center-s"></div>
<div class="main-col-right-s"></div>
</div>
</div>
Each column contains various elements (something like pinterest website).
Now, when I resize, after reaching certain width, I want only 2 colums to be visible, and later only one. While stacking from 3 to 1 is not difficult as it'll happen automatically, the issue was from 3 to 2 columns, so what I did is I gave the middle column display: none property when screen gets to small, so it's not shown (and on the backend side I assume data will be transferred to visible column if the current one is hidden).
Is this solution rubbish and there is far better one, or it'll do?
I do not want to have situation when in one row I have 2 columns and in the next one only one, so this CAN'T happen:
ǀdataǀdataǀ
ǀdataǀ ǀ
-----------
ǀdataǀdataǀ
ǀdataǀ ǀ
but it should always be:
ǀdataǀdataǀ
ǀdataǀdataǀ
-----------
ǀdataǀdataǀ
ǀdataǀdataǀ
Thanks for clarifying your question. Basically, a css-only solution is possible and recommended. It'd be easy to achieve with CSS3 and the new Flexible Box Model, however, browser support is not evenly implemented -even major browsers. So, if you want to support at least all major browsers I'd suggest you stick to the Traditional Box Model which is what my answer is based on.
The solution is quite straight forward:
One block div that serves as the container element
Multiple divs (inside the container div) displayed inline-block which would be your "table cells"
The html structure would be something like below:
<div class="container">
<div class="box"></div>
<div class="box"></div>
</div>
which would be styled in the following manner...
div.container{
width:100%;
display:block;
font-size:0;
}
div.box{
width:30%;
font-size:40px;
margin:20px 0 0 2.5%;
display:inline-block;
}
This will display 3 boxes aligned horizontally (in one row) in a responsive manner.The font-size:0 declaration is a work-around for the inline-block font spacing issue, you can read more about it if you google it, there are other ways to approach this problem.
Now, in order to display only 2 boxes in one row when the screen width is limited, you can use media queries, as below...
#media all and (max-width:950px){
div.box{
width:47%;
margin:20px 0 0 2%;
}
of course...you can change the max-width constraint to something else. Finally, I've put together a fiddler below in order to add some visuals...
div.container{
width:100%;
height:100%;
padding-bottom:40px;
display:block;
background-color:#eee;
font-family:Arial;
font-size:0;
}
div.box{
color:#666;
background-color:#fff;
width:30%;
font-size:40px;
font-weight:bold;
margin:20px 0 0 2.5%;
line-height:200px;
display:inline-block;
border-radius:6px;
box-shadow:0 4px 5px #ccc;
text-align:center;
*display:inline;
zoom:1;
}
#media all and (max-width:950px){
div.box{
width:47%;
margin:20px 0 0 2%;
}
}
<div class="container">
<div class="box">1</div>
<div class="box">2</div>
<div class="box">3</div>
<div class="box">4</div>
<div class="box">5</div>
<div class="box">6</div>
<div class="box">7</div>
<div class="box" style="height:150px">8</div>
<div class="box">9</div>
<div class="box">10</div>
<div class="box">11</div>
</div>
Notice in the example above that intentionally set the height of box 8
You need to use media queries. Try something like this in your css file:
.main-col-left-s, .main-col-center-s, .main-col-right-s {
width: 100%;
}
#media (min-width: 600px) {
.main-col-left-s, .main-col-center-s, .main-col-right-s {
width: 50%;
}
}
#media (min-width: 960px) {
.main-col-left-s, .main-col-center-s, .main-col-right-s {
width: 33.33%;
}
}
you can also use the float: left property of css, for your table cells, that makes what you wished for
I want to move div's on window resize.
I have three div's inside one div (i.e container)
Eg:
<div id="container">
<div class="left"></div>
<div class="middle"></div>
<div class="right"></div>
</div>
It's aligned properly. But I want these div's to move (but it shouldn't get overlap, I mean it should stop before it gets overlap) when I do windows resize.
This is how my CSS looks.
#container {
text-align:center;
width : 100%;
}
.left {
float:left;
}
.center {
display: inline-block;
margin:0 auto;
}
.right {
float:right;
}
Thanks for the help!
Blockquote
you can simply create your div's and css design you like on this twitter bootstrap, this service can create responsive layout automaticly.
twitter bootstrap
Your CSS is not right. Instead of use #left, #center, #right, you need to use .left, .center, .right
When you use # it will select a html element with that id, this is why your css is just selecting <div id="container">, in your other divs you are using classes, so you use .
See a example :
http://jsfiddle.net/rELXZ/
More info about CSS Selectors you may find here http://www.w3schools.com/cssref/css_selectors.asp
I have a problem with my HTML/CSS webpage. I want to have this layout:
http://img227.imageshack.us/img227/9978/layoutw.png
But all what I get is a layout in which the areas are only as high as the content is.
Here you can see my website: http://ud05_188.ud05.udmedia.de/spotlight/jquery.html I tried several work-arounds, but it does not work.
What's the best way to solve this?
you can use the following code
html
<div id="wrapper">
<div id="left"></div>
<div class="right">start of top</div>
<div class="right">start of bottom</div>
</div>
css
html, body {
height:100%;
}
#wrapper {
height:100%;
overflow:hidden;
}
#left {
height:100%;
width:50%;
background:#09F;
float:left;
}
.right {
height:50%;
width:50%;
float:left;
background:#69a;
}
live example: http://jsbin.com/idozi4
What you're looking for is an adaptation of the Holy Grail method. In this case, #list1 is the 'left' column (as described in that article) and the rest goes into the 'center' column, so that means you can leave out the 'right' column altogether.
Basically something like:
<div id="container">
<div id="left">
#list 1 contents
</div>
<div id="center">
<div>
#list2
</div>
<div>
#data
</div>
</div>
</div>
#container {
padding-left: 200px; /* LC width */
}
#container > div {
position: relative;
float: left;
}
#center {
width: 100%;
}
#left {
width: 200px; /* LC width */
right: 200px; /* LC width */
margin-left: -100%;
}
Heights will always be tricky... some solutions call for using explicit heights, but then if your content ever gets bigger, it'll overflow and look nasty, or worse, overflow and be inaccessible to the user.
You can use min-heights to display a best-case scenario, in which if the content needs to be taller, the minimum requirement will allow the div to stretch. You can use absolute positioning to get the layout that you want, but then the divs wont be flexible enough to accommodate content. You can use overflow: scroll to allow the divs to act like frames, but that is usually more annoying and messy-looking for the user.
I'd say use the above holy grail method to lay the containers out, and then use min-height for a best case scenario layout.
If none of those solutions are good enough, then there are also plenty of blog posts out there from experts about how to get equal height columns more consistently.
By default, giving something height: 100% will make the item as big as the item that contains it. This works for, say, divs within divs, but not for divs directly within the body tag. For this to work you need to set the height of the body element. Like so.
html, body{
height: 100%;
}
Hope this helps.
Update:
I think you are having trouble because you are trying to do two things which are tricky with CSS: fixed-to-bottom-of-page footers and 100% height. I think you will have to change the way that your footer works in order to get the 100% height working.
I haven't got a complete solution but I have made an example page:
http://deviouschimp.co.uk/misc/stackoverflow/columntest.html
That should sort out your 100% height issues. The footer doesn't always match the bottom of the content (#wrap height:94% gets it close, but it's not perfect).
This sticky footer technique should sort the rest out: http://www.cssstickyfooter.com/
Good luck!
In the body of my site, I am trying to create two columns - one on the far right with a fixed width (300px) for advertisements etc, and one on the left which will take up the remaining space on the page. How can this be accomplished in CSS?
CSS :
.column-right {
float: left;
width: 100%;
height: 200px;
background-color: red;
}
.column-right .column-content {
margin-left: 250px;
}
.column-left {
float: left;
margin-left: -100%;
width: 250px;
height: 200px;
background-color: green;
}
HTML :
<div class="column-right">
<div class="column-content">
<strong>Right Column:</strong><em>Liquid</em>
</div>
</div>
<div class="column-left">
<strong>Left Column:</strong><em>250px</em>
</div>
Here is a tool to generate fixed liquid columns for placing adsense ads.
CSS:
#right-column{
width:300px;
float:right;
}
#other-column{
float:left;
width:100%;
padding-right:20px; /*to prevent text overlap as suggested in the comment*/
}
In HTML:
<div id='right-column'>
<!-- ads here -->
</div>
<div id='other-column'>
<!-- content here -->
</div>
You might also want to check out the YUI: CSS Grid Builder. It is a simple web interface where you specify what grid layout you are looking for, and they will provide you the html code you can use in combination with the YUI Grids CSS framework to get your desired layout. One nice thing about the YUI Grids CSS framework is it has good cross browser support which saves you time getting it to work across different browsers. You can also reverse engineer the code that you are provided from the grid builder to get some ideas on how you can do it on your own. The settings you will want to use with the YUI: CSS Grid Builder to get your desired layout is as follows:
Body Size: 100%
Body Columns: Sidebar right 300px
One solution I've found for this is to float the right column to the right and give the left column an absolute position with left:0 and right:300px. This will make it fluid as if you gave it a width:80%, but it will be relative to the parent container in a different way.
Here's an example:
http://jsfiddle.net/tkane2000/dp9GZ/
One issue you might find with this is that since it's absolute, it won't naturally push down the elements below it.
Another possible solution would be to give the left column
width:100%
padding-right: 300px;
and the right (fixed width) column:
position: absolute:
top:0;
right:0;
You might need to set box-sizing:border-box on the left column.
This also as some limitations. One that comes to mind, is that if you wanted the left column to have a border-right to separate each, the border would be on the wrong side of the right column.