Alright guys, I've been busting my balls over this one.
I've got three divs; left, middle, right. All 100% height. The left and right div have a fixed width of 150px. Now I want the middle div to take up the remaining space.
Example: Here
CSS:
#left {
height:100%;
width:150px;
float:left;
background:red;
z-index:999;
}
#middle {
height:100%;
width:100%;
background:yellow;
margin-left:-150px;
margin-right:-150px;
}
#right {
float:right;
height:100%;
width:150px;
background:red;
z-index:998;
}
Use display: table:
#container {
display: table;
width: 100%;
}
#left, #middle, #right {
display: table-cell;
}
#left, #right {
width: 150px;
}
Where the #container is your parent element like in
<div id="container">
<div id="left"></div>
<div id="middle"></div>
<div id="right"></div>
</div>
Here is a Fiddle.
Okay using flex and based this answer
#parent {
display: flex;
}
#left {
width:150px;
background-color:#ff0000;
}
#middle {
flex: 1 1 auto;
background-color:#00ff00;
}
#right {
width: 150px;
background-color:#0000ff;
}
<div id="parent">
<div id="left">left</div>
<div id="middle">middle</div>
<div id="right">right</div>
</div>
This actually works if the left and right divs has variable width also.
Check this similar answer
HTML
<div class = "container">
<div class = "fixed">
I'm 150px wide! Glee is awesome!
</div>
<div class = "fluid">
I'm fluid! Glee is awesome!
</div>
<div class = "fixed">
I'm 150px wide! Glee is awesome!
</div>
</div>
CSS
html, body {
height: 100%;
font-family: 'Arial', 'Helvetica', Sans-Serif;
}
.container {
display: table;
width: 100%;
height: 100%;
}
.container > div {
display: table-cell;
text-align: center;
}
.fixed {
width: 150px;
background: rgb(34, 177, 77);
color: white;
}
.fluid {
background: rgb(0, 162, 232);
}
DEMO
If you don't want to use table cells and don't want to give your outer boxes a fixed width (instead let their width be determined by their content, you can use the overflow-hidden and float method)
The bad thing about this method is you have to adhere to having overflow hidden on your divs and also you have to arrange your divs in a backwards way (see below)
DEMO
HTML
<div class='container'>
<div class='third-box'>Third</div>
<div class='first-second'>
<div class='first-box'>First</div>
<div class='second-box'>Second</div>
</div>
</div>
CSS
.container {
width: 400px;
}
.first-second {
overflow: hidden;
}
.first-box {
float: left;
background-color: coral;
}
.second-box {
overflow: hidden;
background-color: aquamarine;
}
.third-box {
float: right;
background-color: salmon;
}
I used this to set a flexible width for the items to the side. Used it in a listed item to get a progress bar with 2 buttons on the side.
ul {
display: table;
width: 100%;
}
ul > li {
display: table-cell;
}
ul > li:nth-child(2) {
min-width: 100%;
}
Related
I'm trying to make a layout that seems simple. Despite looking at lots of examples, I can't crack it.
SideBar| .......MapContainer......
SideBar| ..........Map............
SideBar| .......MapContainer......
Both SideBar and MapContainer should be 100% height.
The tricky bit: Map must have a defined height and width, because the mapbox-gl-js library uses its dimensions to populate it. (Rather than adding content which then sizes it).
MapContainer exists because there will be other absolutely positioned overlay elements within it.
I'm trying to avoid having the sidebar width coded into the definition of MapContainer so I can hide/show the sidebar in JS, and have the MapContainer automatically fill the space.
This gets really, really close:
* {
box-sizing: border-box;
}
.sidebar, .mapcontainer, .container {
height: 200px;
}
.container {
width:100%;
border:1px solid;
display: flex
}
.sidebar {
width:200px;
background:lightblue;
}
.mapcontainer {
width:auto;
background:lightgreen;
position:relative;
flex-grow: 1;
}
.map {
width: 100%;
height: 100%;
position:absolute;
border: 20px dashed grey;
}
<div class="container">
<div class="sidebar"></div>
<div class="mapcontainer">
<div class="map">
</div>
</div>
</div>
But as soon as I change the "height: 200px" to "height: 100%", it collapses to nothing. What do I need to do?
Use viewport units vh instead in the .sidebar, .mapcontainer, .container rule
* {
box-sizing: border-box;
}
html, body {
margin: 0;
}
.sidebar, .mapcontainer, .container {
height: 100vh;
}
.container {
border: 1px solid;
display: flex
}
.sidebar {
width: 200px;
background:lightblue;
}
.mapcontainer {
background:lightgreen;
position:relative;
flex-grow: 1;
}
.map {
width: 100%;
height: 100%;
position:absolute;
border: 20px dashed grey;
}
<div class="container">
<div class="sidebar"></div>
<div class="mapcontainer">
<div class="map">
</div>
</div>
</div>
I just need to add height: 100%; to html and body:
* {
box-sizing: border-box;
}
html, body {
height: 100%;
margin: 0;
}
.sidebar, .mapcontainer, .container {
height: 100%;
}
.container {
width:100%;
border:1px solid;
display: flex
}
.sidebar {
width:200px;
background:lightblue;
}
.mapcontainer {
width:auto;
background:lightgreen;
position:relative;
flex-grow: 1;
}
.map {
width: 100%;
height: 100%;
position:absolute;
border: 20px dashed grey;
}
<div class="container">
<div class="sidebar"></div>
<div class="mapcontainer">
<div class="map">
</div>
</div>
</div>
I am trying to create a textbox that spans the entire width of my middle column. Whenever I set the width of the textbox to 100% though it drops below the divs and doesnt look good. How do I keep the textbox contained in the middle DIV and have it be 100% of the middle DIV?
HTML
<div class="leftsidebar">a</div>
<div class="rightsidebar">b</div>
<div class="content">
<div>
<input type="text" style=""/>
</div>
</div>
CSS
.leftsidebar { width: 60px; background:red; float:left; }
.rightsidebar { background:blue; width: 170px; float:right; }
.content { width: auto;background:yellow; }
.content input[type='text'] { width: 100%; }
http://jsfiddle.net/v0mp0wgm/
You can achieve this using flexbox. First, you want to create a containing div for your content, then assign it display: flex;. After that, move your .content div between the left and right sidebar and remove their floats. Then, give your .content and .content input[type='text'] classes a width of 100%; and you should be good to go.
.container {
display: flex;
}
.leftsidebar { width: 60px; background:red; }
.rightsidebar { background:blue; width: 163px;}
.content { width: auto; background:yellow; width: 100%; }
.content input[type='text'] { width: 100%; }
<div class="container">
<div class="leftsidebar">a</div>
<div class="content">
<div>
<input type="text" style=""/>
</div>
</div>
<div class="rightsidebar">b</div>
</div>
JSFiddle
One option is to apply float:left to everything and use calc() :
.leftsidebar {
float:left;
width: 60px;
background:red;
}
.content {
float:left;
width: calc(100% - 60px - 170px);
background:yellow;
}
.rightsidebar {
float:left;
width: 170px;
background:blue;
}
.content input[type='text'] {
display: block;
width: 100%;
}
<div class="leftsidebar">a</div>
<div class="content">
<div>
<input type="text" />
</div>
</div>
<div class="rightsidebar">b</div>
Example:
<div class="container">
<div>variable</div>
<div>fixed</div>
<div>variable with min-width</div>
<div>fixed</div>
<div>variable</div>
</div>
I want the whole thing to be as wide as the viewport.
I know how to do that for three columns, but I am completely lost with the five column version. I do not even have a concept of how that could work. The usual three column style involves absolute positioning of the fixed columns, but that would not work since the outermost columns are of variable width. I am lost.
Any ideas?
This is what I tried:
HTML:
<div class="container">
<div class="left">var</div>
<div class="inner_container">
<div class="inner_left">fix</div>
<div class="middle">var</div>
<div class="inner_right">fix</div>
</div>
<div class="right">var</div>
</div>
CSS:
.container {
position:relative;
}
.container div {
background: yellow;
}
.container .left,
.container .right {
background: orange;
width: 15%;
}
.inner_container {
position:relative;
}
.inner_container div {
margin:0 50px;
background:lightgreen;
}
.inner_container .inner_left,
.inner_container .inner_right {
background:lightblue;
position:absolute;
top:0;
width:50px;
}
.inner_container .inner_left {
left:-50px;
}
.inner_container .inner_right {
right:-50px;
}
The "inner_container" is basically the usual three column solution. If I set the inner_container to "left: 15%" the whole inner container is moved to the right, but still on its own "line".
flexbox can do that.
* {
box-sizing: border-box;
}
.container div {
height: 75px;
border:1px solid grey;
}
.container {
display: flex;
}
.variable {
background: lightgreen;
flex: 1 0 auto
}
.fixed {
background: lightblue;
flex: 0 0 150px;
}
.min-width {
flex-basis:250px;
min-width:250px;
background: pink;
}
<div class="container">
<div class="variable">variable</div>
<div class="fixed">fixed</div>
<div class="variable min-width">variable with min-width</div>
<div class="fixed">fixed</div>
<div class="variable">variable</div>
</div>
Codepen Demo
I'm trying to create 3 columns layout, where structure should be main, left column, right column. The main column is auto-width to fill rest of page.
Unfortunately I cannot change the HTML, which is currently like this:
<div class="wrap">
<div class="main"></div>
<div class="left"></div>
<div class="right"></div>
</div>
Yes: That means I cannot change the order of divs.
I've found some solutions, one of these is by using display: table-cell, but there is issue when using float. Second solutions is layout by using flexbox, it is pretty good solution, but I cannot use it because of IE9 where this CSS style isn't supported.
Just to restate the aim: My need is to have left and right with fixed width, and main will fill rest of free space.
<---250px--><----------------auto-width-------------><---200px--->
<---Left-----><------------------main------------------><---right----->
Have anyone any solutions for this in pure CSS without any JavaScript?
Here you go. A simple CSS solution. Remember you should always clear your floats.
HTML
<div class="left"></div>
<div class="right"></div>
<div class="main"></div>
<div class="clear"></div>
CSS
.main, .left, .right {
min-height: 250px;
}
.left {
float: left;
background-color: green;
width: 50px;
}
.right {
float: right;
background-color: blue;
width: 50px;
}
.clear {
clear: both;
}
.main {
background-color: gray;
}
JSFiddle: http://jsfiddle.net/18rvc23q/
You could try floating the sidebars to the left and right respectively, and then applying some padding to the .main div to keep it from overlapping them.
<style>
.left {float: left; width: 250px;}
.right {float: right; width: 200px;}
.main {padding: 0 200px 0 250px;}
</style>
<div class="wrap">
<div class="right">right</div>
<div class="left">left</div>
<div class="main">main</div>
</div>
https://jsfiddle.net/1ofqkLmw/
Note that in this markup I've moved the main div to be the last child of wrap.
Also note that you can just as well use margin instead of padding - if you don't want the border and background to overlap the sidebars, then margin is the way to go.
You could use a mix of left and right margin on .main and then absolute position the .left and .right columns.
HTML
<div class="wrap">
<div class="main"></div>
<div class="left"></div>
<div class="right"></div>
</div>
CSS
.wrap {
position: relative;
}
.main {
border: 1px dashed red;
margin: 0 100px;
min-height: 300px;
}
.left,
.right {
width: 100px;
min-height: 300px;
position: absolute;
top: 0;
}
.left {
left: 0;
background-color: yellow;
}
.right {
right: 0;
background-color: blue;
}
Here's a jsFiddle of it in action: http://jsfiddle.net/1u9gzyh6/
Two ways to do this:
HTML
<div class="wrap">
<div class="left"></div>
<div class="main"></div>
<div class="right"></div>
</div>
The better (but unsupported in IE9-) way
.wrap {
display:flex;
}
.left {
flex-basis:250px;
}
.right {
flex-basis:200px;
}
.main {
flex-grow:1;
}
The somewhat hackier, but supported in IE9 (but not IE8- or certain mobile browsers) way
.wrap {
display:block;
}
.left {
width:250px;
}
.right {
width:200px;
}
.main {
width:calc(100% - 450px);
}
UPDATE: if you wanted to dynamically add / remove columns, just add a few extra classes in your CSS file:
.main.no-left {
width:calc(100% - 200px);
}
.main.no-right {
width:calc(100% - 250px);
}
.main.no-left.no-right {
width:100%;
}
And apply the classes dynamically via JS as needed. Anything else requires a JS solution that actually sets the width as an inline style, or makes use of position:absolute;, which can get real hacky, real fast.
EDITED:
<style>
div {
margin: 0;
padding: 0
}
div.main-wrapper {
overflow: hidden;
width: 700px;
margin: 0 auto;
}
div.left-wrapper {
float: left;
width: 500px;
}
div.left-col {
float: left;
width: 200px; /*change to what value you desire*/
background-color: #5446EB;
height: 400px;
}
div.main-col {
background-color: #DDEB46;
height: 400px;
}
div.right-col {
float: right;
width: 200px; /*change to what value you desire*/
background-color: #EB838D;
height: 400px;
}
</style>
<div class="main-wrapper">
<div class="left-wrapper">
<div class="left-col">
insert content of the left col here
</div>
<div class="main-col">
insert content of the main col here.
</div>
</div>
<div class="right-col">
insert content of the right col here
</div>
</div>
I think this should solve your problem:
.main, .left, .right {
height: 250px;
}
.left {
float: left;
background-color: green;
width: 50px;
position: relative;
margin-left: -300px; // negative width of main
}
.right {
float: left;
background-color: blue;
width: 80px;
margin-left: 50px; // width of left
}
.main {
width: 300px;
background-color: gray;
float: left;
position: relative;
left: 50px; // width of left
}
.wrap:after {
content: "";
clear: both;
}
<div class="wrap">
<div class="main">Main</div>
<div class="left">Left</div>
<div class="right">Right</div>
</div>
<div class="table">
<div class="sidebar"></div>
<div class="content"></div>
</div>
* {
margin:0; padding:0;
}
html, body {
width:100%;
height:100%;
}
.table {
display:table;
width:100%;
height:100%;
}
.sidebar {
width:200px;
height:100%;
background:red;
display:table-cell;
white-space:nowrap;
vertical-align: top;
}
.content {
width:100%;
height:100%;
background:orange;
display:table-cell;
vertical-align: top;
}
What am I missing exactly? :), trying to replicate this structure:
http://dev.brigademarketing.com/brigade/old-content/site1/
fiddle:
http://jsfiddle.net/8o50f0cf/
Remove the width:100% from the dynamic column, so it can calculate its width automatically.
Updated Fiddle
A display: table-cell element acts like a <td>, meaning that it takes the remaining space of its table parent if no width is define.
Here's a solution that uses calc() function and floating: http://jsfiddle.net/jyx9orLy/.
HTML:
<div class="container">
<div class="sidebar"></div>
<div class="content"></div>
</div>
CSS:
* {
margin: 0;
padding: 0;
}
html, body, .container {
height: 100%;
}
.container .sidebar {
height: 100%;
background-color: red;
width: 200px;
float: left;
}
.container .content {
float: left;
height: 100%;
width: calc(100% - 200px);
background-color: orange;
}
A second solution is to use a table, which you are doing, and to make it work you do what #LcSalazar mentioned.
A third solution uses flexbox specification and requires a modern browser: http://jsfiddle.net/yp49uqay/.
CSS:
* {
margin: 0;
padding: 0;
}
html, body, .container {
height: 100%;
}
.container {
display: flex;
flex-direction: row;
}
.container > .sidebar {
flex: 0 0 200px;
background-color: red;
}
.container > .content {
flex: 1 1 auto;
background-color: orange;
}
And, a fourth solution that uses floating in a different way: http://jsfiddle.net/079sr0fu/.
HTML:
<div class="container">
<div class="sidebar"></div>
<div class = "contentWrapper">
<div class="content">Content...</div>
</div>
</div>
CSS:
* {
margin: 0;
padding: 0;
}
html, body, .container,
.container > .sidebar,
.container > .contentWrapper,
.container > .contentWrapper > .content {
height: 100%;
}
.container > .sidebar {
width: 200px;
background-color: red;
float: left;
}
.container > .contentWrapper {
overflow: hidden;
}
.container .content {
float: left;
width: 100%;
background-color: orange;
}