I'm using a flex box to display 8 items that will dynamically resize with my page. How do I force it to split the items into two rows? (4 per row)?
Here is a relevant snip:
(Or if you prefer jsfiddle - http://jsfiddle.net/vivmaha/oq6prk1p/2/)
.parent-wrapper {
height: 100%;
width: 100%;
border: 1px solid black;
}
.parent {
display: flex;
font-size: 0;
flex-wrap: wrap;
margin: -10px 0 0 -10px;
}
.child {
display: inline-block;
background: blue;
margin: 10px 0 0 10px;
flex-grow: 1;
height: 100px;
}
<body>
<div class="parent-wrapper">
<div class="parent">
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
</div>
</div>
</body>
You've got flex-wrap: wrap on the container. That's good, because it overrides the default value, which is nowrap (source). This is the reason items don't wrap to form a grid in some cases.
In this case, the main problem is flex-grow: 1 on the flex items.
The flex-grow property doesn't actually size flex items. Its task is to distribute free space in the container (source). So no matter how small the screen size, each item will receive a proportional part of the free space on the line.
More specifically, there are eight flex items in your container. With flex-grow: 1, each one receives 1/8 of the free space on the line. Since there's no content in your items, they can shrink to zero width and will never wrap.
The solution is to define a width on the items. Try this:
.parent {
display: flex;
flex-wrap: wrap;
}
.child {
flex: 1 0 21%; /* explanation below */
margin: 5px;
height: 100px;
background-color: blue;
}
<div class="parent">
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
</div>
With flex-grow: 1 defined in the flex shorthand, there's no need for flex-basis to be 25%, which would actually result in three items per row due to the margins.
Since flex-grow will consume free space on the row, flex-basis only needs to be large enough to enforce a wrap. In this case, with flex-basis: 21%, there's plenty of space for the margins, but never enough space for a fifth item.
Add a width to the .child elements. I personally would use percentages on the margin-left if you want to have it always 4 per row.
DEMO
.child {
display: inline-block;
background: blue;
margin: 10px 0 0 2%;
flex-grow: 1;
height: 100px;
width: calc(100% * (1/4) - 10px - 1px);
}
Here is another apporach.
You can accomplish it in this way too:
.parent{
display: flex;
flex-wrap: wrap;
}
.child{
width: 25%;
box-sizing: border-box;
}
Sample:
https://codepen.io/capynet/pen/WOPBBm
And a more complete sample:
https://codepen.io/capynet/pen/JyYaba
I would do it like this using negative margins and calc for the gutters:
.parent {
display: flex;
flex-wrap: wrap;
margin-top: -10px;
margin-left: -10px;
}
.child {
width: calc(25% - 10px);
margin-left: 10px;
margin-top: 10px;
}
Demo: https://jsfiddle.net/9j2rvom4/
Alternative CSS Grid Method:
.parent {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-column-gap: 10px;
grid-row-gap: 10px;
}
Demo: https://jsfiddle.net/jc2utfs3/
For more detail you can follow this Link
.parent{
display: flex;
flex-wrap: wrap;
}
.parent .child{
flex: 1 1 25%;
/*Start Run Code Snippet output CSS*/
padding: 5px;
box-sizing: border-box;
text-align: center;
border: 1px solid #000;
/*End Run Code Snippet output CSS*/
}
<div class="parent">
<div class="child">1</div>
<div class="child">2</div>
<div class="child">3</div>
<div class="child">4</div>
<div class="child">5</div>
<div class="child">6</div>
<div class="child">7</div>
<div class="child">8</div>
</div>
I believe this example is more barebones and easier to understand then #dowomenfart.
.child {
display: inline-block;
margin: 0 1em;
flex-grow: 1;
width: calc(25% - 2em);
}
This accomplishes the same width calculations while cutting straight to the meat. The math is way easier and em is the new standard due to its scalability and mobile-friendliness.
.parent-wrapper {
height: 100%;
width: 100%;
border: 1px solid black;
}
.parent {
display: flex;
font-size: 0;
flex-wrap: wrap;
margin-right: -10px;
margin-bottom: -10px;
}
.child {
background: blue;
height: 100px;
flex-grow: 1;
flex-shrink: 0;
flex-basis: calc(25% - 10px);
}
.child:nth-child(even) {
margin: 0 10px 10px 10px;
background-color: lime;
}
.child:nth-child(odd) {
background-color: orange;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style type="text/css">
</style>
</head>
<body>
<div class="parent-wrapper">
<div class="parent">
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
</div>
</div>
</body>
</html>
;)
Flex wrap + negative margin
Why flex vs. display: inline-block?
Flex gives more flexibility with elements sizing
Built-in white spacing collapsing (see 3 inline-block divs with exactly 33% width not fitting in parent)
Why negative margin?
Either you use SCSS or CSS-in-JS for the edge cases (i.e. first element in column), or you set a default margin and get rid of the outer margin later.
Implementation
https://codepen.io/zurfyx/pen/BaBWpja
<div class="outerContainer">
<div class="container">
<div class="elementContainer">
<div class="element">
</div>
</div>
...
</div>
</div>
:root {
--columns: 2;
--betweenColumns: 20px; /* This value is doubled when no margin collapsing */
}
.outerContainer {
overflow: hidden; /* Hide the negative margin */
}
.container {
background-color: grey;
display: flex;
flex-wrap: wrap;
margin: calc(-1 * var(--betweenColumns));
}
.elementContainer {
display: flex; /* To prevent margin collapsing */
width: calc(1/var(--columns) * 100% - 2 * var(--betweenColumns));
margin: var(--betweenColumns);
}
.element {
display: flex;
border: 1px solid red;
background-color: yellow;
width: 100%;
height: 42px;
}
you can try this
.parent-wrapper {
height:100%;
width:100%;
border: 1px solid black;
}
.parent {
display: grid;
font-size: 0;
grid-template-columns: 25% 25% 25% 25%;
}
.child {
background:blue;
flex-grow: 1;
height:100px;
margin: 10px;
margin-bottom: 0;
}
.child:last-child {
margin-bottom: 10px;
}
<body>
<div class="parent-wrapper">
<div class="parent">
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
</div>
</div>
</body>
https://jsfiddle.net/samet19/gdntwLhb/
Here's another way without using calc().
// 4 PER ROW
// 100 divided by 4 is 25. Let's use 21% for width, and the remainder 4% for left & right margins...
.child {
margin: 0 2% 0 2%;
width: 21%;
}
// 3 PER ROW
// 100 divided by 3 is 33.3333... Let's use 30% for width, and remaining 3.3333% for sides (hint: 3.3333 / 2 = 1.66666)
.child {
margin: 0 1.66666% 0 1.66666%;
width: 30%;
}
// and so on!
That's all there is to it. You can get fancy with the dimensions to get a more aesthetic sizes but this is the idea.
Related
I have a page layout with a sidebar alongside a main-content div. Partway down the page, I have a div (parent) inside of a div (child). The child div needs to be horizontally centered relative to the screen instead of the parent.
<div class="sidebar"></div>
<div class="main-content">
<div class="parent">
<div class="child"></div>
<div class="other-stuff"></div>
</div>
</div>
<style>
.parent{
width: 100px;
}
.child{
width: 200px;
}
</style>
My first thought was using absolute positioning with something like this:
.child{
position: absolute;
margin-left: auto;
margin-right: auto;
left: 0;
right: 0;
text-align: center;
}
The problem I faced here was that I had to make up for the extra space due to the child being taken out of document flow. "Other-stuff" wanted to move up to fill the gap left behind.
Is there a better way to accomplish this beyond just pushing the div around with absolute positioning and adding extra margin/padding to make up the space so the lower content doesn't come up?
I'm open to abandoning absolute positioning — that was just the first thing that came to mind.
You can use a flexbox to position multiple items in one container and knock the children out of the parent div so it's not affected by whatever positioning you do with that.
*,
*::before,
*::after {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
width: 100vw;
}
.parent {
border: 1px solid black;
width: 100px;
height: fit-content;
}
.container {
display: flex;
flex-direction: column;
align-items: center;
width: 100%;
height: 100%;
gap: 2px;
}
.child {
display: block;
border: 1px solid black;
width: 200px;
height: fit-content;
}
.other-stuff {
display: block;
border: 1px solid black;
width: 200px;
height: fit-content;
}
<div class="sidebar"></div>
<div class="main-content">
<div class="parent">
I'm the Parent
</div>
<div class="container">
<div class="child">I'm the Child</div>
<div class="other-stuff">I'm the Other Stuff</div>
</div>
</div>
Here is the layout that I want:
Circles of 36px are distributed evenly across width
Circles are inset horizontally by 16px on both edges of the screen
It works perfectly below, except that the tap targets are only the small gold circles.
Array.from(document.querySelectorAll('.child')).map((x, i) => x.addEventListener('click', () => alert(`Hey child ${i}`)))
* { box-sizing: border-box; padding: 0; margin: 0 }
body {
background-color: blue;
}
.parent {
display: flex;
background-color: crimson;
height: 100px;
justify-content: space-between;
align-items: center;
padding-left: 16px;
padding-right: 16px;
}
.child {
background-color: gold;
border-radius: 50%;
width: 36px;
height: 36px;
}
<div class="parent">
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
</div>
I need the tap targets to take up all available space. Tapping anywhere on this crimson box should fire the nearest gold circle.
I achieved this by introducing a mask layer and a bunch of calculations and hacks. Surely there is a better way of keeping the above layout but just having the tap targets expand to fill the available space of the parent? My solution comes with a new set of problems such as accessibility, hover and active styles.
Hack solution below:
Array.from(document.querySelectorAll('.child-mask')).map((x, i) => x.addEventListener('click', () => alert(`Hey child ${i}`)))
* { box-sizing: border-box; padding: 0; margin: 0 }
body {
background-color: blue;
}
.parent {
display: flex;
background-color: crimson;
height: 100px;
flex-direction: row;
justify-content: space-between;
align-items: center;
padding-left: 16px;
padding-right: 16px;
}
.child {
background-color: gold;
border-radius: 50%;
width: 36px;
height: 36px;
}
.parent-mask {
position: absolute;
top: 0;
width: 100%;
display: flex;
height: 100px;
flex-direction: row;
}
.child-mask {
height: 100px;
flex-basis: 1;
flex-grow: 2;
}
.child-mask:first-child {
flex-grow: 1;
/* 16 + 36 / 2 */
padding-left: 34px;
}
.child-mask:nth-last-child(1) {
flex-grow: 1;
/* 16 + 36 / 2 */
padding-right: 34px;
}
<div class="parent">
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
</div>
<div class="parent-mask">
<div class="child-mask"></div>
<div class="child-mask"></div>
<div class="child-mask"></div>
<div class="child-mask"></div>
<div class="child-mask"></div>
<div class="child-mask"></div>
<div class="child-mask"></div>
</div>
Note, the parent could have an arbitrary width, the horizontal padding should always remain 16px regardless of the parent width.
Bonus points if you can get this working using only the subset of css primitives provided by react native as this is my actual use case. https://reactnative.dev/docs/flexbox
You can do it like this, the child elements will fill all the space so they will be the tap targets, the ::before pseudo-element will be the yellow circles:
const childs = [...document.querySelectorAll('.child')];
childs.map((x, i) => x.addEventListener('click', () => alert(`Hey child ${i}`)));
document.querySelector('.parent').style.setProperty('--childs', childs.length);
* { box-sizing: border-box, padding: 0, margin: 0 }
body {
background-color: blue;
padding: 0;
margin: 0;
}
.parent {
display: flex;
background-color: crimson;
height: 100px;
flex-direction: row;
justify-content: space-between;
align-items: center;
overflow: hidden;
}
.child {
--diameter: 36px;
--slices: calc(var(--childs) * 2);
--margin: calc(var(--diameter) / 2 + 16px);
position: relative;
display: flex;
align-items: center;
justify-content: center;
flex: 1;
height: 100%;
--width: calc(100% + 2 * calc(100% / var(--slices) - var(--margin)));
--cut: calc(-1 * var(--width) / var(--slices) + var(--margin));
}
.child:first-child {
margin-left: var(--cut);
}
.child:last-child {
margin-right: var(--cut);
}
.child::before {
content: '';
position: absolute;
background-color: gold;
border-radius: 50%;
width: var(--diameter);
aspect-ratio: 1;
}
.ml, .mr {
position: fixed;
height: 100px;
width: 1px;
top: 0;
background: black;
}
.ml {
left: 16px;
}
.mr {
right: 16px;
}
<div class="parent">
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
</div>
<div class="ml"></div>
<div class="mr"></div>
How to create 3 divs side by side using flex where middle div can (grow&shrink) in respect to other two divs?
I want to create Three divs A B C with a parent containing flex css property. Having A fixed width of 300px and C having min width 200px and can grow in width as more content is added.
While B should be in between A and C should grow and shrink automatically as per the widths of A and C.
Although A and C can be of any width 300px and 200px are just examples.
I've tried but unable to place it correctly.
For C i used flex: 1 1 0%; with A and C with fixed width - But didn't worked
You can give childB, You can read more about flex here
flex: 1;
.parent {
display: flex;
}
.child {
height: 300px;
display: flex;
justify-content: center;
align-items: center;
}
.childA {
flex-basis: 300px;
background-color: turquoise;
}
.childB {
flex: 1;
background-color: wheat;
}
.childC {
flex-basis: 200px;
background-color: blueviolet;
}
<div class="parent">
<div class="child childA">A</div>
<div class="child childB">B</div>
<div class="child childC">C</div>
</div>
it will be easier if you write your own code, which does not work
.abc {
display: flex;
height: 200px;
width: 400px;
margin: 0 auto;
border: 1px solid black;
}
.A {
min-width: 150px;
flex-shrink: 0;
background-color: aliceblue;
}
.B {
flex-grow: 1;
background-color: grey;
}
.C {
min-width: 100px;
flex-shrink: 0;
background-color: antiquewhite;
}
<div class="abc">
<div class="A"></div>
<div class="B"></div>
<div class="C"></div>
</div>
HTML :
<div class="container">
<div class="box">A</div>
<div class="box">B</div>
<div class="box">C</div>
</div>
CSS :
.container {
display: flex;
flex-wrap: nowrap;
border: 1px solid red;
height: 100px;
}
.box {
border: 1px solid black;
margin: 5px 5px 5px 5px;
}
.box:nth-child(2) {
width:25%;
background-color: blue;
}
you can use nth-child(child) to select any child and costom it
Result : https://codepen.io/pk-salma/pen/qBjqwBG
.main {
height: 100px;
width: 100px;
border: 1px solid;
background: green;
}
.columns {
display: flex;
}
.columns.vertical {
flex-direction: column;
flex-wrap: nowrap;
}
.box22 {
overflow: auto;
}
.box1 {
background: red;
}
.box2 {
background: orange;
border: 1px blue solid;
}
.box222 {
background: white;
border: 1px blue solid;
}
<md-content class="md-padding">
<div class="main columns vertical">
<nav class="box1">nav</nav>
<div class="box columns vertical">
<div class="b">asdasd</div>
<div class="box2 columns vertical">
<div class="box21 columns">
box21
</div>
<div class="box22 columns">
<div class="box221">box221</div>
<div class="box222">
<p>a</p>
<p>a</p>
</div>
</div>
</div>
</div>
</div>
</md-content>
I manually set the height of outermost box main and also set box22 with overflow:auto, however the box22 stretched out the main box and no scroll bar shows up.
What I want is to set height in the outermost box and the nested inner box can automitically control it's height thus all boxes are fitted. How to fix these kind of problem, should I set heights for all descendant boxes?
I tested setting overflow :auto at box(level1), box2(level2) and box22(level3), only box(level1) can automatically control it's height and shows up a scroll bar when it's height overlayed.
what I want is shown below, however, to achieve this, I need to manually specify the father box of box22. In other words, if I want to make a flex contaner scrollable, I have to at least set it's father box's height, which is toally unaccptable.
.main {
height: 100px;
width: 100px;
border: 1px solid;
background: green;
}
.columns {
display: flex;
}
.columns.vertical {
flex-direction: column;
flex-wrap: nowrap;
}
.box22 {
overflow: auto;
}
.box1 {
background: red;
}
.box2 {
height:64px;
background: orange;
border: 1px blue solid;
}
.box21 {
background: yellow;
}
.box222 {
background: white;
border: 1px blue solid;
margin-top: auto;
}
<md-content class="md-padding">
<div class="main columns vertical">
<nav class="box1">nav</nav>
<div class="box columns vertical">
<div class="b">asdasd</div>
<div class="box2 columns vertical">
<div class="box21 columns">
box21
</div>
<div class="box22 columns">
<div class="box221">box221</div>
<div class="box222">
<p>a</p>
<p>a</p>
<p>a</p>
</div>
</div>
</div>
</div>
</div>
</md-content>
Well, as you noted, the parent container needs a height declaration in order to generate a scrollbar.
This makes sense because there's no way to trigger an overflow condition if there's no fixed length.
With a flexible length (e.g., height: auto), the container will shrink and expand to accommodate content, never triggering an overflow and, therefore, never generating a scrollbar.
MDN describes it like this:
In order for overflow to have an effect, the block-level container must have either a set height (height or max-height) or white-space set to nowrap.
So that's your obstacle. Here's how you get around it (knowing that you can't set more heights):
Give the browser what it needs to trigger the overflow: set a tiny (1px) height.
You get the full height that you want: use flex-grow to consume remaining space.
So something like this...
height: 1px;
flex-grow: 1;
but more efficiently:
flex: 1 0 1px; /* fg, fs, fb */
Add this to your code:
.main .columns.vertical {
flex: 1 0 1px;
}
.box22 {
flex: 1 0 1px;
}
.main {
height: 100px;
width: 100px;
border: 1px solid;
background: green;
}
/* NEW */
.main .columns.vertical {
flex: 1 0 1px;
}
/* ADJUSTMENT */
.box22 {
flex: 1 0 1px;
overflow: auto;
}
.columns {
display: flex;
}
.columns.vertical {
flex-direction: column;
flex-wrap: nowrap;
}
.box22 {
flex: 1 0 1px;
overflow: auto;
}
.box1 {
background: red;
}
.box2 {
background: orange;
border: 1px blue solid;
}
.box222 {
background: white;
border: 1px blue solid;
}
<md-content class="md-padding">
<div class="main columns vertical">
<nav class="box1">nav</nav>
<div class="box columns vertical">
<div class="b">asdasd</div>
<div class="box2 columns vertical">
<div class="box21 columns">box21</div>
<div class="box22 columns">
<div class="box221">box221</div>
<div class="box222">
<p>a</p>
<p>a</p>
</div>
</div>
</div>
</div>
</div>
</md-content>
consider using max-height instead of height on main also... if you start with flexbox... best to keep display: flex through the whole chain
.top {
position: static;
height: 200px;
width: 200px;
max-height: 200px;
max-width: 200px;
overflow: auto;
}
.flexcol {
width: 100%;
display: flex;
flex-direction: column;
padding: 0;
}
.mynav {
display: flex;
flex-direction: row;
flex-grow: 1;
background-color: blue;
}
.box1 {
display: flex;
flex-grow: 1;
background-color: red;
}
.box2 {
display: flex;
flex-direction: column;
flex-grow: 1;
background-color: green;
}
.box3 {
display: flex;
flex-grow: 1;
background-color: yellow;
}
.box221 {
min-height: 50px;
background-color: pink;
width: 100%;
}
.box222 {
min-height: 50px;
background-color: grey;
width: 100%;
}
.darklink {
color: white;
}
<div class="top">
<div class="flexcol">
<nav class="mynav">
<a class="darklink" href="#" target="_">Link1</a>
<a class="darklink" href="#" target="_">Link2</a>
<a class="darklink" href="#" target="_">Link3</a>
</nav>
<div class="box1">
<p>para</p>
</div>
<div class="box2">
<div class="box221">
<p>para</p>
<p>para</p>
</div>
<div class="box222">
<p>para</p>
<p>para</p>
<p>para</p>
</div>
</div>
<div class="box3">
<p>para</p>
</div>
</div>
</div>
I'm trying to fill my page horizontally with as many blocks as possible and center the result.
I want the grid to be able to resize when the window becomes smaller:
wide window
xxx
small window
xx
x
Is this possible to achieve without javascript?
.box {
box-sizing: border-box;
width: 200px;
height: 150px;
background-color: white;
border: solid 6px red;
}
.box:nth-child(2) {
background-color: blue
}
.grid {
display: grid;
grid-template-columns: repeat(auto-fill, 200px);
}
<div class="center">
<div class="grid">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
</div>
To explain the desired centering visually:
Can the yellow highlighted area be evenly distributed on either side?
The desired box alignment:
This only works in chrome for some reason.
Auto-fit and auto-fill needs a known width to calculate from, we can do that with max-width:100% instead of using width which will stretch it and prevent us from centering, and avoid fixed widths.
.box {
box-sizing: border-box;
width: 200px;
height: 150px;
background-color: white;
border: solid 6px red;
}
.box:nth-child(2) {
background-color: blue
}
.grid {
display: grid;
grid-template-columns: repeat(auto-fill, 200px);
max-width: 100%;
}
.center {
display: flex;
flex-direction: column;
align-items: center;
}
<div class="center">
<div class="grid">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
</div>
There is a quirk with this, if you start with a wide viewport then resize it to a smaller one, the grid won't be centerd because of auto-fill
Say you have 3 elements but the container can fit 4 with auto-fill it will create a forth column but we have no forth element so it will look unevenly spaced.
I suggest using auto-fit, which instead of creating the forth column it will split the space evenly on each side.
.box {
box-sizing: border-box;
width: 200px;
height: 150px;
background-color: white;
border: solid 6px red;
}
.box:nth-child(2) {
background-color: blue
}
.grid {
display: grid;
grid-template-columns: repeat(auto-fit, 200px);
max-width: 100%;
}
.center {
display: flex;
flex-direction: column;
align-items: center;
}
<div class="center">
<div class="grid">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
</div>
Now if you resize the window enough you'll see sometimes it's not evenly spaced that's because of the relative unit on the max-width, it need to recalculate the width because it's based on the parent and parent's width which is based on the content.
we can trigger that recalculation using an animation.
chrome specific solution
.center {
display: flex;
flex-direction: column;
align-items: center;
}
.box {
box-sizing: border-box;
width: 200px;
height: 150px;
background-color: white;
border: solid 6px red;
}
.box:nth-child(2) {
background-color: blue
}
.grid {
display: grid;
grid-template-columns: repeat(auto-fit, 200px);
max-width: 100%;
animation: recalc 5s linear infinite;
}
#keyframes recalc {
to {
max-width: 99.9%;
}
}
<div class="center">
<div class="grid">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
</div>
To support at least FF and maybe some other browsers, use viewport units.
.box {
box-sizing: border-box;
width: 200px;
height: 150px;
background-color: white;
border: solid 6px red;
}
.box:nth-child(2) {
background-color: blue
}
.grid {
display: grid;
grid-template-columns: repeat(auto-fit, 200px);
max-width: 100vw;
margin:0 auto;
}
.center {
display: flex;
}
<div class="center">
<div class="grid">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
</div>
Try this with flexbox.
.box {
box-sizing: border-box;
width: 200px;
height: 150px;
background-color: white;
border: solid 6px red;
}
.box:nth-child(2) {
background-color: blue
}
.grid {
display: flex;
justify-content: center;
align-items: center;
}
#media screen and (max-width: 767px) {
.grid {
flex-wrap: wrap;
justify-content: center;
}
.box {
width: 50%
}
}
<div class="center">
<div class="grid">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
</div>
I wouldn't use grid for this. Use flex:
*{
box-sizing:border-box; padding:0; margin:0; font-size:0;
}
html,body{
width:100%; height:100%; background:#ccc;
}
.box{
width:200px; height:150px; background-color:white; border:6px solid red;
}
.box:nth-child(2n+2) {
background-color:blue;
}
.center,.grid{
display:flex; align-items:center; justify-content:center; height:100%;
}
.grid{
min-width:600px; flex-wrap:wrap; align-items:center;
}
<div class='center'>
<div class='grid'>
<div class='box'></div>
<div class='box'></div>
<div class='box'></div>
<div class='box'></div>
<div class='box'></div>
</div>
</div>
Yes, you can centre an auto-fill, left-aligned grid (and it works in Firefox).
To do this, you just need justify-content: center; on the grid container, which would give you this:
A good example of this (and why it works) is on the MDN docs page for justify-content
Your example would look like this:
.box {
box-sizing: border-box;
width: 200px;
height: 150px;
background-color: white;
border: solid 6px red;
}
.box:nth-child(2) {
background-color: blue
}
.grid {
display: grid;
grid-template-columns: repeat(auto-fill, 200px);
justify-content: center; /* <-- This is all you need to add */
}
<div class="center">
<div class="grid">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
</div>
It's worth noting though, that when you only have one row of boxes, they may not be centred, since the repeat function will create empty columns to fill the row, effectively left aligning the actual boxes: