In the following example mid-left and mid-right should equally share space left by all other elements. But if there is only one of them, it should take all this space. It's not known which of them would be present. Supporting of gap is NOT needed.
I can make this only via :has selector. How can I make the same thing without it?
Markup should NOT be changed. Otherwice I would wrap mid-left and mid-right into container and used flex or grid-auto-columns: 1fr on it.
Here are 5 examples how it should work:
section {
display: grid;
grid-template: "l t t t" 2em
"l mt mt r" 1fr
"l ml mr r" 1fr / 5em 1fr 1fr 5em;
min-height: 8em;
}
section + section {
margin-top: 2em;
}
div {
display: flex;
justify-content: center;
align-items: center;
text-align: center;
}
.left { grid-area: l; background: antiquewhite; }
.top { grid-area: t; background: silver; }
.right { grid-area: r; background: antiquewhite; }
.mid-top { grid-area: mt; background: yellow; }
.mid-left { grid-area: ml; background: aquamarine; }
.mid-right { grid-area: mr; background: lightsalmon; }
section:not(:has(.mid-left)) {
grid-template-columns: 5em 0 1fr 5em;
}
section:not(:has(.mid-right)) {
grid-template-columns: 5em 1fr 0 5em;
}
<section>
<div class="left">Left</div>
<div class="top">Top</div>
<div class="right">Right</div>
<div class="mid-top">Mid top</div>
<div class="mid-left">Mid left takes half of space</div>
<div class="mid-right">Mid right takes half of space</div>
</section>
<section>
<div class="left">Left</div>
<div class="top">Top</div>
<div class="right">Right</div>
<div class="mid-top">Mid top</div>
<div class="mid-left">Mid left should take all width</div>
</section>
<section>
<div class="left">Left</div>
<div class="top">Top</div>
<div class="right">Right</div>
<div class="mid-top">Mid top</div>
<div class="mid-right">Mid right should take all width</div>
</section>
<section>
<div class="left">Left</div>
<div class="top">Top</div>
<div class="right">Right</div>
<div class="mid-top">Mid top</div>
<div class="mid-left">Mid left should have equal width even if it has more content</div>
<div class="mid-right">Mid right</div>
</section>
<section>
<div class="left">Left</div>
<div class="top">Top</div>
<div class="right">Right</div>
<div class="mid-top">Mid top</div>
<div class="mid-left">Mid left</div>
<div class="mid-right">Mid right should have equal width even if it has more content</div>
</section>
PS: Actually I have several divs with display: contents on them and the elements mid-left and mid-right are not on the same level.
PPS: Anyway, I think answers based on provided markup are usefull for future viewers or maybe even for me if I could adopt selectors.
Actually I was not going to add examples with wrappers into the question, but as I was asked, here they are:
section {
display: grid;
grid-template: "l t t t" 2em
"l mt mt r" 1fr
"l ml mr r" 1fr / 5em 1fr 1fr 5em;
min-height: 8em;
}
section + section {
margin-top: 2em;
}
div {
display: flex;
justify-content: center;
align-items: center;
text-align: center;
}
some-wrapper {
display: contents;
}
.left { grid-area: l; background: antiquewhite; }
.top { grid-area: t; background: silver; }
.right { grid-area: r; background: antiquewhite; }
.mid-top { grid-area: mt; background: yellow; }
.mid-left { grid-area: ml; background: aquamarine; }
.mid-right { grid-area: mr; background: lightsalmon; }
section:not(:has(.mid-left)) {
grid-template-columns: 5em 0 1fr 5em;
}
section:not(:has(.mid-right)) {
grid-template-columns: 5em 1fr 0 5em;
}
<section>
<div class="left">Left</div>
<some-wrapper>
<div class="top">Top</div>
<div class="right">Right</div>
<div class="mid-top">Mid top</div>
<div class="mid-right">Mid right</div>
</some-wrapper>
<some-wrapper>
<div class="mid-left">Mid left</div>
</some-wrapper>
</section>
<section>
<div class="left">Left</div>
<some-wrapper>
<div class="top">Top</div>
<div class="right">Right</div>
<div class="mid-top">Mid top</div>
</some-wrapper>
<some-wrapper>
<div class="mid-left">Mid left</div>
</some-wrapper>
</section>
<section>
<div class="left">Left</div>
<some-wrapper>
<div class="top">Top</div>
<div class="right">Right</div>
<div class="mid-top">Mid top</div>
<div class="mid-right">Mid right</div>
</some-wrapper>
<some-wrapper>
</some-wrapper>
</section>
<section>
<div class="left">Left</div>
<some-wrapper>
<div class="mid-right">Mid right</div>
<div class="mid-top">Mid top</div>
<div class="top">Top</div>
</some-wrapper>
<div class="right">Right</div>
</section>
<section>
<div class="left">Left</div>
<div class="top">Top</div>
<some-wrapper>
<div class="mid-right">Mid right</div>
<div class="mid-top">Mid top</div>
</some-wrapper>
<some-wrapper>
<div class="mid-left">Mid left</div>
</some-wrapper>
<div class="right">Right</div>
</section>
Same question in Russian.
Related
I'm new to CSS Grid and I want to create a grid of divs. I want the grids to be fill up horizontally--filling up the pink div, but instead they go vertical like in the snippet below. I've tried everything, how do I fix it
.mygrid
{
background-color: pink;
display: grid;
gap: 2px;
grid-template-columns: 30px 40px;
}
.item
{
background-color: blue;
}
<div class="mygrid">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
<div class="item">5</div>
<div class="item">6</div>
<div class="item">7</div>
<div class="item">8</div>
<div class="item">9</div>
<div class="item">10</div>
<div class="item">11</div>
<div class="item">12</div>
</div>
You should define the columns to half and half, using the "fr" unit.
.mygrid
{
background-color: pink;
display: grid;
gap: 2px;
grid-template-rows: 1fr 1fr;
grid-template-columns: 1fr 1fr;
}
.item
{
background-color: blue;
}
<div class="mygrid">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
<div class="item">5</div>
<div class="item">6</div>
<div class="item">7</div>
<div class="item">8</div>
<div class="item">9</div>
<div class="item">10</div>
<div class="item">11</div>
<div class="item">12</div>
</div>
Your problem comes from grid-template-columns property.
You can use the auto param get the same size of columns.
Follow this doc for more information : https://developer.mozilla.org/en-US/docs/Web/CSS/grid-template-columns
.mygrid
{
background-color: pink;
display: grid;
gap: 2px;
grid-template-columns: auto auto auto;
}
.item
{
background-color: blue;
}
<div class="mygrid">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
<div class="item">5</div>
<div class="item">6</div>
<div class="item">7</div>
<div class="item">8</div>
<div class="item">9</div>
<div class="item">10</div>
<div class="item">11</div>
<div class="item">12</div>
</div>
use grid-template-columns: auto auto; to fill the entire pink box,
.mygrid
{
background-color: pink;
display: grid;
grid-template-columns: auto auto auto;
gap: 2px;
}
View on codepen for more detail : link
help me please, how do i get a result like this in the grid? the result i want - link - img https://ibb.co/XbW025V . here is my code https://jsfiddle.net/o0zjuyqb/1/
<div class="container">
<div class="parent">
<div class="div1"></div>
<div class="div2"></div>
<div class="div3"></div>
<div class="div4"></div>
<div class="div5"></div>
<div class="div6"></div>
</div>
</div>
You can do this by using grid-column: span 2;
.grid {
display: grid;
grid-auto-flow: dense;
grid-template-columns: 250px 290px 290px 250px;
grid-template-rows: repeat(2, 280px);
gap: 40px;
}
.grid div {
background: grey;
}
.grid div.wide {
grid-column: span 2;
background: green;
}
<div class="grid">
<div class="wide"></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div class="wide"></div>
</div>
I've setup a grid-template but a problem has arisen in the front-end template layer. Basically there comes a time when divs with assigned grid-areas conditionally render onto the page. Being that I have a grid-row-gap declaration in place, it maintains gaps of grid template areas that aren't present on the page. I was wondering if there was a way to collapse these gaps when this sort of thing occurs.
.grid {
display: grid;
grid-template-areas:
'a b'
'a c'
'a d'
'a e'
'a f';
grid-gap: 25px;
}
.cell {
display: flex;
align-items: center;
justify-content: center;
padding: 15px;
border: 1px solid #000;
}
.a {
grid-area: a;
}
.b {
grid-area: b;
}
.c {
grid-area: c;
}
.d {
grid-area: d;
}
.e {
grid-area: e;
}
.f {
grid-area: f;
}
<div class="grid">
<div class="a cell">A</div>
<div class="b cell">B</div>
<!-- <div class="c cell">C</div> -->
<!-- <div class="d cell">D</div> -->
<div class="e cell">E</div>
<div class="f cell">F</div>
</div>
You can think it otherwise, use template and span instead area , and margin instead grid-gap.
.grid {
display: grid;
grid-template-columns: 1fr 1fr;
margin: 1em;
background: #bee;
}
.cell {
display: flex;
align-items: center;
justify-content: center;
padding: 15px;
border: 1px solid #000;
grid-column: 2;
}
.a {
grid-column: 1;
grid-row: 1 / span 10;
/* here what you think is enough */
}
.cell:nth-child(1)~.cell {
margin-left: 24px;
}
.cell:nth-child(2)~.cell {
margin-top: 24px;
<div class="grid">
<div class="a cell">A</div>
<div class="b cell">B</div>
<div class="c cell">C</div>
<div class="d cell">D</div>
<div class="e cell">E</div>
<div class="f cell">F</div>
</div>
<div class="grid">
<div class="a cell">A</div>
<div class="b cell">B</div>
<div class="d cell">D</div>
<div class="f cell">F</div>
</div>
Don't use template-areas and reply on auto placement:
.grid {
display: grid;
grid-template-columns: 1fr 1fr; /* 2 columns */
column-gap: 25px;
margin:5px;
}
.cell {
display: flex;
align-items: center;
justify-content: center;
padding: 15px;
border: 1px solid #000;
}
.grid .a {
grid-row: span 5; /* take 5 rows */
}
/* to replace vertical gap, don't apply to "a" and last-child */
.cell:not(.a):not(:last-child) {
margin-bottom:25px;
}
<div class="grid">
<div class="a cell">A</div>
<div class="b cell">B</div>
<!-- <div class="c cell">C</div> -->
<!-- <div class="d cell">D</div> -->
<div class="e cell">E</div>
<div class="f cell">F</div>
</div>
<div class="grid">
<div class="a cell">A</div>
<div class="b cell">B</div>
<div class="c cell">C</div>
<!-- <div class="d cell">D</div> -->
<div class="e cell">E</div>
<div class="f cell">F</div>
</div>
<div class="grid">
<div class="a cell">A</div>
<div class="b cell">B</div>
<div class="c cell">C</div>
</div>
I am very new to CSS Grid and am trying to create a 2 X 2 grid. I am able to create the four image divs ( 2 on each row and 2 on each column) but I want the text to appear underneath each one. I have tried to use the grid-template-areas property but all the text just appears under one div all overlapped.
Any help would be appreciated, please.
.image {
width: 526px;
height: 360px;
border: 1px solid #000;
border-radius: 10px;
margin-top: 35px;
margin-bottom: 35px;
}
.grid-container {
display: grid;
grid-template-rows: auto;
grid-template-columns: 1fr 1fr;
column-gap: 10px;
row-gap: 1em;
grid-template-areas: "image image " "text text";
}
.text {
grid-area: text;
}
<div class="banner">
<div class="wrapper">
<div class="grid-container">
<div class="image"></div>
<p class="text">TEXT 1</p>
<div class="image"></div>
<p class="text">
TEXT 2
</p>
<div class="image"></div>
<p class="text">TEXT 3</p>
<div class="image"></div>
<p class="text">TEXT 4</p>
</div>
</div>
<!-- wrapper -->
</div>
<!-- banner -->
You can use nth-child() to correctly place your elements instead of grid-area:
.image {
width: 200px;
height: 150px;
border: 1px solid #000;
border-radius: 10px;
margin-top: 35px;
margin-bottom: 35px;
}
.grid-container {
display: grid;
grid-auto-flow: dense; /* this one is important to fill all the cells */
grid-auto-columns: 1fr;
column-gap: 10px;
}
.image:nth-child(4n + 3) {
grid-column: 2;
}
.text:nth-child(4n + 2) {
grid-column: 1;
}
<div class="banner">
<div class="wrapper">
<div class="grid-container">
<div class="image"></div>
<p class="text">TEXT 1</p>
<div class="image"></div>
<p class="text">TEXT 2</p>
<div class="image"></div>
<p class="text">TEXT 3</p>
<div class="image"></div>
<p class="text">TEXT 4</p>
</div>
</div>
</div>
This will work even if you add more image/text:
.image {
width: 200px;
height: 150px;
border: 1px solid #000;
border-radius: 10px;
margin-top: 35px;
margin-bottom: 35px;
}
.grid-container {
display: grid;
grid-auto-flow: dense; /* this one is important to fill all the cells */
grid-auto-columns: 1fr;
column-gap: 10px;
}
.image:nth-child(4n + 3) {
grid-column: 2;
}
.text:nth-child(4n + 2) {
grid-column: 1;
}
<div class="banner">
<div class="wrapper">
<div class="grid-container">
<div class="image"></div>
<p class="text">TEXT 1</p>
<div class="image"></div>
<p class="text">TEXT 2</p>
<div class="image"></div>
<p class="text">TEXT 3</p>
<div class="image"></div>
<p class="text">TEXT 4</p>
<div class="image"></div>
<p class="text">TEXT 5</p>
<div class="image"></div>
<p class="text">TEXT 6</p>
<div class="image"></div>
<p class="text">TEXT 7</p>
<div class="image"></div>
<p class="text">TEXT 8</p>
</div>
</div>
</div>
Manage placement without template areas using nth-of-type and flow via columns.
.image {
width: 100px;
height: 100px;
border: 1px solid #000;
border-radius: 10px;
margin-top: 35px;
margin-bottom: 35px;
}
.grid-container {
display: grid;
grid-template-rows: auto;
grid-template-columns: 1fr 1fr;
column-gap: 10px;
row-gap: 1em;
grid-auto-flow: column;
}
p:nth-of-type(odd),
.image:nth-of-type(odd) {
grid-column: 1;
}
p:nth-of-type(even),
.image:nth-of-type(even) {
grid-column: 2;
}
<div class="banner">
<div class="wrapper">
<div class="grid-container">
<div class="image"></div>
<p class="text">TEXT 1</p>
<div class="image"></div>
<p class="text">
TEXT 2
</p>
<div class="image"></div>
<p class="text">TEXT 3</p>
<div class="image"></div>
<p class="text">TEXT 4</p>
</div>
</div>
<!-- wrapper -->
</div>
<!-- banner -->
I removed the grid-area configuration from CSS code. Also, I have rearranged the sequence of your image and text HTML code. I hope this is what you expected.
.image {
width: 526px;
height: 360px;
border: 1px solid #000;
border-radius: 10px;
margin-top: 35px;
margin-bottom: 35px;
/*grid-area: image;*/
}
.grid-container {
display: grid;
grid-template-rows: auto;
grid-template-columns: 1fr 1fr;
column-gap: 10px;
row-gap: 1em;
/* grid-template-areas: "image image" "text text"; */
}
.text {
text-align: center; /* Aligning the text to center */
/* grid-area: text;*/
}
<div class="banner">
<div class="wrapper">
<div class="grid-container">
<div class="image"></div>
<div class="image"></div>
<p class="text">TEXT 1</p>
<p class="text">TEXT 2</p>
<div class="image"></div>
<div class="image"></div>
<p class="text">TEXT 3</p>
<p class="text">TEXT 4</p>
</div>
</div>
<!-- wrapper -->
</div>
<!-- banner -->
Why blocks .b have different width? How to set it equal?
.parent {
display: flex;
}
.parent>div {
flex: 1 1 auto;
}
.parent .b {
display: flex;
}
<div class="parent">
<div class="cell">
<div class="b"></div>
</div>
<div class="cell">>
<div class="b"></div>
</div>
<div class="cell">>
<div class="b"></div>
</div>
<div class="cell">>
<div class="b"></div>
</div>
<div>
Why blocks <div class="cell"> have different width?
Edit: use CSS grid and auto-fit:
.parent {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(0, 1fr));
}
.parent {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(0, 1fr));
}
.parent>div {
background-color: lightblue;
margin-left: 5px;
}
<div class="parent">
<div class="cell">
<div class="b"></div>
</div>
<div class="cell">>
<div class="b"></div>
</div>
<div class="cell">>
<div class="b"></div>
</div>
<div class="cell">>
<div class="b"></div>
</div>
</div>
Second re-edit**
First choice you can do is just set a flex on the parent element as this will only effect the first element below that, which in this case is the cell class, i will add a border on the cell class so you can see this in effect
<div class="parent">
<div class="cell">
<div class="b"></div>
</div>
<div class="cell">
<div class="b"></div>
</div>
<div class="cell">
<div class="b"></div>
</div>
<div class="cell">
<div class="b"></div>
</div>
<div>
.parent {
display: flex;
width: 70%;
}
.cell {
width: 20%;
height: 100px;
border: 1px solid orange;
}
here you can set the size of your parent width which will be the size across your screen, you can then set the width of the .cell childs and they will all then be the same, but only at a maximum of the parent
** second option you can do
Here is a simpler version, and i have added 3 different classes to show how you can choose the sizing you want
<div class="parent">
<div class="a"></div>
<div class="b"></div>
<div class="c"></div>
<div>
.parent {
display: flex;
width: 80%;
height: 100px;
}
.a {
flex: 40%;
border: 1px solid greenyellow;
}
.b {
flex: 20%;
border: 1px solid orange;
}
.c {
flex: 20%;
border: 1px solid blue;
}
Of course you can change them back and have them all be called the same class, and just assign one width and again they will all be the same... i hope this helps
I think they all are in same width. You need to use this css instead of the .parent>div selector
.cell {
flex: 1 1 auto;
}
.parent {
display: flex;
}
.cell {
flex: 1 1 auto;
}
.parent .b {
display: flex;
align-items: center;
justify-content: center;
}
.b {
height: 50px;
}
.cell:nth-child(1) {
background: red;
}
.cell:nth-child(2) {
background: yellow;
}
.cell:nth-child(3) {
background: green;
}
.cell:nth-child(4) {
background: teal;
}
<div class="parent">
<div class="cell">
<div class="b">hi</div>
</div>
<div class="cell">
<div class="b">hi</div>
</div>
<div class="cell">
<div class="b">hi</div>
</div>
<div class="cell">
<div class="b">hi</div>
</div>
<div>