Flex positioning of sidebar when in particular order - html

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;
}

Related

Two div in one line, but one div is fixed size, how to? [duplicate]

This question already has answers here:
Two divs side by side - Fluid display [duplicate]
(9 answers)
Expand a div to fill the remaining width
(21 answers)
Closed 1 year ago.
I'm sorry, I speak a little English. I would like see in one line the left and right div.
HTML:
<div id="header">header</div>
<div id="container">
<div id="left"></div>
<div id="right"></div>
</div>
<div id="footer">footer</div>
CSS:
#container { max-width: 1700px; }
#left { width: 100%-314px; }
#right { width: 314px; }
And I would like work if without #right div. See:
HTML (2):
<div id="header">header</div>
<div id="container">
<div id="left"></div>
</div>
<div id="footer">footer</div>
How to?
A possible workaround might be using the span tag, used in your code like this:
<div id="header">header</div>
<div id="container">
<span id="left"></span>
<span id="right"></span>
</div>
<div id="footer">footer</div>
that wont require a fixed size or anything.
Do you mean something like this?
I simply select the divs inside the container and gives them display: inline-block
#container { max-width: 1700px; }
#left { width: 100%-314px; }
#right { width: 314px; }
#container div {
display: inline-block;
}
<div id="header">header</div>
<div id="container">
<div id="left"><p>|left elem|</p></div>
<div id="right"><p>|right elem|</p></div>
</div>
<div id="footer">footer</div>
How about css grid?
.container {
display: grid;
grid-template-columns: 1fr auto;
}
.right {
width: 314px;
}
<div class="container">
<div class="left">A</div>
<div class="right">B</div>
</div>
You can use flexbox, make sure you set display:flex for your container and if you want to align your items with space in between, you can set justify-content:space-between.
#container {
display: flex;
max-width: 1700px;
justify-content: space-between;
}
#left {
background-color: green;
width: 314px;
}
#right {
background-color: red;
width: 314px;
}
<div id="header">header</div>
<div id="container">
<div id="left">left</div>
<div id="right">right</div>
</div>
<div id="footer">footer</div>
This should work for you!
#container {
max-width: 1700px;
display: flex;
}
#left {
width: calc(100% - 314px);
}
#right {
width: 314px;
}
Code Explained:
display:flex : The main idea behind the flex layout is to give the container the ability to alter its items' width/height (and order) to best fill the available space.
calc(100%-314px) : The calc() function performs a calculation that can be used on the property.
I hope this helped you!
You can do this by CSS flex property. div is block level element to get div in one line you can set div to display:inline-block; or inline
check example below.
.flex-container {
display: flex;
height:400px;
flex-flow: column wrap;
background-color: green;
align-content: space-between;
}
.flex-container > div {
background-color: #fff;
width: 100px;
margin: 10px;
text-align: center;
line-height: 75px;
font-size: 30px;
}
.container{
border:1px solid #000;
height:500px !important;
padding:20px;
}
.left{
margin:10px;
background:#f00;
padding:50px;
color:#fff;
float:left;
}
.right{
margin:10px;
background:#f00;
padding:50px;
color:#fff;
float:right;
}
<h1>Example 1</h1>
<div class="flex-container">
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
<div>6</div>
<div>7</div>
<div>8</div>
</div>
<h1>Example 2</h1>
<div class="container">
<div class="left">
<h3>Left</h3>
</div>
<div class="right">
<h3>Right</h3>
</div>
<div class="left">
<h3>Left</h3>
</div>
<div class="right">
<h3>Right</h3>
</div>
</div>

Fit content in to flex direction column [duplicate]

This question already has answers here:
Why don't flex items shrink past content size?
(5 answers)
Closed 2 years ago.
Im trying to fit content into a div with a flex.
Works perfectly into a flex-direction:row; (Standar) but isenĀ“t work into a flex-direction:column;
In "column" just overflow my div, do not resize the elements inside.
How can i do to resize elemetns to fit into a div with out know cuantity of elemnts?
https://codepen.io/nandordena/pen/jObjJNw
HTML
<body>
<div class="column">
<div>
<video src="https://www.w3schools.com/tags/movie.ogg">
</div>
<div>
<video src="https://www.w3schools.com/tags/movie.ogg">
</div>
<div>
<video src="https://www.w3schools.com/tags/movie.ogg">
</div>
</div>
<div class="row">
<div>
<video src="https://www.w3schools.com/tags/movie.ogg">
</div>
<div>
<video src="https://www.w3schools.com/tags/movie.ogg">
</div>
<div>
<video src="https://www.w3schools.com/tags/movie.ogg">
</div>
</div>
</body>
CSS
div{
border:solid 1px #f00;
margin:1px;
flex:1;
}
body{
border:solid 1px #00f;
pading:1px;
display:flex;
height: 500px;
width: 500px;
}
.row{
display:flex;
flex-direction:row;
}
.column{
display: flex;
flex-direction:column;
}
video {
max-height:100%;
max-width:100%;
}
Probably the easiest (not sure if a correct way), to let column grow and don't let it shrink. You can achieve this by adding flex: 1 0 auto; to your wrapper (.row > div)
Grid can do the trick
.grd {
display: grid;
grid-template-columns: auto;
grid-template-rows: 50px;
}
.item1 {
background-color: blue;
width: 120px;
grid-row: 1;
}
.item2 {
background-color: pink;
width: 1fr;
grid-row: 1;
}
.item3 {
background-color: red;
width: 20px;
grid-row: 1;
}
.item4 {
background-color: darkblue;
width: 1fr;
grid-row: 1;
}
<div class="grd">
<div class="item1">One</div>
<div class="item2">Two</div>
<div class="item3">Three</div>
<div class="item4">Four</div>
</div>

