Square CSS grid with square images? - html

Similar to this question, I want to create a perfect square grid, but inside of each grid cell, I want to place an image with 100% height.
The problem is because I did the padding-bottom: 100%; height: 0 hack, height: 100% no longer works on the image because the browser thinks the container has 0 height.
How can I set the height of the image to match that of the cell?
.grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
grid-gap: 4px;
}
.item {
overflow: hidden;
position: relative;
background-color: red;
width: 100%;
padding-bottom: 100%;
height: 0;
}
img {
position: relative;
left: 50%;
transform: translateX(-50%);
display: block;
/*height: 100%;*/
}
<div class="grid">
<div class="item">
<img src="https://picsum.photos/400/300">
</div>
<div class="item">
<img src="https://picsum.photos/300/300">
</div>
<div class="item">
<img src="https://picsum.photos/500/250">
</div>
<div class="item">
<img src="https://picsum.photos/600/300">
</div>
<div class="item">
<img src="https://picsum.photos/300/400">
</div>
<div class="item">
<img src="https://picsum.photos/300/300">
</div>
<div class="item">
<img src="https://picsum.photos/300/300">
</div>
<div class="item">
<img src="https://picsum.photos/300/300">
</div>
<div class="item">
<img src="https://picsum.photos/300/300">
</div>
<div class="item">
<img src="https://picsum.photos/300/300">
</div>
</div>
I should clarify that my intent is to stretch the image height to 100% but maintain aspect ratio. The left and right edges of the image should be clipped as needed, and the image should be centered.

You could create a "hidden" cell with a pseudo element (width:0px; height: 0px; padding-bottom: 100%;), overlap it with the real first cell and set all cells to the same height with grid-auto-rows: 1fr; and make the images absolutely positioned.
More in this article: https://medium.com/cloudaper/how-to-create-a-flexible-square-grid-with-css-grid-layout-ea48baf038f3
.grid::before {
content: '';
width: 0;
padding-bottom: 100%;
grid-row: 1 / 1;
grid-column: 1 / 1;
}
.grid > *:first-child {
grid-row: 1 / 1;
grid-column: 1 / 1;
}
.item {
overflow: hidden;
position: relative;
background-color: red;
width: 100%;
/* padding-bottom: 100%; */
/* height: 0; */
}
img {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%,-50%);
min-width: 100%;
min-height: 100%;
}

You could use object-fit: cover and then give the grid items an explicit height so that the replaced content is sized to maintain its aspect ratio while filling the element’s entire content box. object-fit MDN
This would replace your height: 0 and padding-bottom: 100% hack. When using object-fit: cover, one thing to note is that if the object's aspect ratio does not match the aspect ratio of its box, then the object will be clipped to fit.
You could not use object-fit: cover with the following CSS and the images will continue to fill 100% of the grid items height, just without the "clipped to fit" part.
.grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
grid-gap: 4px;
}
.item {
overflow: hidden;
position: relative;
background-color: red;
width: 100%;
height: 18rem; /* vary this to what you need */
}
img {
display: block;
max-width: 100%;
object-fit: cover;
width: 100%;
height: 100%;
}
<div class="grid">
<div class="item">
<img src="https://picsum.photos/400/300">
</div>
<div class="item">
<img src="https://picsum.photos/300/300">
</div>
<div class="item">
<img src="https://picsum.photos/500/250">
</div>
<div class="item">
<img src="https://picsum.photos/600/300">
</div>
<div class="item">
<img src="https://picsum.photos/300/400">
</div>
<div class="item">
<img src="https://picsum.photos/300/300">
</div>
<div class="item">
<img src="https://picsum.photos/300/300">
</div>
<div class="item">
<img src="https://picsum.photos/300/300">
</div>
<div class="item">
<img src="https://picsum.photos/300/300">
</div>
<div class="item">
<img src="https://picsum.photos/300/300">
</div>
</div>

You can do it like below:
.grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
grid-gap: 4px;
}
.item {
background-color: red;
aspect-ratio: 1; /* square items */
}
img {
/* no size contribution */
width: 0;
height: 0;
/* */
/* fill the item space*/
min-height: 100%;
min-width: 100%;
/* */
display: block;
object-fit: cover; /* avoid distortion*/
}
<div class="grid">
<div class="item">
<img src="https://picsum.photos/400/300">
</div>
<div class="item">
<img src="https://picsum.photos/300/300">
</div>
<div class="item">
<img src="https://picsum.photos/500/250">
</div>
<div class="item">
<img src="https://picsum.photos/600/300">
</div>
<div class="item">
<img src="https://picsum.photos/300/400">
</div>
<div class="item">
<img src="https://picsum.photos/300/300">
</div>
<div class="item">
<img src="https://picsum.photos/300/300">
</div>
<div class="item">
<img src="https://picsum.photos/300/300">
</div>
<div class="item">
<img src="https://picsum.photos/300/300">
</div>
<div class="item">
<img src="https://picsum.photos/300/300">
</div>
</div>

Related

auto infinite image slider with div css not working

ive been trying to make an infinite image slider with html and css, but everytime after the initial few photos are shown, there is a huge empty space before it starts appearing again, but 3 of the first photos dont show too. i can't seem to make it load infinitely like i want it to.
here's my html:
<div class="container">
<div class="banner">
<div class="profile">
<img src="img1.png" alt="">
</div>
<div class="profile">
<img src="img2.png" alt="">
</div>
<div class="profile">
<img src="img3.png" alt="">
</div>
<div class="profile">
<img src="img4.png" alt="">
</div>
<div class="profile">
<img src="img5.png" alt="">
</div>
<div class="profile">
<img src="img6.png" alt="">
</div>
<!---->
<div class="profile">
<img src="img1.png" alt="">
</div>
<div class="profile">
<img src="img2.png" alt="">
</div>
<div class="profile">
<img src="img3.png" alt="">
</div>
<div class="profile">
<img src="img4.png" alt="">
</div>
<div class="profile">
<img src="img5.png" alt="">
</div>
<div class="profile">
<img src="img6.png" alt="">
</div>
</div>
</div>
css:
.container{
height: 250px;
width: 90%;
position: relative;
display: grid;
place-items: center;
overflow: hidden;
}
.banner{
position: absolute;
overflow: hidden;
white-space: nowrap;
display: flex;
width: calc(250px*12);
animation: scroll 40s linear infinite;
}
.profile{
height: 500px;
width: 150px;
display: flex;
align-items: center;
padding: 15px;
perspective: 100px;
}
.profile img{
width: 100%;
}
thank you in advance!
This method - where there are 2 copies of the elements and a translation of -50% (so the changeover is seamless) - does not work if the elements do not cover at least the full width of the parent.
There are fixed widths in the code given which make it non responsive and on some viewports the elements will not cover the width.
This snippet removes the fixed 150px and sets the width of each element to a proportion of the viewport width to ensure coverage. If you need the actual images to be less than that in width you can of course set their width back down to 150px.
You will need to work on vertical height. The profiles have a height larger than the parent but with overflow hidden. That is a different question from getting the carousel to work however.
The keyframes are simple - a translation from 0 to half the overall width, so that the second section of images is replaced by the first half when it reaches the left hand side so making things look continuous.
.container {
height: 250px;
width: 90%;
position: relative;
/* display: grid;
place-items: center; */
overflow: hidden;
margin: 0 auto;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.banner {
position: absolute;
overflow: hidden;
white-space: nowrap;
/*display: flex;
width: calc(250px*12);*/
animation: scroll 40s linear infinite;
font-size: 0;
/* to get rid of gaps between inline elements */
}
#keyframes scroll {
0% {
transform: translateX(0);
}
100% {
transform: translateX(-50%);
}
}
.profile {
height: 500px;
/* width: 150px; */
width: calc(100vw / 5);
display: inline-flex;
align-items: center;
padding: 15px;
perspective: 100px;
font-size: initial;
}
.profile img {
width: 100%;
}
<meta name="viewport" content="width=device-width, initial-scale=1">
<div class="container">
<div class="banner">
<div class="profile">
<img src="https://picsum.photos/id/1015/200/300" alt="">
</div>
<div class="profile">
<img src="https://picsum.photos/id/1016/200/300" alt="">
</div>
<div class="profile">
<img src="https://picsum.photos/id/1015/200/300" alt="">
</div>
<div class="profile">
<img src="https://picsum.photos/id/1016/200/300" alt="">
</div>
<div class="profile">
<img src="https://picsum.photos/id/1015/200/300" alt="">
</div>
<div class="profile">
<img src="https://picsum.photos/id/1016/200/300" alt="">
</div>
<!---->
<div class="profile">
<img src="https://picsum.photos/id/1015/200/300" alt="">
</div>
<div class="profile">
<img src="https://picsum.photos/id/1016/200/300" alt="">
</div>
<div class="profile">
<img src="https://picsum.photos/id/1015/200/300" alt="">
</div>
<div class="profile">
<img src="https://picsum.photos/id/1016/200/300" alt="">
</div>
<div class="profile">
<img src="https://picsum.photos/id/1015/200/300" alt="">
</div>
<div class="profile">
<img src="https://picsum.photos/id/1016/200/300" alt="">
</div>
</div>

How to Fit image into div?

I am trying to fit my images into the div which will be a inside a drag slider. I have tried a few object-fit properties but didnt seem to work. All of my images seem to take the entire width/height of the divs they are inside but I want there to be space between the images inside the div
<div class="homes-container">
<div class="home-container-item">
<div class="home-container-img">
<img src="./assets/content-images/desktop-development-1.jpg" alt="">
</div>
<div class="home-container-img">
<img src="./assets/content-images/desktop-development-2.jpg" alt="">
</div>
<div class="home-container-img">
<img src="./assets/content-images/desktop-development-3.jpg" alt="">
</div>
<div class="home-container-img">
<img src="./assets/content-images/desktop-development-4.jpg" alt="">
</div>
<div class="home-container-img">
<img src="./assets/content-images/mobile-development-1.jpg" alt="">
</div>
<div class="home-container-img">
<img src="./assets/content-images/mobile-development-2.jpg" alt="">
</div>
<div class="home-container-img">
<img src="./assets/content-images/mobile-development-3.jpg" alt="">
</div>
<div class="home-container-img">
<img src="./assets/content-images/mobile-development-4.jpg" alt="">
</div>
</div>
</div>
.homes-container{
position: absolute;
left: 10%;
top: 12%;
width: 80%;
height: 50rem;
overflow: hidden;
background: chartreuse;
}
.home-container-item{
position: absolute;
top: 0;
left: 0;
height: 100%;
display: grid;
grid-template-columns: repeat(8, 1fr);
gap: 20px;
pointer-events: none;
transition: 1s;
object-fit: scale-down;
}
You can set the image style width and height to 100%. This should fill the div with the image.
<style>
img {
width: 100%;
height: 100%;
}
</style>

Gallery based on grid - overflow of content and images ratio issue

I am exercising my web development skills by building a simple gallery app. Unfortunately CSS turned out to be biggest problem.
html, body {
height: 100%;
width: 100%;
margin: 0;
padding: 0;
}
* {
box-sizing: border-box;
}
.main-container {
height: 100%;
width: 100%;
margin: 0 10%;
display: flex;
flex-direction: column;
}
.searchbox {
margin-bottom: 20px;
}
.gallery {
height: 100%;
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-template-rows: repeat(5, 20%);
gap: 20px;
justify-items: center;
}
.image-container {
display: flex;
flex-direction: column;
height: 100%;
}
img {
display: block;
flex: 9;
min-height: 0;
}
.title {
flex: 1;
}
.pagination {
margin-top: 20px;
}
<div class="main-container">
<div class="searchbox">SEARCHBOX</div>
<div class="gallery">
<div class="image-container">
<img src="https://placekitten.com/200/300"/>
<div class="title">TITLE</div>
</div>
<div class="image-container">
<img src="https://placekitten.com/300/200"/>
<div class="title">TITLE</div>
</div>
<div class="image-container">
<img src="https://placekitten.com/200/200"/>
<div class="title">TITLE</div>
</div>
<div class="image-container">
<img src="https://placekitten.com/400/300"/>
<div class="title">TITLE</div>
</div>
<div class="image-container">
<img src="https://placekitten.com/200/300"/>
<div class="title">TITLE</div>
</div>
<div class="image-container">
<img src="https://placekitten.com/100/300"/>
<div class="title">TITLE</div>
</div>
<div class="image-container">
<img src="https://placekitten.com/100/100"/>
<div class="title">TITLE</div>
</div>
<div class="image-container">
<img src="https://placekitten.com/200/300"/>
<div class="title">TITLE</div>
</div>
<div class="image-container">
<img src="https://placekitten.com/200/200"/>
<div class="title">TITLE</div>
</div>
<div class="image-container">
<img src="https://placekitten.com/300/100"/>
<div class="title">TITLE</div>
</div>
<div class="image-container">
<img src="https://placekitten.com/200/300"/>
<div class="title">TITLE</div>
</div>
<div class="image-container">
<img src="https://placekitten.com/200/300"/>
<div class="title">TITLE</div>
</div>
<div class="image-container">
<img src="https://placekitten.com/200/300"/>
<div class="title">TITLE</div>
</div>
<div class="image-container">
<img src="https://placekitten.com/200/300"/>
<div class="title">TITLE</div>
</div>
<div class="image-container">
<img src="https://placekitten.com/200/300"/>
<div class="title">TITLE</div>
</div>
<div class="image-container">
<img src="https://placekitten.com/200/300"/>
<div class="title">TITLE</div>
</div>
<div class="image-container">
<img src="https://placekitten.com/200/300"/>
<div class="title">TITLE</div>
</div>
<div class="image-container">
<img src="https://placekitten.com/200/300"/>
<div class="title">TITLE</div>
</div>
<div class="image-container">
<img src="https://placekitten.com/200/300"/>
<div class="title">TITLE</div>
</div>
<div class="image-container">
<img src="https://placekitten.com/200/300"/>
<div class="title">TITLE</div>
</div>
</div>
<div class="pagination">PAGINATION</div>
</div>
My gallery will have 20 images per page (4x5). The images might be of different sizes - some might be horizontal, some vertical, some square.
The problems that I have:
The images are scaled in a way that does not keep their original ratio
The "app" does not take only 100% of the height - it takes more, and I need to scroll. Ideally, 100% should be taken always
The "pagination" DIV landed somewhere inside of the grid. It should be placed below the grid.
I have to admit that I tried many different ways to fix it, however I was either getting into even weirder results, or not fixing the problem at all.
What is wrong with my CSS?
First take the height and width out of your html, body - it's directly affecting your image sizes
html, body {margin:0; padding:0;}
Then drop the margin from your main container, it's causing an overflow. Maybe you meant to use padding?
.main-container {
height: 100%;
width: 100%;
/*margin: 0 10%;*/ <--- Remove
display: flex;
flex-direction: column;
}
After that you can use the object-fit property to align your image positions :) It's important that your height and width are set though!
img {
display: block;
flex: 9;
min-height: 0;
width:300px;
max-height:300px;
object-fit:cover;
}
I hope this helps! https://jsfiddle.net/1txLvoh6/
I'd prefer this variant:
html,
body {
height: 100%;
width: 100%;
margin: 0;
padding: 0;
}
* {
box-sizing: border-box;
}
.main-container {
width: 80%;
margin: 0 10%;
display: grid;
grid-gap: 20px;
grid-template-rows: 1em max-content 1em;
grid-template-columns: 1fr;
}
.searchbox {
/* your styles for searchbox */
}
.gallery {
display: grid;
/* columns can be equal too, using calc and without justification on center */
grid-template-columns: repeat(4, 1fr);
/* 4 gaps between rows + 2 gaps above and below of gallery + search and pager heights */
grid-template-rows: repeat(5, calc(20vh - 2em));
grid-gap: 20px;
justify-items: center;
}
.image-container {
display: flex;
flex-direction: column;
height: 100%;
}
img {
display: block;
flex: 9;
min-height: 0;
object-fit: cover;
}
.title {
flex: 1;
}
.pagination {
/* your styles for pagination */
}

How to make the grid columns smaller and the same size?

