I have the grid, each element has an image and other divs underneath. Because it's a grid, each element has responsive width and so it scales automatically as the screen shrinks. I would like the images (which can have different sizes and not be homogeneous) of the elements to have the same height while maintaining this responsive feature. If I set a specific height, as the screen shrinks the aspect ratio is not maintained. Basically I need a youtube style responsivness, that is a perfect example. How can I do it?
This is my grid:
JSX:
<div className="home-container">
{elements.map((el) => (
<Element el={el}></Element >
))}
</div>
CSS:
.home-container {
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
gap: 20px;
margin-left: 250px;
grid-auto-rows: 1fr;
grid-row-gap: 30px;
}
This is my elementcard:
JSX:
<div className="element-container">
<div className="element-img">
<img src={imageUrl} alt={title} />
</div>
<div>...</div>
<div>...</div>
</div>
CSS:
.element-container {
display: flex;
flex-direction: column;
box-sizing: border-box;
height: fit-content;
border-radius: 10px;
overflow: hidden;
}
.element-img {
display: flex;
margin-bottom: 20px;
}
.element-img > img {
width: 100%;
height: 100%;
border-radius: 20px;
object-fit: cover;
}
PROBLEM: As you can see, the dish problem is ok when the grid is not shrunk, but then that it does not maintain the same aspect-ratio as the other elements.
Create a wrapper around the image to maintain the aspect ratio. Use position: relative;
and set a padding-top
to define the aspect ratio.
For the image, set position:absolute;
to position it within the wrapper. Use object-fit: cover;
to maintain the aspect ratio while covering the entire container. Set width:100%;
and height:100%;
to fill the container.
.home-container {
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
gap: 20px;
margin-left: 250px;
grid-auto-rows: 1fr;
grid-row-gap: 30px;
}
.element-container {
display: flex;
flex-direction: column;
box-sizing: border-box;
min-height: 250px;
border-radius: 10px;
overflow: hidden;
}
.element-img {
position: relative;
width: 100%;
padding-top: 56.25%; /* 16:9 */
margin-bottom: 20px;
}
.element-img > img {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
object-fit: cover;
border-radius: 20px;
}
The padding-top
in .element-img
is what maintains the aspect ratio. When you set the padding-top
you're essentially creating an invisible box with the specified aspect ratio. The padding-top
is calculated as a percentage of the width of the element, so it maintains the aspect ratio regardless of the actual width of the element, which is what makes it responsive.
You can calculate the aspect ratio using the following formula:
Padding Percentage = (Height / Width) * 100
16:9 Example:
56.25 = (9/16) * 100
Or you can just use any percentage you think works the best :)
.grid-container {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 20px;
padding: 20px;
}
.grid-item {
background-color: #f0f0f0;
border: 1px solid #ddd;
padding: 10px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
.aspect-ratio-16-9 {
position: relative;
width: 100%;
padding-top: 56.25%;
}
.aspect-ratio-16-9 img {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
object-fit: cover;
}
<div class="grid-container">
<div class="grid-item">
<div class="aspect-ratio-16-9">
<img src="https://via.placeholder.com/300x169" alt="300x169 Image">
</div>
</div>
<div class="grid-item">
<div class="aspect-ratio-16-9">
<img src="https://via.placeholder.com/400x225" alt="400x225 Image">
</div>
</div>
<div class="grid-item">
<div class="aspect-ratio-16-9">
<img src="https://via.placeholder.com/500x281" alt="500x281 Image">
</div>
</div>
<div class="grid-item">
<div class="aspect-ratio-16-9">
<img src="https://via.placeholder.com/600x338" alt="600x338 Image">
</div>
</div>
<div class="grid-item">
<div class="aspect-ratio-16-9">
<img src="https://via.placeholder.com/700x394" alt="700x394 Image">
</div>
</div>
<div class="grid-item">
<div class="aspect-ratio-16-9">
<img src="https://via.placeholder.com/800x450" alt="800x450 Image">
</div>
</div>
<div class="grid-item">
<div class="aspect-ratio-16-9">
<img src="https://via.placeholder.com/900x506" alt="900x506 Image">
</div>
</div>
<div class="grid-item">
<div class="aspect-ratio-16-9">
<img src="https://via.placeholder.com/1000x563" alt="1000x563 Image">
</div>
</div>
</div>
Below I've included some related resources that might be useful to future users for understanding why and how this works, and to reduce issues with implementation and adjustments.