Grid align horizontal center is not works

.parent{
border:1px solid red;
display:grid;
grid-template-columns: repeat(12, 1fr);
}
.child{
background:green;
align-self:center;
}
<div class="parent">
<div class="child" style="justify-self: center;">
I am child
</div>
</div>
I am looking a solution to let child should align itself to center. so i can create a class name for left, right, and center will use across.
What's happening here for you is automatic grid placement. Technically speaking the item is aligned to the center inside the first column you created. The problem is that it ends up all the way on the left because that's where your first column actually is.
There's a few ways you can approach this if you want to continue using CSS Grid for this layout concept. But the problem with a 12 col grid is that there won't be a "center" without some offsetting or transforms.
I recommend you use the following if you really only need one row with 3 possible placements. It's a 13 col grid with a defined height of a single row, this ensures if the items are being shuffled out of order (if left is second like my example) that they won't jump to a second implied row.
.parent{
border:1px solid red;
display:grid;
grid-template-columns: repeat(13, 1fr);
grid-template-rows: 60px;
}
.center{
background:green;
grid-column: 7/8;
grid-row: 1/2;
}
.left {
background: red;
grid-column: 1/2;
grid-row: 1/2;
}
.right {
background: blue;
grid-column: 13/14;
grid-row: 1/2;
}
<div class="parent">
<div class="center">
I am child
</div>
<div class="left">
Me too
</div>
<div class="right">
Also me
</div>
</div>
Edit: You can also use flexbox and drop some of the complexity and get better responsiveness by using the order property and justifying the content as space-between.
.parent {
border: 1px solid red;
display: flex;
justify-content: space-between;
}
.center {
background: green;
order: 2
}
.left {
background: red;
order: 1
}
.right {
background: blue;
order: 3
}
<div class="parent">
<div class="center">
I am child
</div>
<div class="left">
Me too
</div>
<div class="right">
Also me
</div>
</div>
Here is an optimized version with flexible values that can work with any number of columns.
I will consider CSS variables to easily adjust the template and the center element. For the left and right we only need 1 and -1
.parent{
--n:6;
display:grid;
grid-template-columns: repeat(calc(2*var(--n)), 1fr);
grid-auto-flow:dense;
margin:5px;
outline:1px solid;
}
.left{
grid-column-start:1;
}
.right{
grid-column-end:-1;
text-align:right;
}
.center {
grid-column:calc(var(--n))/span 2;
text-align:center;
}
.parent > * {
border:1px solid red;
}
<div class="parent">
<div class="left">
left
</div>
<div class="right">
right
</div>
<div class="center">
center
</div>
</div>
<div class="parent" style="--n:3">
<div class="left">
left
</div>
<div class="right">
right
</div>
<div class="center">
center
</div>
</div>
<div class="parent" style="--n:10">
<div class="left">
left
</div>
<div class="right">
right
</div>
<div class="center">
center
</div>
</div>
.parent {
border: 1px solid red;
display: grid;
grid-template-columns: repeat(1, 1fr);
}

How can i place two divs side by side and a third div aligning with the second

