How to move up 1 of 3 columns up. Using Flexbox - css

I think i have simple problem. I have 3 columns called Left, Middle, Right obviously ^^
Width of these columns is set to 20%-65%-15% (Left-Mid-Right). I'd need set the left columns at the same line menu is.
index.html
<div class="header-IMG">
<h1>IMG</h1>
</div>
<div class="header-menu">
<horizontal-menu></horizontal-menu>
</div>
<div class="Parent">
<div class="left">
<vertical-menu></vertical-menu>
<center>
<h1>Left</h1>
</center>
</div>
<div class="middle">
<center>
<h1>Middle</h1>
</center>
</div>
<div class="right">
<center>
<h1>Right</h1>
</center>
</div>
</div>
Styles
.Parent {
display: flex;
flex-direction: row;
}
.left {
width: 20%;
height: 100vh;
border: 2px solid red;
color: white;
}
.middle {
width: 65%;
border: 2px solid orange;
}
.right {
width: 15%;
border: 2px solid white;
height: 100vh;
}
For better imagination i send the image from my localhost here:
I tried set to .left position: absolute and then set top property but i think there must be something smarter cuz in this case i had to set padding to middle...

As commented A.Haworth, what about css grid!
Lot of writing saying to use grid for website, not flex. Use flex for 1 element and elements inside it.
#grid {
display: grid;
grid-template-rows: 80px 1fr;
grid-template-columns: 20% 65% 15%;
gap: 0;
width: 100vw;
height: 100vh;
}
#div1 {
grid-area: 1 / 1 / 3 / 2;
background-color: rgba(143, 36, 28, 0.5);
}
#div2 {
grid-area: 1 / 2 / 2 / 4;
background-color: rgba(148, 208, 189, 0.5);
}
#div3 {
grid-area: 2 / 2 / 3 / 3;
background-color: rgba(170, 154, 160, 0.5);
}
#div4 {
grid-area: 2 / 3 / 3 / 4;
background-color: rgba(11, 38, 185, 0.5);
}
<div id="grid">
<div id="div1">div1</div>
<div id="div2">div2</div>
<div id="div3">div3</div>
<div id="div4">div4</div>
</div>

Related

is there a way to display this div next to the one before instead of below it?

I've been trying to put the 3rd container in the free space on the right, like covering the whole height of 1st and 2nd container but fitting right in the free space of their width, and i haven't achieved it yet.
Here is the code so maybe you could help me:
.container {
background-color: rgb(181, 233, 138);
height: 50vh;
width: 50vw;
}
* {
padding: 0;
margin: 0;
}
.container2 {
background-color: rgb(2, 159, 243);
height: 50vh;
width: 50vw;
}
.container3 {
background-color: rgb(23, 223, 133);
height: 100vh;
width: 50vw;
}
<section id="only">
<div class="only container"></div>
<div class="only container2"></div>
<div class="only container3"></div>
</section>
Use a proper CSS grid for the task:
* {
padding: 0;
margin: 0;
}
#only {
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-rows: 1fr 1fr;
height: 100vh;
}
.container {
background-color: rgb(181, 233, 138);
grid-column: 1;
}
.container2 {
background-color: rgb(2, 159, 243);
grid-column: 1;
grid-row: 2;
}
.container3 {
background-color: rgb(23, 223, 133);
grid-column: 2;
grid-row: 1 / 3;
}
<section id="only">
<div class="only container"></div>
<div class="only container2"></div>
<div class="only container3"></div>
</section>
Find a complete guide to CSS grid here. MDN also has excellent information on CSS grid.

Grid layout but avoid space distribute equally