I have a gallery of gifs and I put them in a grid, here's the image. I want to make the columns smaller like at least 5 images in one row, and in the same size(in the image you can see there's a difference in height).
here's the css:
.gallery {
margin: 5px;
border: 1px solid #ccc;
}
.gallery:hover {
border: 1px solid #777;
}
.gallery img {
width: 100%;
height: 100%;
object-fit:cover;
}
.container {
background-color: #222324;
padding: 20px;
margin: 20px;
overflow: auto;
text-align: center;
}
and the html:
<div class='container' style='display: grid;grid-template-columns: auto auto auto;'>
<div class='gallery'>
<img src=GIFURL>
</div>
<div class='gallery'>
<img src=GIFURL2>
</div>
...
</div>
thanks
You can have 5 images in a row with help of grid-template-columns: repeat(5, 1fr); It will accommodate 5 elements in a row all having the same width.
you can control the height of images based on viewport height by putting height: calc(100vh /3); on gallery image.
.gallery {
margin: 5px;
border: 1px solid #ccc;
}
.gallery:hover {
border: 1px solid #777;
}
.gallery img {
width: 100%;
height: calc(100vh /3);
object-fit:cover;
}
.container {
display: grid;
grid-template-columns: repeat(5, 1fr);
background-color: #222324;
padding: 20px;
margin: 20px;
overflow: auto;
text-align: center;
}
<div class='container'>
<div class='gallery'>
<img src="https://picsum.photos/id/237/200/200">
</div>
<div class='gallery'>
<img src="https://picsum.photos/id/237/200/400">
</div>
<div class='gallery'>
<img src="https://picsum.photos/id/237/200/300">
</div>
<div class='gallery'>
<img src="https://picsum.photos/id/237/200/300">
</div>
<div class='gallery'>
<img src="https://picsum.photos/id/237/200/200">
</div>
<div class='gallery'>
<img src="https://picsum.photos/id/237/200/100">
</div>
<div class='gallery'>
<img src="https://picsum.photos/id/237/200/500">
</div>
<div class='gallery'>
<img src="https://picsum.photos/id/237/200/300">
</div>
<div class='gallery'>
<img src="https://picsum.photos/id/237/200/300">
</div>
<div class='gallery'>
<img src="https://picsum.photos/id/237/200/100">
</div>
<div class='gallery'>
<img src="https://picsum.photos/id/237/200/100">
</div>
</div>

CSS Styling for div layout

Please see my HTML structure below - I am trying to have the .prod divs to be to the right of the logo, and the logo to be the full height of the .row div
I know this can be done using tables and floats but I want to try and avoid using those.
Here's my structure:
.row {
width: 100%;
}
.row > div {
display: inline-block;
}
.row .image {
height: 100%;
width: 24%;
}
.row .prod {
width: 75%;
height: auto;
}
.prod > div {
display: inline-block;
width: Calc(50% - 4px);
}
div {
border: solid 1px black;
}
<div class="row">
<div class="image">
<img alt="Full Height Logo" src="" />
</div>
<div class="prod">
<div class="prod_image">
<img alt="Product Image" src="" />
</div>
<div class="prod_info">
Prod Info
</div>
</div>
<div class="prod">
<div class="prod_image">
<img alt="Product Image" src="" />
</div>
<div class="prod_info">
Prod Info
</div>
</div>
</div>
Wrap the additional info inside another div and give it the remaining width.
I have given it 74% because of the extra space from inline-block elements. Adjust it to your requirement. I would prefer flexbox if you are implementing it for modern browsers.
.row {
width: 100%;
}
.row > div {
display: inline-block;
}
.row .image {
height: 100%;
width: 24%;
vertical-align: top; /* Default to baseline, align to the top */
}
.row .product_info {
width: 74%; /* Remaining width */
}
.row .product_info .prod {
/* width: 75% */ Remove
height: auto;
}
.prod > div {
display: inline-block;
width: Calc(50% - 4px);
}
div {
border: solid 1px black;
}
<div class="row">
<div class="image">
<img alt="Full Height Logo" src="" />
</div>
<div class="product_info">
<div class="prod">
<div class="prod_image">
<img alt="Product Image" src="" />
</div>
<div class="prod_info">
Prod Info
</div>
</div>
<div class="prod">
<div class="prod_image">
<img alt="Product Image" src="" />
</div>
<div class="prod_info">
Prod Info
</div>
</div>
</div>
</div>
flexbox can do that.
.row {
display: flex;
}
.image,
.prod {
flex: 1;
background: lightblue;
text-align: center;
height: 75px;
}
.image {
flex: 0 0 auto;
background: orange;
display: flex;
flex-direction: column;
}
.image img {
height: 100%;
width: auto;
}
<div class="row">
<div class="image">
<img alt="Full Height Logo" src="http://lorempixel.com/output/food-q-c-50-50-1.jpg" />
</div>
<div class="prod">
<div class="prod_image">
<img alt="Product Image" src="" />
</div>
<div class="prod_info">
Prod Info
</div>
</div>
<div class="prod">
<div class="prod_image">
<img alt="Product Image" src="" />
</div>
<div class="prod_info">
Prod Info
</div>
</div>
</div>
Flexbox?
I'm still pretty new to flexbox myself, but you could use the align-items: stretch property on your container to cause your items to stretch, but give the .prod div's a max-height so that they only stretch so much. You can also set various widths properties using the flex property on your flex items so that you get the width your after.
For more information: https://css-tricks.com/snippets/css/a-guide-to-flexbox/