I've been fiddling with this for a while and can't get what I want. Can someone give me some guidance to achieve the layout in the attached drawing?
I started this off for you. It uses flexbox which is a suggestion by #Keith M (and a good one, I would also recommend flexbox).
Hope it gets you on your way!
.body {
display:flex;
flex-direction:column;
width:100vw;
height:100vh;
}
.body > .topNav {
flex:0 0 50px;
background: blue;
}
.body > .page {
display:flex;
flex-direction:row;
flex: 1 1 auto;
}
.body > .page > .leftNav{
flex: 0 0 300px;
background: red;
}
.body > .page > .content{
flex: 1 1 auto;
}
<div class="body">
<div class="topNav">
</div>
<div class="page">
<div class="leftNav">
</div>
<div class="content">
</div>
</div>
</div>
Related
I have a simple 2-column layout with 3 sections. Depending on a media query, I want to change the order of them - for this I am using flex order.
This works fine, except I get my narrow sidebar section starting at the end of the first section, or similar to this. Is there a way I can get them to position more like jigsaw pieces?
Fiddle example of issue:
https://jsfiddle.net/an7m3yvs/
HTML:
<div class="page-wrapper">
<div class="container">
<div class="box1">
BOX 1
</div>
<div class="box2">
BOX 2
</div>
<div class="box3">
BOX 3 Sidebar
</div>
</div>
</div>
CSS:
.page-wrapper{
width:100%;
max-width:500px;
margin:0 auto;
}
.container{
display:flex;
flex-wrap:wrap;
}
.box1{
display:inline-block;
background:red;
width:70%;
height:400px;
order:1;
}
.box2{
display:inline-block;
background:green;
width:70%;
height:150px;
order:2;
}
.box3{
display:inline-block;
background:grey;
width:30%;
height:600px;
order:3;
}
How I want it:
(I know this can be done simpler but the idea is so I can change the order with a media query, as in mobile I want a single column and them in a different order.)
GRID ATTEMPT: https://jsfiddle.net/w489b2fj/
The 3rd element is not positioned according to the first element but to its predecessor. The sidebar will occupy the remaining space after the 2nd element and not the 1st.
To achieve the desired result, I think it is better to manage 2 flexbox containers. The first includes box1 and box2. The second includes box container and the sidebar.
Edit HTML:
<div class="page-wrapper">
<div class="container">
<div class="content-wrapper">
<div class="box1">
BOX 1
</div>
<div class="box2">
BOX 2
</div>
</div>
<div class="box3">
BOX 3 Sidebar
</div>
</div>
</div>
And edit the CSS:
.container, .content-wrapper{
display:flex;
flex-wrap:wrap;
}
.content-wrapper {
width: 70%;
}
.box1, .box2 {
width: 100%;
}
EDIT:
Ok, with this new information I have another solution:
.container {
position: relative;
}
.box3 {
position: absolute;
top: 0;
right: 0;
}
You can achieve that by adding flex-direction: column; to the container. But in this case (in order to wrap the items) you also need to set a fixed height, in your case height: 550px;.
And actually, you don't need the order settings for the flex items in this simple case...
.page-wrapper {
width: 100%;
max-width: 500px;
margin: 0 auto;
}
.container {
display: flex;
flex-wrap: wrap;
flex-direction: column;
height: 550px;
}
.box1 {
display: inline-block;
background: red;
width: 70%;
height: 400px;
order: 1;
}
.box2 {
display: inline-block;
background: green;
width: 70%;
height: 150px;
order: 2;
}
.box3 {
display: inline-block;
background: grey;
width: 30%;
height: 600px;
order: 3;
}
<div class="page-wrapper">
<div class="container">
<div class="box1">
BOX 1
</div>
<div class="box2">
BOX 2
</div>
<div class="box3">
BOX 3 Sidebar
</div>
</div>
</div>
You wanted an answer using CSS Grid, where box3 places inbetween box1 and box2 in mobile viewports. Here you are:
.container{
display: grid;
grid-template-columns: 1fr;
grid-template-rows: 1fr 1fr 1fr;
grid-template-areas:
"box1"
"box3"
"box2"
}
#media (min-width:768px){
.container{
display:grid;
grid-template-columns: 1fr 1fr;
grid-template-rows: 1fr 1fr;
grid-template-areas:
"box1 box3"
"box2 box3"
}
}
.box1{
grid-area: box1;
background-color: #f00;
}
.box2{
grid-area: box2;
background-color: #0f0;
}
.box3{
grid-area: box3;
background-color: #00f;
}
<div class="page-wrapper">
<div class="container">
<div class="box1">
BOX 1
</div>
<div class="box2">
BOX 2
</div>
<div class="box3">
BOX 3 Sidebar
</div>
</div>
</div>
Try using position property and place the boxes relative to page wrapper.
if you can change HTML ( and always make good structure ) try this:
do the flex on c1 and c2 elements and you simply remove all inline-block instructions
<div class="page-wrapper">
<div class="container">
<div class=c1>
<div class="box1">
BOX 1
</div>
<div class="box2">
BOX 2
</div>
</div>
<div class=c2>
<div class="box3">
BOX 3 Sidebar
</div>
</div>
</div>
And css:
.page-wrapper{
width:100%;
max-width:500px;
margin:0 auto;
}
.container{
display:flex;
}
.box1{
background:red;
height:200px;
order:2;
}
.box2{
background:green;
height:150px;
order:1;
}
.box3{
background:grey;
width:100%;
height:400px;
}
.c2{
width:30%;
flex-basis:1;
}
.c1{
display:flex;
flex-direction:column;
width:70%;
flex-basis:1;
}
I want:
.parent has height based on content, but with max-height
children have height based on content
.second has height based on content, but with respect to .parent max-height
But IE do problems. Other browsers work good.
HTML:
<div class=buggedFix>
<div class=parent>
<div class=first>...</div>
<div class=second><div class=big>...</div></div>
<div class=third>...</div>
</div>
</div>
CSS:
/*.buggedFix{display:flex;}*/
.parent{display:flex;flex-direction: column;width:250px;max-height:200px;}
.first{background:pink;flex: 0 1 auto;}
.third{background:yellow;flex: 0 1 auto;}
.second{background:brown;flex: 1 1 auto;overflow: auto}
.big{background:red;height:600px;margin:10px}
Bad 1: https://jsfiddle.net/fpnjwp0j/3/
Bad 2: https://jsfiddle.net/j53ds1mb/3/
Change the first and third rule's flex-shrink value to 0
Updated fiddle
Stack snippet
.buggedFix {
display: flex;
}
.parent {
display: flex;
flex-direction: column;
width: 250px;
max-height: 200px;
}
.first {
background: pink;
flex: 0 0 auto; /* changed */
}
.third {
background: yellow;
flex: 0 0 auto; /* changed */
}
.second {
background: brown;
flex: 1 1 auto;
overflow: auto
}
.big {
background: red;
height: 600px;
margin: 10px
}
<div class=buggedFix>
<div class=parent>
<div class=first>This is OK. This is OK. This is OK. This is OK. This is OK. This is OK. This is OK. This is OK. </div>
<div class=second>
<div class=big>parent max-height is ignored!</div>
</div>
<div class=third>This is OK. This is OK. This is OK. This is OK.</div>
</div>
</div>
I am having problem with contents of my left sidebar not respecting overflow:hidden anywhere other than Chrome browser.
In Firefox, IE and Edge sidebar is extended instead of being limited to 300 pixels of .container div. Does anyone know how to fix this behavior?
https://jsfiddle.net/o1uu1d0L/2/
Try to change
.flex-fill {
display:flex;
flex:1 1 auto;
}
to
.flex-fill {
display:flex;
min-height: 0;
flex:1 1 0%;
}
I think there are two reasons why this problem occurs:
The first problem is that IE does not accept unitless flex-basis. That's why you have to use flex: 1 1 0% or flex: 1 1 0px but not flex: 1 1 0. And flex: 1 1 auto did not work in this case as well.
The second problem is different interpretation of display: flex in Chrome and Firefox. Firefox, by default, sets min-height: auto; min-width: auto; on display: flex elements and Chrome sets it as min-height: 0; min-width: 0. And what you need is second option.
I'm not sure if that simple change will solve all your problems (but it looked ok when i tested it on IE and Firefox). If not, please think about what I wrote and make similar changes in other classes. I hope it will help!
your codes with a few changes :
<div class="container">
<div class="flex-col flex-fill">
<div class="flex-row flex-fill">
<div class="flex-col flex-50 dragscroll default-box" style="margin-right:5px;">
<div class="button selected">1</div>
<div class="button">2</div>
<div class="button selected">3</div>
<div class="button">4</div>
<div class="button">5</div>
<div class="button selected">6</div>
<div class="button selected">7</div>
<div class="button">8</div>
<div class="button">9</div>
<div class="button">10</div>
</div>
<div class="flex-fill default-box">
center
</div>
<div class="flex-250 default-box" style="margin-left:5px;">
side
</div>
</div>
<div class="default-box flex-50" style="margin-top:5px;">
bottom
</div>
</div>
</div>
.container {
width:500px;
height:300px;
display:flex;
flex-flow:column;
background:lightblue;
}
.buttons-container {
min-height:1px;
height:100%;
flex:0 1 50px;
border:1px solid #CCC;
background:#FFF;
margin-right:5px;
overflow:hidden;
display:flex;
flex-flow:column;
}
.flex-col {
display:flex;
flex-flow:column;
overflow:hidden;
}
.flex-row {
display:flex;
flex-flow:row;
overflow:hidden;
}
.flex-fill {
display:flex;
flex:1 1 auto;
}
.flex-50 {
display:flex;
flex:0 0 50px;
}
.flex-250 {
display:flex;
flex:0 0 250px;
}
.default-box {
background:#FFF;
border:1px solid #CCC;
}
.plot-area {
display:block;
position:relative;
flex:1 1 auto;
background:#FFF;
border:1px solid #CCC;
box-shadow:1px 1px 4px rgba(0,0,0,0.1);
}
.button {
background:#cfeceb;
vertical-align:middle;
margin-bottom:5px;
text-align:center;
color:#56b6b2;
cursor:pointer;
font-size:26px;
flex:1 1 auto;
display:flex;
flex-direction:column;
justify-content:center;
min-height:50px;
}
.button.selected {
background:#56b6b2;
color:#FFF;
}
.button:last-child {
margin:0 !important;
}
I have struggled to align content-div elements of a wrapper-div using only CSS with the following restriction.
The wrapper div can have a row which allows multiple content-div elements be on the row
At most 4 content-div elements can exist on a row of the wrapper div.
Content-div elements of the last row must expand to fill the row. (e.g if 3 content-div elements exist on the last row, then the width of each content-div should be 33.3%)
One and only one content-element always is selected, and the selected element should be bottom-left conner of the wrapper-div element.
To handle this, I have tried the following css.
.wrapper{
width:100%;
}
.content{
max-width:100%;
min-width:25%;
background-color:white;
float:right;
}
.content.selected{
position:absolute;
top:100%;
left:0;
float:left;
background-color:yellow;
}
I thought that the "float:right; float:left position:absolute; top:100%; left:0;" option can handle the restriction 1 and restriction 4, the "min-width:25%" option can handle the restriction 2 and the "max-width:100%" option can handle the restriction 3. However, only a few restriction were satisfied through the CSS.
I have setup jsFiddle example:
https://jsfiddle.net/6qyc5kLw/2/
I would help in this regard.
This image is what I want to do.
ever considered display:flex? its HUGE!
.wrapper{
width:100%;
position:relative;
display: flex;
flex-flow:row wrap;
align-items: stretch;
}
.content{
min-width:25%;
background-color:white;
//float:right;
flex:1;
order:1;
}
.content.selected{
//position:absolute;
//top:100%;
//left:0;
//float:left;
background-color:yellow;
order:-1;
}
The new flexbox possibilities are most certainly what you are looking for. See below snippet or https://jsfiddle.net/6qyc5kLw/3/ for an updated demo with some basic flexbox properties. An additional one would be
flex-order (to reverse the order of elements in first row)
.wrapper{
width:100%;
position:relative;
display: flex;
justify-content: space-between;
flex-wrap: wrap;
}
.content{
flex-basis: 25%;
background-color:white;
border: 1px solid #ccc;
flex-grow: 1;
box-sizing: border-box;
}
.content.selected{
align-self: flex-end;
background-color:yellow;
}
<body>
<div class="wrapper">
<div class="content">
1
</div>
<div class="content">
2
</div>
<div class="content">
3
</div>
<div class="content">
4
</div>
<div class="content selected">
5
</div>
<div class="content">
6
</div>
<div class="content">
7
</div>
</div>
</body>
You can use display: flex
.wrapper{
width:100%;
display: flex;
flex-wrap: wrap;
justify-content: space-around;
}
.content{
background:#fff;
box-flex: 1;
min-width:25%;
flex: 1;
margin: auto;
}
.content.selected{
background-color:yellow;
}
<div class="wrapper">
<div class="content">1</div>
<div class="content">2</div>
<div class="content">3</div>
<div class="content">4</div>
<div class="content selected">5</div>
<div class="content">6</div>
<div class="content">7</div>
</div>
Here is exactly what you want in example picture:
.wrapper{
width:100%;
position:relative;
}
.content{
max-width:100%;
min-width:25%;
background-color:white;
float:right;
border: 1px solid black;
box-sizing: border-box;
}
.content.selected{
background-color:yellow;
float: left;
width: 33.33%;
}
.content:nth-child(6) {
float: right;
width: 33.33%;
}
.content:nth-child(7) {
float: left;
width: 33.33%;
}
<body>
<div class="wrapper">
<div class="content">
1
</div>
<div class="content">
2
</div>
<div class="content">
3
</div>
<div class="content">
4
</div>
<div class="content selected">
5
</div>
<div class="content">
6
</div>
<div class="content">
7
</div>
</div>
</body>
I'm looking for a way to create a CSS layout where the left column is fluid and the right column is fixed using the exact markup below. I don't think it is possible. Am I wrong?
<div class="wrapper">
<div class="left">Fluid Column</div>
<div class="right">Fixed Column</div>
</div>
Yep. Try this:
<div id="wrapper">
<div id="left">
<div id="content">
...
</div>
</div>
<div id="right">
...
</div>
</div>
CSS:
#wrapper { width: 900px; }
#left { float: left; width: 100%; margin: 0 -100px 0 0 ; }
#content { margin: 0 100px 0 0; }
#right { float: right; width: 100px; }
Note: Remove wrapper if you want the width to be 100%.
It's probably not a viable solution at this point in time but if you are not adverse to using bleeding-edge CSS you could also use the CSS3 flex box module. Using vendor specific prefixes, it is currently supported in Firefox, and Webkit based browsers such as Safari and Google Chrome.
<!doctype html>
<style>
.wrapper {
display: -moz-box;
display: -webkit-box;
display: flexbox;
-moz-box-orient: horizontal;
-webkit-box-orient: horizontal;
flex-direction: lr; /* box-orient has been renamed in the most recent version of the draft */
width: 100%;
}
.right {
width:150px;
background-color: #eee;
}
.left {
-moz-box-flex: 1;
-webkit-box-flex: 1;
flex-box: 1; /* box-flex has been renamed flex-box */
}
</style>
<div class="wrapper">
<div class="left">Fluid Column</div>
<div class="right">Fixed Column</div>
</div>
For the sake of semantics, you might want to rename .left and .right to something like .content and .sidebar
Give this a shot:
* { padding:0px; margin:0px; }
.wrapper {
position:absolute;
width:100%;
height:100%;
}
.left {
position:absolute;
top:0; bottom:0;
left:0; right:150px;
background-color:#999999;
}
.right {
position:absolute;
top:0; bottom:0;
right:0;
width:150px;
background-color:#AAAAAA;
}