I'm trying to use the grid layout for two columns in one row which can be easily achieved by flex. I have to create one more div for flex but the grid doesn't need one more div.
The problem with the grid is that it will divide the width space by 2 (cannot align to start/left) and that's not what I want, please refer to the first example below and you will understand.
Is there any way to use the grid in this situation but we can align the items to the left like in the second example?
#main-1 {
display: grid;
gap: 30px;
grid-teplate-column: repeat(2, minmax(0, 1fr));
}
.test-1 {
background-color: orange;
grid-area: span 1 / span 2;
}
.test-2 {
background-color: gray;
width: 150px;
}
#main-2 {
display: flex;
gap: 30px;
margin-top: 30px;
}
.test-3 {
background-color: orange;
width: 100%;
}
.test-4 {
background-color: gray;
width: 150px;
}
.test-1,
.test-2,
.test-3,
.test-4 {
height: 60px;
}
<h1>Grid</h1>
<div id="main-1">
<div class="test-1"></div>
<div class="test-2"></div>
<div class="test-2"></div>
</div>
<h1 style="margin:30px 0 0 0;padding-top:15px;border-top: 3px solid #000;">Flex</h1>
<p style="margin:0 0 30px 0;">This is the desired layout but with one more extra div</p>
<div>
<div class="test-3"></div>
<div id="main-2">
<div class="test-4"></div>
<div class="test-4"></div>
</div>
</div>
Edited
Inline-block might work but we cannot control how many items should be on each row. Imagine the width of the first div .first is dynamic and we do not know how wide it would be(but I will make it 30px for illustration). Now the desired layout should be only one .first and one .second on each row.
By inline-block it would appear that now each row is one .first, one .second, and one .first. Check out the example below. Because we cannot control the amount like grid on each row.
#main {
width: 120px;
}
.first,
.second {
display: inline-block;
height: 60px;
}
.first {
background-color: orange;
width: 30px;
}
<div id="main">
<div class="first"></div>
<p class="second">hhhhhh</p>
<div class="first"></div>
<p class="second">hhhhhh</p>
<div class="first"></div>
<p class="second">hhhhhh</p>
</div>
Define the columns as auto and keep only one at 1fr then you can align to the left.
#main-1 {
display: grid;
gap: 30px;
/* update "5" based on your needs */
grid-template-columns: repeat(5,auto) 1fr;
justify-content: left; /* align to left */
}
.test-1 {
background-color: orange;
grid-column: 1/-1; /* take all the columns */
}
.test-2 {
background-color: gray;
width: 150px;
}
#main-2 {
display: flex;
gap: 30px;
margin-top: 30px;
}
.test-3 {
background-color: orange;
width: 100%;
}
.test-4 {
background-color: gray;
width: 150px;
}
.test-1,
.test-2,
.test-3,
.test-4 {
height: 60px;
}
<h1>Grid</h1>
<div id="main-1">
<div class="test-1"></div>
<div class="test-2"></div>
<div class="test-2"></div>
</div>
<h1 style="margin:30px 0 0 0;padding-top:15px;border-top: 3px solid #000;">Flex</h1>
<p style="margin:0 0 30px 0;">This is the desired layout but with one more extra div</p>
<div>
<div class="test-3"></div>
<div id="main-2">
<div class="test-4"></div>
<div class="test-4"></div>
</div>
</div>

Flex items dont shrink equally when padding is add to one of them

.flex-container {
display: flex;
width: 200px;
height: 100px;
padding: 10px;
background-color: green;
}
.flex-item {
min-width: 0;
height: 100%;
flex: 0 1 50%;
}
.flex-item-1 {
margin-right: 50px;
background-color: red;
}
.flex-item-2 {
padding-left: 50px;
background-color: rgb(15, 36, 221);
}
<div class="flex-container">
<div class="flex-item flex-item-1"></div>
<div class="flex-item flex-item-2"></div>
</div>
Flex items dont shrink equally when padding is add to one of them no matter what you do.
Is it possible to make items grow equally or shrink equally if one of them have padding?
I found an answer in beatifully written articles on css tricks - https://css-tricks.com/equal-columns-with-flexbox-its-more-complicated-than-you-might-think/
The conclusion is - padding and borders of flex items do not participate in flex-grow or flex-shrink calculations and act as they were taking space outside of those items.
Use CSS grid in this case
.flex-container {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
width: 200px;
height: 100px;
padding: 10px;
gap: 50px;
background-color: green;
}
.flex-item-1 {
background-color: red;
}
.flex-item-2 {
padding-left: 50px;
background-color: rgb(15, 36, 221);
}
<div class="flex-container">
<div class="flex-item flex-item-1"></div>
<div class="flex-item flex-item-2"></div>
</div>

How to arrange items in css grid with auto heights

