I'm trying to achieve the following responsive grid-layout using flexbox, but i can't manage to get the "desktop"-version right without a fixed height. I want #1 to be on its own to the left and #2 and #3 stacked on each other to the right (#1 does not have to have the same height as the right col)
HTML (simplified)
<div class="wrapper">
<div class="inner">
<div class="col1"></div>
<div class="col2"></div>
<div class="col3"></div>
</div>
</div>
CSS (simplified)
.wrapper {
max-width: 600px;
margin: 0 auto;
border: 1px solid #c4c4c4
}
.col1, .col2, .col3 {
background: #fe4c4c;
position: relative;
margin: 10px;
padding: 5px;
color: #FFF;
font-weight: bold;
font-size: 40px;
font-family: sans-serif;
min-height: 100px;
&:after {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
}
.col1 {
&:after {
content: '1';
}
width: 100px;
}
.col2 {
&:after {
content: '2';
}
width: calc(100% - (100px + 60px))
}
.col3 {
&:after {
content: '3';
}
width: calc(100% - 30px);
}
.inner {
width: 100%;
display: flex;
flex-wrap: wrap;
}
#media only screen and (min-width: 768px) {
.inner {
flex-direction: column;
}
.col1 {
width: 300px;
}
.col2 {
width: auto;
}
.col3 {
width: auto;
}
}
jsFiddle
https://jsfiddle.net/pcwudrmc/28053/
I've search around for similar problems but can't find an answer without fixed height.
Thanks in advance!
Solution using CSS grid:
https://codepen.io/seanstopnik/pen/bd511c728bb79d02d11ae04edbfe9a33
* {
box-sizing: border-box;
}
.wrapper {
max-width: 600px;
margin: 0 auto;
border: 1px solid #c4c4c4;
padding: 10px;
}
.col1,
.col2,
.col3 {
background: #fe4c4c;
position: relative;
color: #fff;
font: {
family: sans-serif;
size: 40px;
weight: 700;
}
min-height: 100px;
&:after {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
}
.col1:after {
content: '1';
}
.col2:after {
content: '2';
}
.col3:after {
content: '3';
}
// Inner
.inner {
display: grid;
grid: {
template-columns: 100px auto;
template-rows: 100px;
gap: 10px 10px;
}
#media (min-width: 768px) {
grid-template-columns: 300px auto;
}
}
.col1 {
#media (min-width: 768px) {
grid: {
column: 1 / span 1;
row: 1 / span 2;
}
}
}
.col3 {
grid: {
column: 1 / span 2;
row: 2 / span 2;
}
#media (min-width: 768px) {
grid: {
column: auto;
row: auto;
}
}
}
It can be done with Flexbox.
Based on the answer of Nenad Vracar to this question Flexbox/Float - 2 1 2 Layout I did this:
body,
html,
ul {
margin: 0;
padding: 0;
}
* {
box-sizing: border-box;
}
ul {
display: flex;
height: 100vh;
list-style-type: none;
flex-direction: column;
flex-wrap: wrap;
}
li {
flex: 0 0 50%;
border: 1px solid black;
display: flex;
align-items: center;
justify-content: center;
font-size: 50px;
}
li:nth-child(1) {
flex: 0 0 100%;
}
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
It gives you one item to the left with 100% height and two stacked one over the other on the right with 50% height each. This is the result:
Related
I have a container with 3 elements that together share a width of 100% (25%,50%,25%). If the container has less than 800px the order of the elements should be changed. #box2 has a width of 100%. #box1 and #box3 should both have a width of 50% and be on the same column.
So as a final result I should have one column with #box2 at 100% and a second column with #box1 and #box2 at 50%. How do I get #box1 and #box3 to be in the same column in the code below?
JsFiddle (link)
#container {
display: flex;
flex-direction: row;
max-width: 100vw;
width: 100%;
}
#box1 {
background: yellow;
width: 25%;
}
#box2 {
background: orange;
width: 50%;
}
#box3 {
background: red;
width: 25%;
}
/* Large Ansicht */
#media only screen and (max-width: 800px) {
#container {
flex-direction: column;
}
#box1 {
background: yellow;
width: 50%;
order: 2;
}
#box2 {
background: orange;
width: 100%;
order: 1;
}
#box3 {
background: red;
width: 50%;
order: 3;
}
}
<div id="container">
<div id="box1">sidemenu</div>
<div id="box2">app</div>
<div id="box3">sidemenu 2</div>
</div>
You could replace flex-direction: column; with flex-wrap: wrap; :
#container {
display: flex;
flex-direction: row;
max-width: 100vw;
width: 100%;
}
#box1 {
background: yellow;
width: 25%;
}
#box2 {
background: orange;
width: 50%;
}
#box3 {
background: red;
width: 25%;
}
/* Large Ansicht */
#media only screen and (max-width: 800px) {
#container {
flex-wrap: wrap;
}
#box1 {
background: yellow;
width: 50%;
order: 2;
}
#box2 {
background: orange;
width: 100%;
order: 1;
}
#box3 {
background: red;
width: 50%;
order: 3;
}
}
<div id="container">
<div id="box1">sidemenu</div>
<div id="box2">app</div>
<div id="box3">sidemenu 2</div>
</div>
Is it possible to add the similar background ( using pseudo element or whatever ) to the left element instead of right? Couldnt achive this using pseudo elements because they constantly appear at the start of containing element so I only could achieve this effect for the right column .
* {
box-sizing: border-box;
margin: 0;
}
.wrapper {
padding: 20px 0;
position: relative;
overflow: hidden;
}
.container {
padding: 0 15px;
max-width: 1170px;
margin-right: auto;
margin-left: auto;
}
.row {
display: flex;
flex-wrap: wrap;
margin-left: -15px;
margin-right: -15px;
}
.col-left,
.col-right {
padding: 0 15px;
flex-grow: 1;
text-align: center;
height: 500px;
}
.col-left {
width: 70%;
}
.col-right {
width: 30%;
}
.col-right::after {
content: '';
display: block;
position: absolute;
z-index: -1;
top: 0;
height: 100%;
width: 50%;
margin-left: -15px;
background-color: lightgray;
}
<div class="wrapper">
<div class="container">
<div class="row">
<div class="col-left"><h1>Left</h1></div>
<div class="col-right"><h1>Right</h1></div>
</div>
</div>
</div>
You can make the pseudo element relative to their column and use a big width to have overflow:
* {
box-sizing: border-box;
margin: 0;
}
.wrapper {
padding: 20px 0;
position: relative;
overflow: hidden;
}
.container {
padding: 0 15px;
max-width: 1170px;
margin-right: auto;
margin-left: auto;
}
.row {
display: flex;
flex-wrap: wrap;
margin-left: -15px;
margin-right: -15px;
}
.col-left,
.col-right {
padding: 0 15px;
flex-grow: 1;
text-align: center;
height: 500px;
position:relative;
}
.col-left {
width: 70%;
}
.col-right {
width: 30%;
}
.col-right::after {
content: '';
position: absolute;
z-index: -1;
left: 0;
top:-20px;
bottom:0;
width: 100vw;
background-color: lightgray;
}
.col-left::after {
content: '';
position: absolute;
z-index: -1;
top: -20px;
right:0;
bottom:0;
width: 100vw;
background-color: green;
}
<div class="wrapper">
<div class="container">
<div class="row">
<div class="col-left"><h1>Left</h1></div>
<div class="col-right"><h1>Right</h1></div>
</div>
</div>
</div>
Explanation:
Currently the columns width is related to wrapper as wrapper has the style definition position:relative. We want the width of the columns to be related to the div with class "row". So if you give position:relative to .row then "col-left" as well as "col-right" will have width as you expected.
What to do:
To get the expected result add the line position:relative to row class definition.
.row {
display: flex;
flex-wrap: wrap;
margin-left: -15px;
margin-right: -15px;
position:relative;
}
Now to get the effect for left hand side add the code as below
.col-left::before {
content: '';
display: block;
position: absolute;
z-index: -1;
top: 0;
height: 100%;
width: 70%;
margin-left: -15px;
background-color: lightgray;
}
Chrome is normal,Safari failure。How can that be compatible? height:100%;
I need to keep Chrome and use Safari. My Safari version 10.1.2 (12603.3.8)
* {
margin: 0;
padding: 0;
box-sizing: border-box;
outline: none;
}
* ::-webkit-scrollbar {
width: 0;
}
html, body {
height: 100%;
width: 100%;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
flex-direction: column;
}
body {
border: 5px solid red;
}
.d {
height: 100%;
border: 5px solid green;
}
<div class="d"></div>
<div class="d"></div>
Seems like a recent Safari rendering bug involving flex-direction: column. You're putting two height: 100% elements into the same space, and they're both rendering at 100% height and stacking instead of fitting into the same space.
Here are two solutions:
Change height: 100% to height: 50% so both elements are half the height of their parent, or...
Remove the height attribute and add flex: 1 so both children grow as large as they can in the parent's space, and split themselves 50/50 automatically.
* {
margin: 0;
padding: 0;
box-sizing: border-box;
outline: none;
}
*::-webkit-scrollbar {
width: 0;
}
html,
body {
height: 100%;
width: 100%;
display: flex;
flex-direction: column;
}
body {
border: 5px solid red;
}
.d {
height: 50%;
border: 5px solid green;
}
<div class="d"></div>
<div class="d"></div>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
outline: none;
}
*::-webkit-scrollbar {
width: 0;
}
html,
body {
height: 100%;
width: 100%;
display: flex;
flex-direction: column;
}
body {
border: 5px solid red;
}
.d {
flex: 1;
border: 5px solid green;
}
<div class="d"></div>
<div class="d"></div>
I'm not very experienced with css and I encountered the following issue while trying to do a layout with fixed-width left and right columns, and a dynamic middle one.
The only way I was able to accomplish this was using margins on the middle div, to avoid the overlapping with the side columns. I imagine that there's a cleaner way of achieving this, but I haven't been able to find a solution for it yet.
See jsfiddle here with margin left and no margin on the right: http://jsfiddle.net/juansg_eng/BCJ6C/119/
HTML
<div class="left">With margin</div>
<div class="right">No margin</div>
<div class="middle"></div>
css
.left { float: left; width: 134px; height: 191px; background-color:#0000ff; opacity: 0.5}
.middle { height: 50px; background-color: #ff0000; margin-left: 134px}
.right { float: right; width: 183px; height: 191px; background-color:#ffff00; opacity:0.5}
thanks!
flexbox can do that. No floats or margins required.
* {
margin: 0;
padding: 0;
}
.main {
height: 191px;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
border: 2px solid green;
}
.main > div {
border: 1px solid grey;
}
.left {
-webkit-box-flex: 0;
-webkit-flex: 0 1 134px;
-ms-flex: 0 1 134px;
flex: 0 1 134px;
background-color: #0000ff;
opacity: 0.5
}
.middle {
-webkit-box-flex: 1;
-webkit-flex: 1 0 auto;
-ms-flex: 1 0 auto;
flex: 1 0 auto;
height: 50px;
background-color: #ff0000
}
.right {
-webkit-box-flex: 0;
-webkit-flex: 0 0 183px;
-ms-flex: 0 0 183px;
flex: 0 0 183px;
background-color: #00ff00;
opacity: 0.5
}
<div class="main">
<div class="left"></div>
<div class="middle"></div>
<div class="right"></div>
</div>
Adding display: flex; to middle container should do the trick.
Do check the browser support.
.left {
float: left;
width: 134px;
height: 191px;
background-color: #0000ff;
opacity: 0.5
}
.middle {
height: 50px;
background-color: #ff0000;
display: flex;
}
.right {
float: right;
width: 183px;
height: 191px;
background-color: #ffff00;
opacity: 0.5
}
<div class="left">With margin</div>
<div class="right">No margin</div>
<div class="middle"></div>
Reference link
.left { float: left; width: 134px; height: 191px; background-color:#0000ff; opacity: 0.5}
.middle { float:left; width: calc(100% - (134px + 183px)); height: 50px; background-color: #ff0000;}
.right { float: right; width: 183px; height: 191px; background-color:#ffff00; opacity:0.5}
I am working on a page redesign that contains 3 divs and I want to make it responsive.
The problem I face is that the divs for large screen are arranged in the order 1,2,3. For responsive design however, I want to change the order to 1,3,2:
I tried different approaches like changing position to relative/absolute/static or changing the divs order with alternative CSS code but nothing proved to work so far.
Any ideas how I can achieve this?
.one {
float: left;
width: 150px;
border: solid 2px #eaeaea;
position: relative;
z-index: 0;
margin-bottom: 20px;
height: 100px;
}
.two {
float: left;
margin: 0 0 0 24px;
width: 150px;
border: solid 2px #eaeaea;
height: 100px;
}
.three {
float: left;
width: 900px;
border: solid 2px #eaeaea;
height: 100px;
}
#media only screen and (max-width: 500px) {
.one {
width: 93%;
padding: 3%;
}
.two {
width: 100%;
margin-left: 0px;
}
.three {
width: 100%;
margin: 0px;
}
}
<div class="one">Content1</div>
<div class="two">Content2</div>
<div class="three">Content3</div>
<div class="500markup">This box is 500px</div>
JSFIDDLE HERE
https://jsfiddle.net/fehrda1c/4/
<div class="container">
<div id="one">Content1</div><!--
!--><div id="three">Content3</div>
<div id="two">Content2</div>
</div>
.container {
padding: 5px;
position: relative;
}
#one, #two {
width: 50%;
display: inline-block;
box-sizing: border-box;
}
#two {
position: absolute;
top: 0;
right: 0;
}
#one {
position: absolute;
top: 0;
left: 0;
}
#three {
position: absolute;
top: 200px;
left: 0;
box-sizing: border-box;
}
#one, #two, #three {
margin: 0;
height: 200px;
border: 1px solid black;
}
#three {
width: 100%;
}
#media (max-width: 600px) {
#one, #two, #three {
width: 100%;
position: initial;
top: default;
}
}
This can be achieved using flexbox:
Contain the divs in a #container set to display: flex; this will tell the child divs to use the flexbox model
Add flex: 1; to .one and .two to tell them to grow if required
Add flex-basis: 100%; to .three to ensure it takes up the full width of the container
Add order: *n*; to .one, .two and .three to give them the desired order when they adapt to the smaller screen size
#container {
display: flex;
flex-wrap: wrap;
width: 100%;
}
.one {
border: solid 2px #eaeaea;
flex: 1;
height: 100px;
margin-bottom: 20px;
}
.two {
border: solid 2px #eaeaea;
flex: 1;
height: 100px;
margin-bottom: 20px;
}
.three {
border: solid 2px #eaeaea;
flex-basis: 100%;
height: 100px;
margin-bottom: 20px;
}
#media only screen and (max-width: 500px) {
.one {
flex-basis: 100%;
order: 1;
}
.two {
flex-basis: 100%;
order: 3;
}
.three {
flex-basis: 100%;
order: 2;
}
}
<div id="container">
<div class="one">Content1</div>
<div class="two">Content2</div>
<div class="three">Content3</div>
</div>
Flexbox can do this.
JSfiddle Demo
* {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
.container div {
height: 150px;
border: 1px solid red;
margin-bottom: 10px;
}
.container {
padding: 5px;
position: relative;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
width: 500px;
border: 1px solid grey;
}
#one,
#two {
width: 220px;
}
#three {
width: 500px;
}
#media (max-width: 600px) {
#one {
order: 1;
width: 500px;
}
#two {
order: 3;
width: 500px;
}
#three {
order: 2;
}
<div class="container">
<div id="one">Content1</div>
<div id="two">Content2</div>
<div id="three">Content3</div>
</div>
You can do like following:
#media only screen and (max-width:500px)
{
.one{width: 93%; padding: 3%;}
.two{width: 100%; margin-left: 0px; margin-bottom: 10px; position:absolute; top:320px;}
.three{width: 100%; margin: 0px;}
}
Check Fiddle Here.