I have a series of images that are fetched from a database, and when three or more images are added it visually shows the three columns.
When less than three images are present, because I'm using display: grid; it is currently justified to the left of the parent container (in the code example I've just used red boxes to represent the images).
Is there anyway of having it so that when one or two images are present these are justified to the centre of the parent element. I appreciate I could use javascript to detect how many images are present and if it is less than three, add a class and change the wrapper to display: flex, but I wondered if such a layout was possible with CSS only?
Due to the nature of the layout I do need to use CSS Grid when more than three images are present.
Note: I've commented out two of the red boxes in the HTML to show the initial issue when only one red box is present.
Codepen: https://codepen.io/anna_paul/pen/xxXrVJQ
body {
display: flex;
justify-content: center;
margin: 0
width: 100%;
height: 100vh;
}
.wrapper {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-gap: 1rem;
max-width: 1250px;
}
.box {
width: 200px;
height: 200px;
background: red;
}
<div class="wrapper">
<div class="box"></div>
<!-- <div class="box"></div>
<div class="box"></div> -->
</div>
Do it like below:
.wrapper {
display: grid;
grid-auto-flow:column; /* column flow */
justify-content:center; /* center everything */
grid-gap: 1rem;
max-width: 600px;
border:1px solid;
margin:10px auto;
}
/* make sure you only have 3 columns*/
.box:nth-child(3n + 1) {grid-column:1}
.box:nth-child(3n + 2) {grid-column:2}
.box:nth-child(3n + 3) {grid-column:3}
/**/
.box {
width: 100px;
height: 100px;
background: red;
}
<div class="wrapper">
<div class="box"></div>
</div>
<div class="wrapper">
<div class="box"></div>
<div class="box"></div>
</div>
<div class="wrapper">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
<div class="wrapper">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
<div class="wrapper">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
<div class="wrapper">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
Because you are using 1fr for each column, even if a column has no content it is taking 33% of the free space. You need to specify units other than fr(fraction of the available space) unit:
grid-template-columns: auto auto auto;
grid-template-columns: repeat(3, auto);
grid-template-columns: repeat(3, minmax(min-content, max-content));
Use any of the above. There is a small difference between auto and minmax(min-content, max-content).
Following is the demo with 3 containers with 1, 2 and >3 items respectively:
body {
margin: 0;
width: 100%;
height: 100vh;
}
.demo {
display: flex;
justify-content: center;
}
.wrapper {
display: grid;
grid-template-columns: repeat(3, minmax(min-content, max-content));
grid-gap: 1rem;
width: auto;
max-width: 1250px;
}
.box {
width: 200px;
height: 200px;
background: red;
border: 1px solid;
}
<p>Grid with one item</p>
<div class="demo">
<div class="wrapper">
<div class="box">1</div>
</div>
</div>
<hr>
<p>Grid with two items</p>
<div class="demo">
<div class="wrapper">
<div class="box">1</div>
<div class="box">2</div>
</div>
</div>
<hr>
<p>Grid with >3 items</p>
<div class="demo">
<div class="wrapper">
<div class="box">1</div>
<div class="box">2</div>
<div class="box">3</div>
<div class="box">4</div>
</div>
</div>
The 1rem grid-gap will remain even if the column has 0 width. So in your setup, grid inside flex, the item in one item grid will be off by 2rem(2grid-gaps) from the center. If this is not a big deal then no worries.
But if you want exact center then you need to make grid-gap:0. And use spacing in side grid items(.box) like margin: 0.5rem; or padding:0.5rem to make artificial grid-gap.
body {
margin: 0;
width: 100%;
height: 100vh;
}
.demo {
display: flex;
justify-content: center;
}
.wrapper {
display: grid;
grid-template-columns: repeat(3, minmax(min-content, max-content));
width: auto;
max-width: 1250px;
}
.box {
width: 200px;
height: 200px;
background: red;
border: 1px solid;
margin: 0.5rem;
}
<p>Grid with one item</p>
<div class="demo">
<div class="wrapper">
<div class="box">1</div>
</div>
</div>
<hr>
<p>Grid with two items</p>
<div class="demo">
<div class="wrapper">
<div class="box">1</div>
<div class="box">2</div>
</div>
</div>
<hr>
<p>Grid with >3 items</p>
<div class="demo">
<div class="wrapper">
<div class="box">1</div>
<div class="box">2</div>
<div class="box">3</div>
<div class="box">4</div>
</div>
</div>
using auto instead of fr and using align-content solve your problem.
body {
display: flex;
justify-content: center;
margin: 0
width: 100%;
height: 100vh;
}
.wrapper {
display: grid;
grid-template-columns: auto auto auto;
align-content : start;
/* grid-gap: 1rem; */
max-width: 1250px;
}
.box {
width: 200px;
height: 200px;
background: red;
margin: 1rem ;
}
<div class="wrapper">
<div class="box"></div>
<!-- <div class="box"></div>
<div class="box"></div> -->
</div>
Related
Is it possible to define a grid with a maximum number of columns, but allow elements to wrap onto new rows when the screen width changes?
I have implemented classes that allow rows to wrap onto new rows, but there is no maximum number of columns.
Here is a CodePen of one method using Flexbox:
CSS:
.flex-container {
display: flex;
flex-wrap: wrap;
}
Another method is to use a grid:
.grid {
display: grid;
counter-reset: grid-items;
position: relative;
}
.grid--auto-fit {
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
}
I want a fairly generic solution to this. Is what I want to achieve possible without JavaScript or media queries?
With CSS grid you can consider the use of max(width, 100%/N) where N is the maximum number of columns. If the width of the container increases, 100%/N will for sure be bigger than width, thus we won't have more than N elements per row.
.grid-container {
--n: 4; /* The maximum number of columns */
display: grid;
grid-template-columns: repeat(auto-fill, minmax(max(200px, 100%/var(--n)), 1fr));
}
.grid-item {
background: tomato;
padding: 5px;
height: 50px;
margin: 10px;
line-height: 50px;
color: white;
font-weight: bold;
font-size: 2em;
text-align: center;
box-sizing: border-box;
}
<div class="grid-container">
<div class="grid-item">1</div>
<div class="grid-item">2</div>
<div class="grid-item">3</div>
<div class="grid-item">4</div>
<div class="grid-item">5</div>
<div class="grid-item">6</div>
<div class="grid-item">7</div>
<div class="grid-item">8</div>
</div>
<div class="grid-container" style="--n:3">
<div class="grid-item">1</div>
<div class="grid-item">2</div>
<div class="grid-item">3</div>
<div class="grid-item">4</div>
<div class="grid-item">5</div>
<div class="grid-item">6</div>
<div class="grid-item">7</div>
<div class="grid-item">8</div>
</div>
With gaps:
.grid-container {
--n: 4; /* The maximum number of columns */
display: grid;
grid-template-columns: repeat(auto-fill,
minmax(max(200px,(100% - (var(--n) - 1)*10px)/var(--n)), 1fr));
gap: 10px;
margin: 5px;
}
.grid-item {
background: tomato;
padding: 5px;
height: 50px;
line-height: 50px;
color: white;
font-weight: bold;
font-size: 2em;
text-align: center;
box-sizing: border-box;
}
<div class="grid-container">
<div class="grid-item">1</div>
<div class="grid-item">2</div>
<div class="grid-item">3</div>
<div class="grid-item">4</div>
<div class="grid-item">5</div>
<div class="grid-item">6</div>
<div class="grid-item">7</div>
<div class="grid-item">8</div>
</div>
<div class="grid-container" style="--n:3">
<div class="grid-item">1</div>
<div class="grid-item">2</div>
<div class="grid-item">3</div>
<div class="grid-item">4</div>
<div class="grid-item">5</div>
<div class="grid-item">6</div>
<div class="grid-item">7</div>
<div class="grid-item">8</div>
</div>
With flexbox, you can simply set a max-width to the container since your elements have a fixed width:
.flex-container {
display: flex;
flex-wrap: wrap;
max-width: calc(5*(200px + 20px));
}
.flex-item {
background: tomato;
padding: 5px;
width: 200px;
height: 100px;
margin: 10px;
line-height: 100px;
color: white;
font-weight: bold;
font-size: 2em;
text-align: center;
box-sizing: border-box;
}
<div class="flex-container wrap">
<div class="flex-item">1</div>
<div class="flex-item">2</div>
<div class="flex-item">3</div>
<div class="flex-item">4</div>
<div class="flex-item">5</div>
<div class="flex-item">6</div>
<div class="flex-item">7</div>
<div class="flex-item">8</div>
</div>
The only drawback is that you need to know the width of your elements and their margin to correctly set the max-width.
If you want your elements to expand and cover all the width, you can use a trick with min-width like below:
.flex-container {
display: flex;
flex-wrap: wrap;
}
.flex-item {
background: tomato;
padding: 5px;
min-width: 200px;
width: calc(100%/5 - 20px); /* 5 columns */
height: 100px;
margin: 10px;
line-height: 100px;
color: white;
font-weight: bold;
font-size: 2em;
text-align: center;
box-sizing: border-box;
}
<div class="flex-container wrap">
<div class="flex-item">1</div>
<div class="flex-item">2</div>
<div class="flex-item">3</div>
<div class="flex-item">4</div>
<div class="flex-item">5</div>
<div class="flex-item">6</div>
<div class="flex-item">7</div>
<div class="flex-item">8</div>
</div>
Here also you need to consider the margin. You can easily make this more flexible using CSS variables:
.flex-container {
display: flex;
flex-wrap: wrap;
}
.flex-item {
--m: 10px;
background: tomato;
padding: 5px;
min-width: 200px;
width: calc(100%/5 - 2*var(--m)); /* 5 columns */
height: 100px;
margin: var(--m);
line-height: 100px;
color: white;
font-weight: bold;
font-size: 2em;
text-align: center;
box-sizing: border-box;
}
<div class="flex-container wrap">
<div class="flex-item">1</div>
<div class="flex-item">2</div>
<div class="flex-item">3</div>
<div class="flex-item">4</div>
<div class="flex-item">5</div>
<div class="flex-item">6</div>
<div class="flex-item">7</div>
<div class="flex-item">8</div>
</div>
You can also consider flex-grow if you want your element to always expand (even when there is a wrap), but you may face the issue of the last row that you need to fix with some hacks:
.flex-container {
display: flex;
flex-wrap: wrap;
--m: 10px;
}
.flex-item {
background: tomato;
padding: 5px;
min-width: 200px;
flex-grow: 1;
width: calc(100%/5 - 2*var(--m)); /* 5 columns */
height: 100px;
margin: var(--m);
line-height: 100px;
color: white;
font-weight: bold;
font-size: 2em;
text-align: center;
box-sizing: border-box;
}
.flex-container span {
min-width: 200px;
flex-grow: 1;
width: calc(100%/5 - 2*var(--m)); /* 5 columns */
margin: 0 var(--m);
}
<div class="flex-container wrap">
<div class="flex-item">1</div>
<div class="flex-item">2</div>
<div class="flex-item">3</div>
<div class="flex-item">4</div>
<div class="flex-item">5</div>
<div class="flex-item">6</div>
<div class="flex-item">7</div>
<div class="flex-item">8</div>
<!-- 4 empty elements to fix the issue (we can also use a pseudo element) -->
<span></span>
<span></span>
<span></span>
<span></span>
</div>
In the example below, we made the number of columns to be 5 so we will need at least 4 empty elements to fix the issue in case we will have one to 4 elements in the last row.
Of course, this is a drawback, but since you know the number of columns you can easily set those empty elements and you won't need any JavaScript.
To make it more flexible, here is an idea with CSS variables:
.flex-container {
display: flex;
flex-wrap: wrap;
border: 1px solid;
--m: 10px;
--n: 5;
--width: 150px;
}
.flex-item {
background: tomato;
min-width: var(--width);
flex-grow: 1;
width: calc(100%/var(--n) - 2*var(--m));
height: 50px;
margin: var(--m);
box-sizing: border-box;
}
.flex-container span {
display: contents; /* Each span will give us 2 elements */
}
.flex-container span: before,
.flex-container span: after,
.flex-container: before,
.flex-container: after{
content: "";
min-width: var(--width);
flex-grow: 1;
width: calc(100%/var(--n) - 2*var(--m));
margin :0 var(--m);
order: 1; /* We make sure they are at the end */
}
<div class="flex-container wrap">
<div class="flex-item">1</div>
<div class="flex-item">2</div>
<div class="flex-item">3</div>
<div class="flex-item">4</div>
<div class="flex-item">5</div>
<div class="flex-item">6</div>
<div class="flex-item">7</div>
<div class="flex-item">8</div>
<!-- A lot of elements !! -->
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
</div>
<div class="flex-container wrap" style="--n:10">
<div class="flex-item">1</div>
<div class="flex-item">2</div>
<div class="flex-item">3</div>
<div class="flex-item">4</div>
<div class="flex-item">5</div>
<div class="flex-item">6</div>
<div class="flex-item">7</div>
<div class="flex-item">8</div>
<!-- A lot of elements !! -->
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
</div>
<div class="flex-container wrap" style="--n:3">
<div class="flex-item">1</div>
<div class="flex-item">2</div>
<div class="flex-item">3</div>
<div class="flex-item">4</div>
<div class="flex-item">5</div>
<div class="flex-item">6</div>
<div class="flex-item">7</div>
<div class="flex-item">8</div>
<!-- A lot of elements !! -->
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
</div>
I used display: contents to be able to set N empty elements that will later be considered as 2*N which can reduce the code.
If you will have 7 columns, we will only need 6 extra elements. We can use the two pseudo elements then only 2 empty element to cover the remaining 4.
You can't explicitly do it either for a flexbox or for a CSS grid - but you can use a hack using CSS variables (usually that's all you need).
CSS Grid Layout
For instance, you can set the global column number in the :root while a specific column number on the grid wrapper - see a CSS grid below with four columns set globally:
:root {
--columns: 3;
}
.grid {
display: grid;
grid-gap: 10px;
/* Adjusting for the 10px grid-gap as well */
grid-template-columns: repeat(auto-fit, minmax(calc(100% / var(--columns) - 20px), 1fr));
}
.grid > * {
background-color: green;
height: 200px;
}
<div class="grid">
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
<div>6</div>
</div>
Now you can set a rule for the number of columns on the grid container by redeclaring --columns (or you can have JavaScript add a class that contains the --columns declaration) - see the demo below:
:root {
--columns: 3;
}
.grid {
display: grid;
grid-gap: 10px;
--columns: 4; /* Redefine the number of columns */
grid-template-columns: repeat(auto-fit, minmax(calc(100% / var(--columns) - 20px), 1fr));
}
.grid > * {
background-color: green;
height: 200px;
}
<div class="grid">
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
<div>6</div>
</div>
Flexbox
Similar arguments are valid for flexboxes - see a simplified demo below:
:root {
--columns: 3;
}
.flexbox {
display: flex;
flex-wrap: wrap;
--columns: 4; /* Redefine the number of columns */
}
.flexbox > * {
background-color: green;
height: 200px;
margin: 10px;
flex-basis: calc(100% / var(--columns) - 20px);
}
<div class="flexbox">
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
<div>6</div>
</div>
With a little bit of math, you can add a percentage in a maximum function within the minmax. That way, it will break at 200 pixels, but expand to fill 1/3 of the page (in this case because I used 33%. Just add whatever percentage you want there though).
grid-template-columns: repeat(auto-fit, minmax(max(200px, 33%), 1fr));
I have a layout that is a sidebar and a grid both wrapped in a flexbox. I'd like to put a div underneath the grid so it can have prev/next buttons, like in this image, but I can't figure out how to do that. The grid resizes itself with the window so the grid can take as many rows as necessary and then the div should go below that, and be as wide as the grid.
This is what I have, but the div is on the right of the grid:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Boardgame Database</title>
<style>
html,
body {
height: 100%;
margin: 0;
padding: 0;
}
aside {
background-color: red;
flex: 1;
min-width: 250px;
}
.grid-container {
flex: 4;
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
}
.grid-item {
border: 1px solid black;
padding: 20px;
font-size: 24px;
text-align: center;
overflow: hidden;
}
#flex-container {
display: flex;
flex-direction: row;
min-height: 100vh;
}
</style>
</head>
<body>
<div id="flex-container">
<aside class="sidebar">
</aside>
<section class="grid-container">
<div class="grid-item">1</div>
<div class="grid-item">2</div>
<div class="grid-item">3</div>
<div class="grid-item">4</div>
<div class="grid-item">5</div>
<div class="grid-item">6</div>
<div class="grid-item">7</div>
<div class="grid-item">8</div>
<div class="grid-item">9</div>
<div class="grid-item">10</div>
<div class="grid-item">11</div>
<div class="grid-item">12</div>
<div class="grid-item">13</div>
<div class="grid-item">14</div>
<div class="grid-item">15</div>
<div class="grid-item">16</div>
<div class="grid-item">17</div>
<div class="grid-item">18</div>
</section>
<div id="page-buttons">
prev
next
</div>
</div>
Checkout the following Code.
#main{
display :flex;
}
#sidebar{
width:70px;
height: 300px;
border: solid black 1px;
}
#grid-area{
width:200px;
height: 300px;
border: solid black 1px;
display: block;
}
#grid{
width:200px;
height: 250px;
border: solid black 1px;
display: block;
}
<div id="main">
<div id="sidebar"></div>
<div id="grid-area">
<div id="grid"></div>
<div id="button">next / prev</div>
</div>
</div>
You should use nested flex containers. Section and bottom div should be wrapped inside another flex container with flex direction to column.
So outer flex will make sidebar & inner flex container to be side by side.
Or just use a normal div container instead of flex.
here is another example only with grid keeping the pre/next button at the bottom of the viewport:
body {
margin: 0;
}
#grid-container {
display: grid;
height: 100vh;
grid-template-columns: minmax(250px, 1fr) 4fr;
grid-template-rows: 1fr auto;
}
aside {
background-color: red;
border: 1px solid;
margin: 0.25em;
grid-row: span 2;
grid-column: 1;
}
section,
#page-buttons {
grid-column: 2;
border: solid 1px;
margin: 0.25em;
}
section {
overflow: auto;
}
#page-buttons {
display: flex;
gap: 1em;
padding: 0.5em;
background: lightgray;
justify-content: center;
}
.grid-item {
border: 1px solid black;
padding: 20px;
font-size: 24px;
text-align: center;
overflow: hidden;
}
<div id="grid-container">
<aside class="sidebar">
</aside>
<section class="grid-container">
<div class="grid-item">1</div>
<div class="grid-item">2</div>
<div class="grid-item">3</div>
<div class="grid-item">4</div>
<div class="grid-item">5</div>
<div class="grid-item">6</div>
<div class="grid-item">7</div>
<div class="grid-item">8</div>
<div class="grid-item">9</div>
<div class="grid-item">10</div>
<div class="grid-item">11</div>
<div class="grid-item">12</div>
<div class="grid-item">13</div>
<div class="grid-item">14</div>
<div class="grid-item">15</div>
<div class="grid-item">16</div>
<div class="grid-item">17</div>
<div class="grid-item">18</div>
</section>
<div id="page-buttons">
prev
next
</div>
</div>
That's a prime example of something that CSS Grid will do better than flexbox. Something like this:
#container{
display: flex;
width:100%;
height:100%;
}
#wrapper {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
outline: 1px solid red;
width: 72%;
height: 100%;
padding: 24px 0px;
box-sizing: border-box;
}
.item {
background-color: yellow;
height: 30px;
margin: 15px;
max-width:110px;
border-radius: 8px;
cursor: pointer;
}
Here the cards looks good as the number of cards are more
<div id ="container">
<div id="wrapper">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
</div>
<hr/>
we have so much white space between cards, how can we get rid of the space as the cards can be dynamic like 2 or 1. and a max of 3 per container
<div id ="container">
<div id="wrapper">
<div class="item"></div>
<div class="item"></div>
</div>
</div>
How can we have the space between grids and make them left aligned so that it , fits correctly as the top cards, dynamically adjust using Css Grids or is there any efficient way of achieving this.
Note - One thing that blocks me here is we cannot have a fixed width and then have the grid at 3 columns as we donot want to have empty spaces when the container is resized
You could remove the minmax(100px, 1fr) and just use a fixed column width. Here is an example:
#container {
display: flex;
width: 100%;
height: 100%;
}
#wrapper {
display: grid;
grid-template-columns: repeat(auto-fit, 100px);
outline: 1px solid red;
width: 72%;
height: 100%;
padding: 24px 0px;
box-sizing: border-box;
}
.item {
background-color: yellow;
height: 30px;
margin: 15px;
max-width: 110px;
border-radius: 8px;
cursor: pointer;
}
Here the cards looks good as the number of cards are more
<div id="container">
<div id="wrapper">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
</div>
<hr/> we have so much white space between cards, how can we get rid of the space as the cards can be dynamic like 2 or 1. and a max of 3 per container
<div id="container">
<div id="wrapper">
<div class="item"></div>
<div class="item"></div>
</div>
</div>
You can use this code
body {
margin: 15px;
}
.three-col-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
outline: 1px solid red;
width: 72%;
height: 100%;
padding: 24px 0px;
box-sizing: border-box;
}
.l-wrap {
margin-right: auto;
margin-left: auto;
display: flex;
}
.grid-item {
margin-top: 0px;
padding-left: 12px;
padding-right: 12px;
float: left;
}
.grid-inner {
display: flex;
justify-content: center;
align-items: center;
text-align: center;
background-color: yellow;
height: 30px;
margin: 15px;
max-width: 200px;
border-radius: 8px;
}
Here the cards looks good as the number of cards are more
<div class="l-wrap">
<div class="three-col-grid">
<div class="grid-item">
<div class="grid-inner">Grid item</div>
</div>
<div class="grid-item">
<div class="grid-inner">Grid item</div>
</div>
<div class="grid-item">
<div class="grid-inner">Grid item</div>
</div>
<div class="grid-item">
<div class="grid-inner">Grid item</div>
</div>
<div class="grid-item">
<div class="grid-inner">Grid item</div>
</div>
</div>
</div>
<br><br>we have so much white space between cards, how can we get rid of the space as the cards can be dynamic like 2 or 1. and a max of 3 per container
<div class="l-wrap">
<div class="three-col-grid">
<div class="grid-item">
<div class="grid-inner">Grid item</div>
</div>
<div class="grid-item">
<div class="grid-inner">Grid item</div>
</div>
</div>
</div>
OK, I edited my question and code to easily show what I mean. I need to have:
"menu" - positioned-left, min-height=500px, width=250px - at all times.
"content" - positioned on the right side of "menu", dynamic width to take all remaining space.
Same height for "menu" and "content" at all times. No matter there will be 1 box or 100 inside "content".
"Boxes" should be lined up from left to right and if there are more, they should stretch height of "content" and "menu" should follow the same height.
<div class="header" style="height:150px; background-color:black;" >
</div>
<div class="navbar" style="height:40px; background-color:yellow;" >
</div>
<div class="menu" style="min-height:500px; width:250px; background-color:orange; float:left;" >
</div>
<div class="content" style="height:auto; background-color:blue; float: left; " >
<?php for ($col = 0; $col < 50; $col++)
{
?><div class="box" style="width:80px; height:80px; background-color:white; margin:10px;" ></div><?php
}
?>
</div>
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
div {
border: 1px solid black
}
body {
display: grid;
grid-template-columns: 250px 1fr;
grid-template-rows: 150px 40px minmax(500px , 1fr)
}
.header, .navbar {
grid-column: 1 / -1
}
.content {
display: grid;
grid-gap: 20px;
padding: 20px;
grid-template-columns: repeat(auto-fill, 80px);
align-content: start;
justify-content: space-evenly;
}
.box {
width: 80px;
height: 80px;
}
<body>
<div class='header'>
Header
</div>
<div class='navbar'>
Navbar
</div>
<div class='menu'>
Menu
</div>
<div class='content'>
<div class='box'>box</div>
<div class='box'>box</div>
<div class='box'>box</div>
<div class='box'>box</div>
<div class='box'>box</div>
<div class='box'>box</div>
<div class='box'>box</div>
<div class='box'>box</div>
<div class='box'>box</div>
<div class='box'>box</div>
<div class='box'>box</div>
<div class='box'>box</div>
<div class='box'>box</div>
<div class='box'>box</div>
<div class='box'>box</div>
<div class='box'>box</div>
</div>
</body>
Your goal is easier to achieve with flexbox, as shown in the solution below.
.header {
height: 150px;
background-color: black;
}
.navbar {
height: 40px;
background-color: yellow;
}
.container {
min-height: 500px;
display: flex;
align-items: flex-start;
}
.menu {
min-height: 500px;
height: 100%;
width: 250px;
background-color: orange;
}
.content {
min-height: 500px;
background-color: blue;
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: center;
}
.box {
width: 80px;
height: 80px;
background-color: white;
margin: 10px;
}
<div class="header">
</div>
<div class="navbar">
</div>
<div class="container">
<div class="menu">
</div>
<div class="content">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
</div>
What I thought would be a simple layout turned out to be something I'm not able to accomplish yet.
I need the grid to be responsive and spread from one side to another (it has to be aligned with the text and box above).
I tried a few options, I commented them out for easier checking:
.big-container {
padding: 0 20%;
}
.header {
width: 100%;
height: 50px;
background-color: blue;
}
.container {
border: 1px solid black;
/* display: flex;
flex-wrap: wrap;
*/
/* display: flex;
flex-wrap: wrap;
justify-content: space-between;
*/
}
.box {
border: 1px solid black;
width: 100px;
height: 30px;
background-color: yellow;
/* float: left;
margin-left: 10px; */
}
<div class="big-container">
<div class="header"></div>
<p>Text</p>
<div class="container">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
</div>
I tried with flex but it doesn't sort nicely the last row, flex-wrap: wrap and float:left with some margin doesn't align correctly to the left.
If you use flexbox and set justify-content: space-between then last row will also have the same spacing instead of left align. Instead you can use grid-layout for this.
.big-container {
padding: 0 20%;
}
.header {
width: 100%;
height: 50px;
background-color: blue;
}
.container {
border: 1px solid black;
display: grid;
justify-content: space-between;
grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
grid-gap: 10px;
}
.box {
border: 1px solid black;
height: 30px;
background-color: yellow;
}
<div class="big-container">
<div class="header"></div>
<p>Text</p>
<div class="container">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
</div>