Image Tile Using CSS Grid - css

I'm trying to create a 2 x 2 image tile using css grid. I'm want to make this dynamic so that no matter how many images are provided (between 1 and 4), the full space of the tile is used. So like this:
Ive got this kinda working with the following css and markup.
CSS
.container {
display: flex;
}
.container .grid-tiles {
margin-right: 20px;
}
.grid-tiles {
display: grid;
grid-template-columns: repeat(auto-fit, 38px);
grid-column-gap: 4px;
grid-row-gap: 4px;
width: 80px;
height: 80px;
}
.grid-tiles .grid-tile {
border-radius: 3px;
background-color: red;
}
/* Only one */
.grid-tile:only-child {
grid-area: 2 span / 2 span;
}
/* Three */
.grid-tile:first-child:nth-last-child(3) {
grid-area: 2 span;
}
HTML
<div class="grid-tiles">
<div class="grid-tile"></div>
<div class="grid-tile"></div>
<div class="grid-tile"></div>
<div class="grid-tile"></div>
</div>
But in some cases there needs to be text in a tile. When that happens the grid doesn't follow the sizing of the other instances:
I need the grid to be consistent. Anyone able to offer some help on how to ensure this / improvements to the grid properties? Thanks!
I've a Codepen of the current working.

Force all the columns/rows to be equal in size by using
grid-template-columns: 1fr 1fr; /* two equal columns */
grid-auto-rows: 1fr; /* all the rows equal */
Full code
.container {
display: flex;
}
.container .grid-tiles {
margin-right: 20px;
}
.grid-tiles {
display: grid;
grid-template-columns: 1fr 1fr;
grid-auto-rows: 1fr;
gap: 4px;
width: 80px;
height: 80px;
}
.grid-tiles .grid-tile {
border-radius: 3px;
background-color: red;
}
/* Only one */
.grid-tile:only-child {
grid-area: span 2 / span 2;
}
/* Three */
.grid-tile:first-child:nth-last-child(3) {
grid-area: span 2;
}
<div class="container">
<div class="grid-tiles">
<div class="grid-tile"></div>
</div>
<div class="grid-tiles">
<div class="grid-tile"></div>
<div class="grid-tile"></div>
</div>
<div class="grid-tiles">
<div class="grid-tile"></div>
<div class="grid-tile"></div>
<div class="grid-tile"></div>
</div>
<div class="grid-tiles">
<div class="grid-tile"></div>
<div class="grid-tile"></div>
<div class="grid-tile"></div>
<div class="grid-tile"></div>
</div>
<div class="grid-tiles">
<div class="grid-tile"></div>
<div class="grid-tile"></div>
<div class="grid-tile"></div>
<div class="grid-tile">Zaa</div>
</div>
</div>

Related

Image pushing divs below

I have a 2 column layout with an image to the left and wanted to have 3 divs on the right but can only manage to get 1 div to align next to the image and the other 3 divs are below the image. How can I have all 3 divs next to the image?
I know this is easy with grid-areas but wanted to do it with out.
.wrapper {
background-color: pink;
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-template-rows: auto auto 1fr;
}
.hero {
background-color: red;
}
.foo {
background-color: orange;
}
.bar {
background-color: lime;
}
.baz {
background-color: aqua;
}
img {
width: 100%;
display: block;
}
<div class="wrapper">
<div class="hero">
<img src="https://via.placeholder.com/1080x1080" alt="">
</div>
<div class="foo">
foo
</div>
<div class="bar">
bar
</div>
<div class="baz">
baz
</div>
</div>
https://codepen.io/emmabbb/pen/oNqPwad
Set a specific grid row value on your hero: grid-row: 1 / 4;
Like this:
.wrapper {
background-color: pink;
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-template-rows: auto auto 1fr;
}
.hero {
background-color: red;
grid-row: 1 / 4;
}
.foo {
background-color: orange;
}
.bar {
background-color: lime;
}
.baz {
background-color: aqua;
}
img {
width: 100%;
display: block;
}
<div class="wrapper">
<div class="hero">
<img src="https://via.placeholder.com/1080x1080" alt="">
</div>
<div class="foo">
foo
</div>
<div class="bar">
bar
</div>
<div class="baz">
baz
</div>
</div>
If you want your divs with text in them to be of equal height change the grid template rows to grid-template-rows: 1fr 1fr 1fr; Like this:
.wrapper {
background-color: pink;
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-template-rows: 1fr 1fr 1fr;
}
.hero {
background-color: red;
grid-row: 1 / 4;
}
.foo {
background-color: orange;
}
.bar {
background-color: lime;
}
.baz {
background-color: aqua;
}
img {
width: 100%;
display: block;
}
<div class="wrapper">
<div class="hero">
<img src="https://via.placeholder.com/1080x1080" alt="">
</div>
<div class="foo">
foo
</div>
<div class="bar">
bar
</div>
<div class="baz">
baz
</div>
</div>
I believe the easiest way to get the 3 divs on the right of the image without using grid area would be to wrap foo, bar, and baz in a parent div and use 1 row on your grid; you may have to mess with the hight of the divs on the right though.
<div class="wrapper">
<div class="hero">
<img src="https://via.placeholder.com/1080x1080" alt="">
</div>
<div>
<div class="foo">
foo
</div>
<div class="bar">
bar
</div>
<div class="baz">
baz
</div>
</div>
</div>
I hope that does what your looking for!

Responsive centering of divs

How do I go from here
To here
I'm trying to center the inner div's to their parent except for the last row where I'd like to align it left to the row above it.
Here is the jsfiddle for the top image https://jsfiddle.net/L15p2nev
.container {
text-align: center;
background-color: green;
}
.item {
display: inline-block;
width: 300px;
background-color: red;
}
<div class="container">
<div class="item">
item
</div>
<div class="item">
item
</div>
<div class="item">
item
</div>
</div>
Using grid display layout, this can be archived.
You can set grid-template-columns: repeat(auto-fit, 300px) to align items as the image.
.container {
background-color: green;
display: grid;
grid-template-columns: repeat(auto-fit, 300px);
justify-content: center;
grid-column-gap: 10px;
grid-row-gap: 10px;
}
.item {
display: inline-block;
background-color: red;
}
<div class="container">
<div class="item">
item
</div>
<div class="item">
item
</div>
<div class="item">
item
</div>
</div>

Expanding cells in CSS grid layout

I have the following HTML/CSS
.main {
display: grid;
grid-template-columns: 2fr 1fr;
}
/* The following is not essential - for decoration purposes only */
.left {
background-color: green;
}
.right {
background-color: orange;
}
<div class="main">
<div class="left">Left</div>
<div class="right">Right</div>
</div>
Now, sometimes, and depending on the div with class main, sometimes I do not have the div with the class right (in other words, the html might look like this
.main {
display: grid;
grid-template-columns: 2fr 1fr;
}
/* The following is not essential - for decoration purposes only */
.left {
background-color: green;
}
.right {
background-color: orange;
}
<div class="main">
<div class="left">Left</div>
</div>
What I like to do is write the CSS code in a way that expands div.left to the full width of the container div.main if div.right does not exist. How can I do that?
You can rely on implicit grid creation:
.main {
display: grid;
grid-template-columns: 2fr;
grid-auto-columns:1fr; /* this will trigger when you add the "right" element */
grid-auto-flow:column;
margin:5px;
}
.left {
background-color: green;
}
.right {
background-color: orange;
}
<div class="main">
<div class="left">Left</div>
<div class="right">right</div>
</div>
<div class="main">
<div class="left">Left</div>
</div>
It does also work if you want to remove left:
.main {
display: grid;
grid-template-columns: 2fr;
grid-auto-columns:1fr; /* this will trigger when you add the "left" element */
grid-auto-flow:column;
margin:5px;
}
.left {
background-color: green;
grid-column-end:1; /* added this */
}
.right {
background-color: orange;
}
<div class="main">
<div class="left">Left</div>
<div class="right">right</div>
</div>
<div class="main">
<div class="right">right</div>
</div>
This is something better suited to flexbox but if your structure is as simplistic as you indicate the only-child can be used here.
.main {
display: grid;
grid-template-columns: 2fr 1fr;
margin-bottom: 1em;
}
/* The following is not essential - for decoration purposes only */
.left {
background-color: green;
height: 25vh;
}
.left:only-child {
grid-column: 1 / -1;
}
.right {
background-color: orange;
}
<div class="main">
<div class="left">Left</div>
<div class="right">Right</div>
</div>
<div class="main">
<div class="left">Left</div>
</div>

how to make a grid mobile responsive in react

I have to make videos in the grid to appear horizontally one after the other when seen in a mobile(mobile responsive) but they should stay vertically aligned in desktop view.
i have tried giving values to rows and columns as auto
return (
<div>
<h1 className="text">trending in youtube</h1>
<div className="grid-container">
<div className="one">
<YouTube
videoId="y6fThXQPT6I"
opts={opts}
onReady={this._onReady}
/>
</div>
<div className="two">
<YouTube
videoId="bo_efYhYU2A"
opts={opts}
onReady={this._onReady}
/>
</div>
<div className="three">
<YouTube
videoId="3AtDnEC4zak"
opts={opts}
onReady={this._onReady}
/>
</div>
</div>
</div>
);
}
css file
display: grid;
grid-template-columns: repeat(auto, 1fr);
grid-gap: 5px;
grid-auto-rows: minmax(100px, auto);
}
.text {
margin-top: 50px;
margin-left: 40%;
}
.one {
grid-column: auto;
grid-row: 1;
}
.two {
grid-column:auto;
grid-row: 1;
}
.three {
grid-column: auto;
grid-row: 1;
}
As you tagged your post with bootstrap-4 I'll assume you use it.
Bootstrap has all you need, look at the grid system: https://getbootstrap.com/docs/4.3/layout/grid/
In your case you can use it like this:
return (
<div className="container">
<h1 className="text">trending in youtube</h1>
<div className="row justify-content-center">
<div className="col-xs-12 col-md-4">
<YouTube
videoId="y6fThXQPT6I"
opts={opts}
onReady={this._onReady}
/>
</div>
<div className="col-xs-12 col-md-4">
<YouTube
videoId="bo_efYhYU2A"
opts={opts}
onReady={this._onReady}
/>
</div>
<div className="col-xs-12 col-md-4">
<YouTube
videoId="3AtDnEC4zak"
opts={opts}
onReady={this._onReady}
/>
</div>
</div>
</div>
);
No more CSS needed 😉
You can Use grid-auto-flow:
.grid-container {
display: grid;
grid-gap: 5px;
grid-auto-flow: row; /* appear Vertically*/
justify-items: center;
}
#media (max-width: 767px) {
.grid-container {
grid-auto-flow: column; /* appear Horizontally on mobile phones*/
}
}
Example About css grid-auto-flow property: When you run the snippet it will appear horizontally, but if you opened it as full screen it will appear vertically.
.grid-container {
display: grid;
grid-gap: 5px;
grid-auto-flow: row;
justify-items: center;
}
#media (max-width: 767px) {
.grid-container {
grid-auto-flow: column;
}
}
.item {
width: 250px;
height: 100px;
}
.one {
background-color: lightblue;
}
.two {
background-color: lightpink;
}
.three {
background-color: lightcoral;
}
<div class="grid-container">
<div class="item one"></div>
<div class="item two"></div>
<div class="item three"></div>
</div>

Four items in two columns

I have this HTML
<div class='wrapper'>
<div class='item-1'>One</div>
<div class='item-2'>Two</div>
<div class='item-3'>Three</div>
<div class='item-4'>Four</div>
</div>
In CSS, is it possible for me to create a two column grid where item-1 and item-2 are in the first column, and item-3 and item-4 are in the second?
The heights of the divs are variable, so this is not strict 2x2 grid.
Basically, I'd like it to look like the example below, but I do not have the luxury of wrapping my items.
THANKS!
.wrapper {
display:grid;
grid-template-columns: 1fr 1fr;
}
<div class='wrapper'>
<div class='wrapper-1'>
<div class='item-1' style='height:100px;background-color:red;'>One</div>
<div class='item-2' style='height:80px;background-color:blue;'>Two</div>
</div>
<div class='wrapper-2'>
<div class='item-3' style='height:40px;background-color:orange;'>Three</div>
<div class='item-4' style='height:40px;background-color:green;'>Four</div>
</div>
</div>
The CSS for the wrapper is correct. The only thing you need to specify is from which line of the grid should each item start and end.
.item-1,
.item-2{
grid-column: 1/2;
width: 100%;
}
.item-3,
.item-4{
grid-column: 3/4;
width: 100%;
}
This should suit your needs. Note that the wrapper needs to have an explicit height in order for the columns to wrap, otherwise it's going to endlessly expand.
.wrapper {
display: flex;
flex-flow: column wrap;
height: 200px;
}
.item {
width: 50%;
}
.i-1 {
height: 100px;
background-color: green;
}
.i-2 {
height: 80px;
background-color: red;
}
.i-3 {
height: 40px;
background-color: blue;
}
.i-4 {
height: 40px;
background-color: yellow;
}
<div class='wrapper'>
<div class='item i-1'>One</div>
<div class='item i-2'>Two</div>
<div class='item i-3'>Three</div>
<div class='item i-4'>Four</div>
</div>

Resources