I have two divs (div1 and div2) side by side and I would like to place a third div (div3) under div2.
I've tried adding a margin to div3 to try and line it up, but div1 width is dynamic. I've also tried floating div3 to the right but then the content is too far and doesn't line up with the start of div2 like in the image above
.row {
display: flex;
}
.div1 {
margin-right: 1em;
}
<div class="row">
<div class="div1">
<p> some content with unknown width</p>
</div>
<div class="div2">
<p> some content </p>
</div>
</div>
<div class="div3">
<p> some content that should be under div2 </p>
</div>
The default behaviour is div3 being under div1. I am trying to put div3 below div 2
You can do this with below:
.wrapper {
display: flex;
flex-wrap: wrap;
justify-content: flex-end;
}
.div {
flex-basis: 50%;
min-height: 100px;
}
.div1 {
background: red;
}
.div2 {
background: blue;
}
.div3 {
background: aqua;
}
<div class="wrapper">
<div class="div div1">div1</div>
<div class="div div2">div2</div>
<div class="div div3">div3</div>
</div>
And here is a codepan
Use float and inline-block:
[class*="div"] {
display:inline-block;
border:2px solid;
}
.div1 {
float:left;
margin-right: 1em;
margin-bottom:10px; /*mandatory margin to push the div3*/
}
<div class="row">
<div class="div1">
<p> some content with unknown width</p>
</div>
<div class="div2">
<p> some content </p>
</div>
</div>
<div class="div3">
<p> some content that should be under div2 </p>
</div>
You can make use of the CSS Grid structure. In this way you can have all child elements inside a single parent container.
.row {
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-template-rows: repeat(2, 1fr);
grid-column-gap: 5px;
grid-row-gap: 5px;
}
.div1 {
grid-area: 1 / 1 / 2 / 2;
}
.div2 {
grid-area: 1 / 2 / 2 / 3;
}
.div3 {
grid-area: 2 / 2 / 3 / 3;
}
/* Snippet styling */
.row > div {
background: #6A67CE;
color: white;
text-align: center;
text-transform: capitalize;
font-family: sans-serif;
}
<div class="row">
<div class="div1">
<p> some content with unknown width</p>
</div>
<div class="div2">
<p> some content </p>
</div>
<div class="div3">
<p> some content under div2 </p>
</div>
</div>
Here is a flex solution, you can use the slider to change the width of the left box to see that the width doesn't matter.
In case you are not familiar with flex, here is what happens.
display: flex; tells the container to act as a flex container, flex is just another display behavior just like float.
flex-flow: row wrap;, now that the container is flex, tells the children to display in a row, and wrap if necessary, not in this case.
That is all, after adding two boxes in the right div, and set some demo width and height, we are done.
window.addEventListener('DOMContentLoaded', e => {
let left = document.querySelector('.left')
let range = document.querySelector('.range')
range.addEventListener('input', e => {
left.style.width = e.target.value + 'px'
})
})
div {
border: 3px solid green;
}
.container,
.right {
border: none;
}
.container {
display: flex;
flex-flow: row wrap;
}
.left,
.one,
.two {
min-width: 50px;
min-height: 50px;
}
.left {
margin-right: 1em;
}
.one {
min-width: 80px;
}
.two {
margin-top: 1em;
}
<div class="container">
<div class="left"></div>
<div class="right">
<div class="one"></div>
<div class="two"></div>
</div>
</div>
<input class="range" type="range" min="50" max="300"></input>
Since div do not share the same parent , you could use display:contents and set a grid-layout one level upper , unfortunately, display:contents is not yet supported every where .
here is an example (body is the wrapper and .row not seen anymore)
body {
display: grid;
grid-template-columns: auto 1fr;
grid-gap: 10px;
}
.row {
display: contents;
/* removed from the tree */
}
div {
border: solid;
/* show me */
grid-column: 2;
/* make it the defaut column position */
width: max-content;
}
.div1 {
grid-column: 1;
/*a single reset enough here */
}
#supports (display:grid) {
.disclaimer {
display: none;
}
}
<div class="row">
<div class="div1">
<p> some content with unknown width</p>
</div>
<div class="div2">
<p> some content </p>
</div>
</div>
<div class="div3">
<p> some content that should be under div2 </p>
</div>
<p class="disclaimer">Your browser do not support <code>display:contents</code>.</p>
Another possibility is the table-layout algorythm
example with display:table (widely supported) , but every cell of each columns are of the same width.
body {
display: table;
border-spacing: 10px;
}
.div3,
.row {
display: table-row;
}
.row>div,
.div3>p,
.div3::before {
display: table-cell;
border: solid;
}
.div3::before {/* it stands in column 1 */
content: '';
border: none;
}
<div class="row">
<div class="div1">
<p> some content with unknown width</p>
</div>
<div class="div2">
<p> some content </p>
</div>
</div>
<div class="div3">
<p> some content that should be under div2 </p>
</div>
Nothing is perfect ;)
hi i coded this if that helps
.first-container {
display: flex;
flex-direction: row;
}
.first-container div{
margin: 10px;
}
.container {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
<div class="container">
<div class="first-container">
<div class="first">first</div>
<div class="second">second</div>
</div>
<div class="third">third</div>
</div>

align content-div element inside of wrapper-div

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>