I have 4 divs that I am using flexbox to align. At desktop size, there are 3 equal width columns with the first and last divs taking up the entire height of the container. The second and third divs stack vertically in the middle with each taking up 50% of the height. That's working fine.
At mobile size, I want the last div to be on top and to stretch the entire width of the container. Then I want the first div to align left underneath the top div and take up 50% of the width and the remaining height of the container.
The problem I'm having is I want the second and third div to align right under the top div and take up the remaining 50% of the width but to stack vertically so each takes up 50% of the remaining height.
I've tried changing the flex-direction in the media query and everything else I can think of but it's not working.
* {
margin: 0;
padding: 0;
}
.box-wrapper {
display: flex;
flex-direction: column;
flex-wrap: wrap;
height: 70vh;
align-items
}
.boxa {
background: red;
flex: 0 0 100%;
width: 33%;
}
.boxb {
background: orange;
}
.boxc {
background: lightgreen;
}
.boxb,
.boxc {
flex: 0 0 50%;
width: 33%;
}
.boxd {
background: grey;
flex: 0 0 100%;
width: 33%;
}
#media (max-width: 700px) {
.boxa {
order: 2;
width: 50%;
flex: 0 0 75%;
}
.boxb {
order: 3;
width: 50%;
flex: 0 0 37.5%;
}
.boxc {
order: 4;
width: 50%;
flex: 0 0 37.5%;
}
.boxd {
order: 1;
flex: 0 0 25%;
width: 100%;
}
}
<div class="box-wrapper">
<div class="boxa"></div>
<div class="boxb"></div>
<div class="boxc"></div>
<div class="boxd"></div>
</div>
The layout you want is difficult to achieve with flexbox because flexbox is not well-suited for 2-dimensional grids. It excels at 1-dimensional grids (placing flex items in rows or columns), but has limited capacity in 2-dimensional grids (placing flex items in rows and columns).
Being that your desired layout involves items having to cross row and column lines, flex is not your best option. With CSS Grid, your layout is simple and easy.
jsFiddle demo
.box-wrapper {
display: grid;
grid-template-columns: 1fr 1fr 1fr; /* 3 equal width columns */
grid-template-rows: 1fr 1fr; /* 2 equal height rows */
height: 70vh;
grid-column-gap: 5px;
grid-row-gap: 5px;
padding: 5px;
grid-template-areas: " first second last "
" first third last ";
}
.boxa { grid-area: first; background: red; }
.boxb { grid-area: second; background: orange; }
.boxc { grid-area: third; background: lightgreen; }
.boxd { grid-area: last; background: grey; }
#media ( max-width: 700px) {
.box-wrapper {
grid-template-columns: 1fr 1fr;
grid-template-rows: 1fr 1fr 1fr;
grid-template-areas: " last last "
" first second "
" first third ";
}
}
* { margin: 0; padding: 0; }
/* for placing and styling numbers only */
.box-wrapper > div {
font-size: 1.5em; display: flex; align-items: center; justify-content: center; }
<div class="box-wrapper">
<div class="boxa">1</div>
<div class="boxb">2</div>
<div class="boxc">3</div>
<div class="boxd">4</div>
</div>
More information:
Is it possible for flex items to align tightly to the items above them?
Related
This question already has answers here:
How to match width of text to width of dynamically sized image/title?
(2 answers)
One flex/grid item sets the size limit for siblings
(6 answers)
Closed 1 year ago.
I have grid layout with two inner elements, I want second element(bbbb row) should be limited by (aaaaa row)
<style>
#container {
display: grid;
width: 90%;
justify-content: center;
background: green;
display: grid;
grid-auto-flow: row;
}
#inner {
display: grid;
width: 100%;
background: red;
}
#inner2 {
display: grid;
width: 100%;
background: yellow;
}
</style>
<div id="container">
<div id="inner">aaaaaaaaa</div>
<div id="inner2">bbbbbbbbbbbbbbbb</div>
</div>
so, this is how it looks like now bad
and how it should be(part of bbb is hidden) good
You can try this
#container {
display: grid;
width: 90%;
justify-content: center;
background: green;
display: grid;
grid-auto-flow: row;
}
#inner {
display: grid;
width: 100%;
background: red;
}
#inner2 {
display: grid;
background: yellow;
/* New */
width: 0;
padding-right: 100%;
overflow: auto;
}
<div id="container">
<div id="inner">aaaaaaaaa</div>
<div id="inner2">abcdefhijklmnopqrst</div>
</div>
Explanation:
width: 0; To lose the content defined width
padding-right: 100%; percentage on the padding is calculated from the parent's width, in this case it's the invisible grid column which is defined by the first element.
overflow: auto; hide the overflow, not sure how you want to deal with it so.
I need to setup the following DIV structure (See image below. It tells more than a 1000 words)
The structure consists of 2 colums. The main column (left) has a variable width and 100% height.
The right colums has a FIXED width of 380px and 100% height.
Then inside the right column I need 3 DIVS.
The top DIV has a fixed height of 200px and must be aligned to the top.
The bottom DIV has a fixed height of 150px and must be aligned to the bottom.
The middle DIV has a variable height and must fill up the space vertically.
This is the DIV setup And the CSS I have:
.main-content {
width: 100%;
padding: 0px;
}
.col-1 {
width: calc(100% - 380px);
min-height: calc(var(--vh, 1vh)*100);
background-color: #2693FF;
float: left;
}
.col-2 {
width: 380px;
min-height: calc(var(--vh, 1vh)*100);
float: right;
}
.col-2-top {
height: 200px;
background-color: #00B200;
}
.col-2-middle {
height: 100%;
background-color: #FF8000;
}
.col-2-bottom {
height: 100px;
background-color: #B25900;
}
<div class="main-content">
<div class="col-1"></div>
<div class="col-2">
<div class="col-2-top"></div>
<div class="col-2-middle"></div>
<div class="col-2-bottom"></div>
</div>
</div>
Then... Column 1 and 2 should stack when the viewport width becomes less than 768px.
Column 1 on top and Column 2 below it.
Like this:
I think I'm almost there, but I'm having problems with the height of the Main DIV and the heights and aligning of the DIV col-2 middle DIV. I also need a bit helpt to get these divs stack nicely above each each other.
I would suggest that you use grid layout instead of floating around your <div>s, grid layout allows you to structure your layout and separate them in columns and rows, and areas using grid-template-areas.
for max-width:748 just add media query, here is how it might be implemented:
body {
padding: 0;
margin: 0;
}
.main-content {
display: grid;
background-color: #2196F3;
grid-template-areas:
'main fixed-top'
'main variable-mid-area'
'main fixed-bottom';
background-color: #2196F3;
height: 100vh;
grid-template-columns: 1fr 380px;
grid-template-rows: 200px 1fr 150px;
}
.main-content > div {
color: #fff;
font-size: 30px;
vertical-align: middle;
display: flex;
justify-content: center;
align-items: center;
}
.main {
grid-area: main;
background-color: #2693FC;
}
.variable-mid-area {
grid-area: variable-mid-area;
background-color: #FF8015;
}
.fixed-top {
grid-area: fixed-top;
background-color:#00B21F;
}
.fixed-bottom {
grid-area: fixed-bottom;
background-color: #B2590B;
}
#media only screen and (max-width: 768px) {
.main-content {
grid-template-areas:
'main'
'fixed-top'
'variable-mid-area'
'fixed-bottom';
grid-template-rows: 300px 200px 1fr 150px;
grid-template-columns: 100%;
height: auto;
}
}
<div class="main-content">
<div class="main"> main </div>
<div class="fixed-top"> 200 </div>
<div class="variable-mid-area"> auto </div>
<div class="fixed-bottom"> 150 </div>
</div>
If you have any questions how the css works, feel free to ask them in the comments.
I know the background-colors are irrelevant but they help to visualize it.
.container {
min-width: 768px;
width: 100%;
display: grid;
grid-template-columns: calc(100% - 380px) 1fr;
min-height: 100vh;
}
.col1 {
background-color: dodgerblue;
}
.col2 {
display: flex;
flex-direction: column;
}
.col2-row1 {
height: 200px;
background-color: orange;
}
.col2-row2 {
background-color: forestgreen;
height: 100%;
}
.col2-row3 {
height: 150px;
background-color: red;
}
#media (max-width: 768px) {
.container {
grid-template-columns: 1fr;
}
}
<div class="container">
<div class="col1">1</div>
<div class="col2">
<div class="col2-row1">2</div>
<div class="col2-row2">3</div>
<div class="col2-row3">4</div>
</div>
</div>
I don't want to explicitly define the number of columns so i can add other auto width children to it later.
I don't want to use extra wrappers.
I want to do it in CSS grid not flexbox (I can do it in flexbox with wrappers and all)
In case you are wondering its a layout for a navigation bar
Heres what i am trying to achieve
.container {
display: grid;
grid-template-columns: auto 1fr auto;
grid-gap: 5px;
align-items: flex-start;
margin-bottom: 10px;
}
.item--1,
.item--3 {
grid-column: 1fr;
width: 100px;
}
.item--2 {
color: #fff;
line-height: 100px;
text-align: center;
font-size: 30px;
}
.item {
height: 100px;
background: deepskyblue;
}
#media screen and (max-width: 768px) {
.container-1 {
grid-template-rows: auto auto;
}
.item--1 {
grid-column: 1 / 2;
}
.item--2 {
grid-row-start: 2;
grid-column: 1 / -1;
}
.item--3 {
grid-column: 3 / 4;
}
}
<div class="container">
<div class="item item--1"></div>
<div class="item item--2">Fill up remaining space</div>
<div class="item item--3"></div>
</div>
Here is an idea with flexbox and without extra wrapper:
.container {
display: flex;
grid-gap: 5px;
margin-bottom: 10px;
}
/* this is your gap */
.item:not(:last-child) {
margin-right: 5px;
}
/**/
.fill {
color: #fff;
line-height: 100px;
text-align: center;
font-size: 30px;
flex-grow: 1; /* fill the remaining space */
}
.item {
height: 100px;
width: 100px;
background: deepskyblue;
margin-bottom: 5px;
}
#media screen and (max-width: 768px) {
.container {
flex-wrap: wrap; /* allow the wrap */
}
.fill {
order: 2; /* make the element the last on*/
flex-basis: 100%; /* 100% width */
margin-right: 0!important;
}
.fill + * {
margin-left: auto; /* keep the element on the left */
}
}
<div class="container">
<div class="item"></div>
<div class="item fill">Fill up remaining space</div>
<div class="item"></div>
<div class="item"></div>
</div>
I'm working on this for hours but can not achieve a working solution. Basically, I want to combine a full-height column (left) with following rows (right) in a two-column-layout with CSS Flexbox.
The full-height column should match the height of the parent's div (.grid-main > main), which is a grid-layout on the other hand.
Screenshot of the issue:
So the yellow boxes should be next to the full-height column and not continue beneath it.
The column should match the height of .grid-main (which could be achieved with flex-direction: column, but all following divs are also listed in a column then).
HTML-Structure:
<div class="grid-main">
<header>...</header>
<nav>...</nav>
<main>
<div class="col-reports"></div>
<div class="classes"></div>
<div class="classes"></div>
<div class="classes"></div>
<div class="classes"></div>
...
</main>
<footer>...</footer>
</div>
CSS:
.grid-main {
display: grid;
height: 98vh;
width: 98vw;
overflow: hidden;
position: relative;
overflow: -moz-hidden-unscrollable;
grid-template-columns: 175px 1fr 1fr;
grid-template-rows: 0.1fr 1fr 0.05fr;
grid-template-areas:
"header header header"
"nav main main"
"footer footer footer";
animation: fadeIn 1s;
transition: 1s all ease-in-out;
}
.grid-main > main {
display: flex;
flex-direction: row;
flex-wrap: wrap;
align-items: flex-start;
place-content: flex-start leftjustify-content: flex-start space-evenly;
grid-area: main;
position: relative;
overflow-y: auto;
background: var(--color-accent-main);
}
.col-reports {
flex: 1;
height: 100%;
position: relative;
max-width: 250px;
padding: 20px;
background: rgba(204,204,204,.7);
box-shadow: 1px 1px 25px inset rgb(179, 179, 179);
font-size: .8rem;
font-weight: bold;
line-height: 200%;
}
.classes {
font-family: 'Lora';
line-height: 2rem;
background: #f6efe0;
border-radius: 5px;
padding: 20px;
margin: 10px;
border: 5px solid #eee9dd;
box-shadow: 0 0 5px rgba(0, 0, 0, 0.07);
animation: fadeInUp 1s;
}
Visualized the issue:
I solved the issue basically with the following code. So the hint from #Paulie_D was quite helpful, although I wanted to avoid Grid for this basic layouting.
.grid-reports {
display: grid; /* Grid in Grid */
height: 100%; /* In contrast to Flexbox, Grid can be used to assign height: 100% to a container.
It stretches to the parent container even if the viewport changes. Flexbox does not work with height actually.
Unless you use flex-direction: column; to the parent container. */
grid-template-rows: 1fr; /* optional */
grid-template-columns: 1fr 6fr;
grid-area: main; /* referes to Main in .grid-main */
}
.col-students {
grid-row: 1; /* .col-students must only be in the first row of .grid-reports to stretch */
grid-column: 1; /* Only the first column of .grid-reports */
max-width: 250px;
padding: 20px;
background: rgba(204,204,204,.7);
box-shadow: 1px 1px 25px inset rgb(179, 179, 179);
font-size: .8rem;
font-weight: bold;
line-height: 200%;
}
.col-reports {
grid-column: 2; /* All childs of .col-reports and itself are in the second column of .grid-reports
Note: grid-rows are automatically assigned, because they are not adressed any further */
display: flex; /* .col-reports becomes now a Flexbox to align its child items (box). */
flex-wrap: wrap; /* All child elements automatically break */
flex-direction: row; /* All child elements flow in a row */
align-self: flex-start; /* To align items next to each other and at start of Flex */
padding: 10px;
}
.col-reports .box { /* Further definitions of the element in .grid-main */
flex-basis: 45%; /* So the flex-basis in this case relates to the .col-reports
and not to the whole .grid-reports which makes sense and is desired behaviour.
45% means that 45% of .col-reports are used, which is in the second column. */
/*Note: This needs to be assigned as 100% in the mobile section, because elements
must be placed under each other for mobile devices. */
}
I'm trying to sort out a css grid to fit my imgs on this tribute page project from free code camp. I managed to do the grid as I wanted to but I can't seem to fit the images perfectly in each cell. Some of them are not filling the entire cell and others are exceeding it. This is the code:
.img-div-container {
display: grid;
grid-template-columns: 50% 25% 25%;
grid template-rows: 5px 5px;
margin-left: 100px;
margin-right: 100px;
grid-column-gap: 5px;
align-content: stretch;
justify-content: stretch;
background: hsla(199, 19%, 62%, 0.21);
border: 2px outset hsla(199, 19%, 62%, 0.21)
}
.image-bigger {
grid-column: 1/2;
grid-row: 1/3;
place-self: stretch;
;
}
.image-wider {
grid-column: 2/4;
grid-row: 2/3;
place-self: end stretch;
width: 95%;
}
.image-normal,
.image-bigger,
{
place-self: stretch;
justify-self: flex-start;
}
img {
width: 100%;
height: 87%;
}
.normal {
width: 100%;
height: auto;
}
<div class="img-div-container">
<div class="image-bigger"><img src="http://s2.glbimg.com/eP3_5jDhj_6tF-nyyiGpPOKdHNh8tT68kXTqIHZg3lBrXaqmUDsPSdlfxwreNWMq/e.glbimg.com/og/ed/f/original/2012/10/29/754_carlos_marighella.jpg"></div>
<div class="image-normal"><img class="resize" src="https://drupal-multisite-s3.s3-us-west-2.amazonaws.com/files/marighella2.jpg"></div>
<div class="image-normal"><img class="normal" src="http://www.cartografiasdaditadura.org.br/files/2014/12/Carlos_Marighella.jpg"></div>
<div class="image-wider"><img class="normal" id="bigode" src="http://memoriasdaditadura.org.br/wp-content/uploads/2014/11/mariguella4-e1471390559677-600x286.jpg"></div>
</div>
I'm sorry the code got a little bit messy when trying to fix this.
The biggest change I did is to add the property object-fit to your images:
img {
width: 100%;
height: 100%;
display: block;
object-fit: cover;
}
https://www.w3schools.com/css/css3_object-fit.asp
For the rest, I have only commented on some of your rules that I considered unnecessary to this work:
.img-div-container {
display: grid;
grid-template-columns: 50% 25% 25%;
/*grid-template-rows: 5px 5px;*/
margin-left: 100px;
margin-right: 100px;
grid-gap: 5px;
/*align-content: stretch;
justify-content: stretch;*/
background: hsla(199, 19%, 62%, 0.21);
border: 2px outset hsla(199, 19%, 62%, 0.21);
overflow:hidden;
}
.image-bigger {
grid-column: 1/2;
grid-row: 1/3;
/*place-self: stretch;*/
}
.image-wider {
grid-column: 2/4;
grid-row: 2/3;
/*place-self: end stretch;
width: 95%;*/
}
/*.image-normal,
.image-bigger,
{
place-self: stretch;
justify-self: flex-start;
}*/
img {
width: 100%;
height: 100%;
display:block;
object-fit: cover;
}
/*.normal {
width: 100%;
height: auto;
}*/
<div class="img-div-container">
<div class="image-bigger"><img src="http://s2.glbimg.com/eP3_5jDhj_6tF-nyyiGpPOKdHNh8tT68kXTqIHZg3lBrXaqmUDsPSdlfxwreNWMq/e.glbimg.com/og/ed/f/original/2012/10/29/754_carlos_marighella.jpg"></div>
<div class="image-normal"><img class="resize" src="https://drupal-multisite-s3.s3-us-west-2.amazonaws.com/files/marighella2.jpg"></div>
<div class="image-normal"><img class="normal" src="http://www.cartografiasdaditadura.org.br/files/2014/12/Carlos_Marighella.jpg"></div>
<div class="image-wider"><img class="normal" id="bigode" src="http://memoriasdaditadura.org.br/wp-content/uploads/2014/11/mariguella4-e1471390559677-600x286.jpg"></div>
</div>
Try to give your grid grid-template-areas
and then grid-area to each div accordingly,
for example:
HTML
<div class="grid-container">
<div class="verticalphoto"></div>
<div class="photo1"></div>
<div class="photo2"></div>
</div>
CSS
.grid-container {
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr;
grid-template-rows: 1fr 1fr 1fr;
grid-template-areas:
"verticalphoto photo1 . ." "verticalphoto photo2 . ." ". . . .";
}
.verticalphoto { grid-area: verticalphoto; }
.photo1 { grid-area: photo1; }
.photo2 { grid-area: photo2; }
to fit the image, try,
img {
width: 100%;
height: 100%;
display: block;
object-fit: cover;
}
you are using
display: grid;
grid-template-columns: 50% 25% 25%;
grid template-rows: 5px 5px;
which seems coherent 3 colums and 2 rows.
I would use
display:grid;
grid-template-columns: 50% 25% 25%;
grid-template-rows:1fr 1fr;
to avoid a fixed value and let the browser manage sizing for the rows.
Then , you use
.image-wider {
grid-column: 2/4;
grid-row: 2/3;
}
Which would work perfectly with a grid-template-areas if areas described 4 columns and 3 rows, which is obviously not the case here (you setted 3 columns and 2 rows ) .
I would safely use here for a grid-template-columns / grid-template-rows :
.image-wider {
grid-column: 2 / span 2; /* set in the second column and span through 2 columns */
grid-row: 2;/* not really needed here since it is already standing in the last empty grid cell avalaible */
}
tell only how many cell there is to span through instead telling go from cell 2 to cell 4 (grid-template-areas was not set ! )
When using flex or grid, if you are unfamiliar with it, make it into steps as simple as possible .
You could have start to build your grid layout with a few extra class to make it easier to read at first and easier to tune later.
the row-gap also seems to me more alike a margin-bottom for the first 2 small grid.
code example broken into pieces to show where to dispatch each containers ;)
.grid {
display:grid;
margin:0 100px;
grid-template-columns: 50% 25% 25%;
grid-template-rows:1fr 1fr;
}
.c1 {
grid-column:1;
}
.c2 {
grid-column:2;a
}
.c3 {
grid-column:3;
}
.c23 {
grid-column:2/ span 3;
}
.r1 {
grid-row:1;
}
.r2 {
grid-row:2;
}
.r12 {
grid-row:1/ span2;
}
.image-normal {
margin-bottom:5px;
}
/* whatever size is needed , object-fit can also be used to clip and avoid pixel stretching */
img {
height:100%;
width:100%;
}
<div class="img-div-container grid">
<div class="image-bigger c1 r12">
<img src="http://s2.glbimg.com/eP3_5jDhj_6tF-nyyiGpPOKdHNh8tT68kXTqIHZg3lBrXaqmUDsPSdlfxwreNWMq/e.glbimg.com/og/ed/f/original/2012/10/29/754_carlos_marighella.jpg">
</div>
<div class="image-normal c2 r1">
<img class="resize" src="https://drupal-multisite-s3.s3-us-west-2.amazonaws.com/files/marighella2.jpg">
</div>
<div class="image-normal c3 r1">
<img class="normal" src="http://www.cartografiasdaditadura.org.br/files/2014/12/Carlos_Marighella.jpg">
</div>
<div class="image-wider c23 r2">
<img class="normal" id="bigode" src="http://memoriasdaditadura.org.br/wp-content/uploads/2014/11/mariguella4-e1471390559677-600x286.jpg">
</div>
</div>
Looks like you mixed grid-template-areas and grid-template-rows (-columns) to fill your grid .