I want to make a fairy simple looking layout with css grid.
As, shown in above image, i want to place 3 items in a grid in the exact same order as shown in the image, I don't want to set specific height to any of the item, since each of the item have different height depending upon the content in it. I want to give 70% of grid horizontal space to item1 and 30% to item2 & item3, item3 should be placed beneath item2. Again, heights of items should be auto. I am trying to achieve this for many hours but failed to do so.
Markup of the problem:
<div class="container">
<div class="item1">some content in it...</div>
<div class="item2">some Content in it...</div>
<div class="item3">some Content in it...</div>
</div>
Solution as requested:
You could use grid-template-areas to span the first item across multiple rows. And use a spacer at the end of the right column to make the items just as big as needed.
We can use calc to account for the grip-gap.
.grid {
display: grid;
grid-gap: 20px;
grid-template-columns: calc(70% - 10px) calc(30% - 10px);
grid-template-areas: "item-1 item-2" "item-1 item-3" "item-1 spacer";
border: 1px dashed #000;
align-items: start;
}
.item {
display: flex;
justify-content: center;
align-items: center;
font-size: 32px;
font-weight: bold;
}
#media screen and (max-width: 600px) {
.grid {
grid-template-areas: "item-2" "item-1" "item-3";
grid-template-columns: 100%;
}
}
.item-1 {
grid-area: item-1;
}
.item-2 {
grid-area: item-2;
}
.item-3 {
grid-area: item-3;
}
.purple {
background-color: #5B00FF;
}
.red {
background-color: #FF0000;
}
.pink {
background-color: #FF00FD
}
.h-500 {
height: 500px;
}
.h-100 {
height: 100px;
}
.h-200 {
height: 200px;
}
<div class="grid">
<div class="item item-1 purple h-500">Item 1</div>
<div class="item item-2 red h-100">Item 2</div>
<div class="item item-3 pink h-200">Item 3</div>
</div>
Alternative solution with different columns:
You could use grid-gap along with grid-template-columns. You have to take the grid-gap into account for the width of template-column That's why there is this calc.
.grid {
display: grid;
grid-gap: 20px;
grid-template-columns: calc(70% - 10px) calc(30% - 10px);
border: 1px dashed #000;
}
.col--right {
display: flex;
flex-flow: column nowrap;
gap: 20px;
}
.item {
display: flex;
justify-content: center;
align-items: center;
font-size: 32px;
font-weight: bold;
}
.purple {
background-color: #5B00FF;
}
.red {
background-color: #FF0000;
}
.pink {
background-color: #FF00FD
}
.h-500 {
height: 500px;
}
.h-100 {
height: 100px;
}
.h-200 {
height: 200px;
}
<div class="grid">
<div class="col col--left">
<div class="item purple h-500">Item 1</div>
</div>
<div class="col col--right">
<div class="item red h-100">Item 2</div>
<div class="item pink h-200">Item 3</div>
</div>
</div>

CSS Flexbox - Two columns with 'content wrap under' conundrum

Hugely frustrated that I've had to admit defeat on this one, just when I thought I had flexbox grokked! Apologies for the strange description but the issue is easier shown that described.
What I need:
All four labelled divs (title, left, right, under-left) must all reside within a common container. Left and Right cols take up half the space each, but UNDER-LEFT must tuck under LEFT regardless of the height of RIGHT.
What I've got: At present as I increase the height of RIGHT it is pushing UNDER-LEFT down with it :(
My Code So Far
<style>
#container {
display: flex;
flex-direction: row;
flex-wrap: wrap;
width: 580px;
background-color: rgb(240, 240, 240);
}
#heading {
display: inline-block;
height: 100px;
width: 100%;
background-color: rgb(200, 200, 200);
}
#left {
background-color: red;
height: 250px;
flex: 0 0 50%;
}
#right {
background-color: lightblue;
flex: 0 0 50%;
}
#under-left {
background-color: lightgreen;
flex: 0 0 50%;
}
</style>
<body>
<div id="container">
<div id="heading">
<p>title</p>
</div>
<div id="left">
<p>LEFT height 250, basis 50%</p>
</div>
<div id="right">
<p>RIGHT, basis 50%</p>
</div>
<div id="under-left">
<p>UNDER-LEFT</p>
</div>
</div>
</body>
What I've tried:
To be honest I'm at a total loss. I have tried floating elements but of course flex ignores floats. I don't know what else to try, it's not laziness as it took me about 25 minutes to create this post. I have searched for other answers on SO (such as CSS Flex Box Layout: full-width row and columns) but none feature the wrap-under element issue.
Please be kind!
Do like this to use flexbox (needed a markup change)
#container {
display: flex;
flex-direction: row;
flex-wrap: wrap;
width: 580px;
background-color: rgb(240, 240, 240);
}
#heading {
display: inline-block;
height: 100px;
width: 100%;
background-color: rgb(200, 200, 200);
}
#left {
flex: 1;
}
#right {
background-color: lightblue;
flex: 1;
padding: 20px;
}
#left-top {
background-color: red;
padding: 20px;
}
#left-bottom {
background-color: lightgreen;
padding: 20px;
}
<div id="container">
<div id="heading">
<p>title</p>
</div>
<div id="left">
<div id="left-top">
LEFT height 250, basis 50%
</div>
<div id="left-bottom">
UNDER-LEFT
</div>
</div>
<div id="right">
RIGHT, basis 50%
</div>
</div>
Update based on comment not being able to wrap the left div's
Note, this might be doable with flexbox and non wrapped divs, though I need to know how that layout should look like.
Here is a floated version, which can use flexbox on smaller screens using #media query to reorder the elements visually.
To make the under-left always stay under the left regardless of the right's height, you need to make them wider than the right (here 1px), have the left one's floated left, the right floated right
Sample, right lower
#container {
width: 580px;
background-color: rgb(240, 240, 240);
}
#heading {
display: inline-block;
height: 100px;
width: 100%;
background-color: rgb(200, 200, 200);
}
#left {
background-color: red;
height: 150px;
float: left;
width: calc(50% + 1px);
}
#right {
background-color: lightblue;
height: 100px;
float: right;
width: calc(50% - 1px);
}
#under-left {
background-color: lightgreen;
float: left;
width: calc(50% + 1px);
}
<div id="container">
<div id="heading">
<p>title</p>
</div>
<div id="right">
<p>RIGHT, basis 50%</p>
</div>
<div id="left">
<p>LEFT height 250, basis 50%</p>
</div>
<div id="under-left">
<p>UNDER-LEFT</p>
</div>
</div>
Sample, right higher
#container {
width: 580px;
background-color: rgb(240, 240, 240);
}
#heading {
display: inline-block;
height: 100px;
width: 100%;
background-color: rgb(200, 200, 200);
}
#left {
background-color: red;
height: 150px;
float: left;
width: calc(50% + 1px);
}
#right {
background-color: lightblue;
height: 250px;
float: right;
width: calc(50% - 1px);
}
#under-left {
background-color: lightgreen;
float: left;
width: calc(50% + 1px);
}
<div id="container">
<div id="heading">
<p>title</p>
</div>
<div id="right">
<p>RIGHT, basis 50%</p>
</div>
<div id="left">
<p>LEFT height 250, basis 50%</p>
</div>
<div id="under-left">
<p>UNDER-LEFT</p>
</div>
</div>
Update 2 based on yet another comment
Here is a floated version combined with flexbox and #media query, that will make them in the right order/size on smaller screens
#container {
width: 580px;
background-color: rgb(240, 240, 240);
}
#heading {
display: inline-block;
height: 100px;
width: 100%;
background-color: rgb(200, 200, 200);
}
#left {
background-color: red;
height: 150px;
float: left;
width: calc(50% + 1px);
}
#right {
background-color: lightblue;
height: 200px;
float: right;
width: calc(50% - 1px);
}
#under-left {
background-color: lightgreen;
float: left;
width: calc(50% + 1px);
}
#media screen and (max-width: 600px) {
#container {
display: flex;
flex-direction: column;
}
#left,
#under-left,
#right {
float: none;
width: auto;
}
#right {
order: 1;
}
}
<div id="container">
<div id="heading">
<p>title</p>
</div>
<div id="right">
<p>RIGHT, basis 50%</p>
</div>
<div id="left">
<p>LEFT height 250, basis 50%</p>
</div>
<div id="under-left">
<p>UNDER-LEFT</p>
</div>
</div>

Resources