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 */
}
Related
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>
This question already has answers here:
Targeting flex items on the last or specific row
(10 answers)
Closed 2 years ago.
I have seen this, question has been asked a lot but I have not really gotten an answer that works. I am trying to create 3 centred divs with multiple rows using (flex box) not grid please. Is it possible and what simple way. it should be center aligned.
I am trying to achieve this.
see as its centrally aligned. but mine is kinda alined to the left and if I use Justify content:center for the wrapper the two boxes go in the middle, like this.
this is my code
<div class="wrapper">
<div id="squares">
<img src="images/galleryimage1.jpg"/>
</div>
<div id="squares">
<img src="images/galleryimage2.jpg"/>
</div>
<div id="squares">
<img src="images/galleryimage1.jpg"/>
</div>
<div id="squares">
<img src="images/galleryimage2.jpg"/>
</div>
<div id="squares">
<img src="images/galleryimage2.jpg"/>
</div>
</div>
.wrapper {
background: #ff0000;
text-align: center;
width: 90%;
height: auto;
display: -webkit-flex;
display: flex;
-webkit-flex-wrap: wrap;
flex-wrap: wrap;
padding: 0 5% 0;
justify-content: center;
}
#squares {
background: #00ff00;
width: 30%;
height: 100px;
margin: 10px;
}
#squares img {
max-height: 300px;
width: 100%;
}
#squares h5 {
margin: 20px 0;
}
here's the link to my jfiddle for a clearer picture.
https://jsfiddle.net/9ros2v4j/6/
Thanks to anyone that can explain.
.wrapper {
background: green;
text-align: center;
width: 80%;
margin-left: auto;
margin-right: auto;
}
.wrapper-inner {
padding: 5px;
display: flex;
flex-wrap: wrap;
}
.square {
flex: 0 1 33.33%;
}
.square img {
width: 100%;
display: block;
}
.square-inner {
padding: 5px;
}
<div class="wrapper">
<div class="wrapper-inner">
<div class="square">
<div class="square-inner">
<img src="http://placekitten.com/200/200" />
</div>
</div>
<div class="square">
<div class="square-inner">
<img src="http://placekitten.com/200/200" />
</div>
</div>
<div class="square">
<div class="square-inner">
<img src="http://placekitten.com/200/200" />
</div>
</div>
<div class="square">
<div class="square-inner">
<img src="http://placekitten.com/200/200" />
</div>
</div>
<div class="square">
<div class="square-inner">
<img src="http://placekitten.com/200/200" />
</div>
</div>
</div>
</div>
One requirement is for justify-content: flex-start which would place your last row as per your need.
The second requirement you're asking for is that they should be centered also. For that I think you can use equal padding on both sides to make the rows look as if they are center-aligned.
Or
If you want you can place all your items in another div inside flex-container. Then you can justify-content: center the newly created div.
You can align items to the left with justify-content: flex-start; instead of justify-content: center but in order to center it all, you might need to start playing with margins and screen size.
If you open the below example on a full page, you will be able to see the expected result.
Please also note that you used id in multiple places (#squares) which could cause issues. I replaced it with a class.
.wrapper {
position: relative;
text-align: center;
height: auto;
background: #ff0000;
display: flex;
justify-content: flex-start;
flex-wrap: wrap;
width: 100%;
}
.squares {
background: #00ff00;
width: 30%;
height: 100px;
flex: 0 31.33%;
margin: 1%;
}
#squares img {
max-height: 300px;
width: 100%;
}
#squares h5 {
margin: 20px 0;
}
<div class="wrapper">
<div class="squares">
<img src="images/galleryimage1.jpg"/>
</div>
<div class="squares">
<img src="images/galleryimage2.jpg"/>
</div>
<div class="squares">
<img src="images/galleryimage1.jpg"/>
</div>
<div class="squares">
<img src="images/galleryimage2.jpg"/>
</div>
<div class="squares">
<img src="images/galleryimage2.jpg"/>
</div>
</div>
I have several columns of images of different sizes. As the sizes are unknown, one column will be the tallest. I now want to stretch out the other (smaller) columns to match that height by increasing the gaps between the images accordingly. Here is an example image:
And here is a jsfiddle of this example that I set up with flexbox.
#main {
width: 50%;
display: flex;
justify-content: space-between;
}
.column {
background-color: lightpink;
margin-right: 20px;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.column:last-child {
margin-right: 0;
}
.column img {
width: 100%;
align-self: center;
}
<div id="main">
<div class="column">
<img src="http://placekitten.com/g/200/300">
<img src="http://placekitten.com/200/300">
<img src="http://placekitten.com/g/200/400">
</div>
<div class="column">
<img src="http://placekitten.com/g/200/200">
<img src="http://placekitten.com/200/280">
<img src="http://placekitten.com/g/200/250">
</div>
<div class="column">
<img src="http://placekitten.com/g/200/400">
<img src="http://placekitten.com/200/220">
<img src="http://placekitten.com/g/200/260">
</div>
</div>
However in my specific case, I cannot use flexbox (as I need to absolute position some children), so I am now looking for a way to achieve the same thing without flexbox. Is there any way to get this vertical "space-between" distribution without flexbox?
Based on the comment regarding absolute positioning:
I have tried to get the absolute positioning to work without any success. Basically I am trying to place captions underneath each images, however this captions should not be part of the flow, so the gaps should keep the same with as if there were no captions. When I tried to place the captions underneath, I ended up with all captions on the bottom of the entire column.
The solution is to rust wrap the images and captions in a div (or better still a figure) and give that position relative...then position your captions absolutely.
Like so:
#main {
max-width: 80%;
margin: auto;
display: flex;
justify-content: space-between;
}
.column {
background-color: lightpink;
margin-right: 20px;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.holder {
position: relative;
}
.column img {
display: block;
max-width: 100%;
height: auto;
}
.caption {
position: absolute;
bottom: 0;
text-align: center;
background: rgba(255, 255, 255, 0.5);
width: 100%;
}
<div id="main">
<div class="column">
<div class="holder">
<img src="http://placekitten.com/g/200/300">
</div>
<div class="holder"> <img src="http://placekitten.com/200/300"></div>
<div class="holder">
<img src="http://placekitten.com/g/200/400">
</div>
</div>
<div class="column">
<div class="holder">
<img src="http://placekitten.com/g/200/200">
<div class="caption">My Caption</div>
</div>
<div class="holder"> <img src="http://placekitten.com/200/280"></div>
<div class="holder">
<img src="http://placekitten.com/g/200/250">
<div class="caption">My Caption</div>
</div>
</div>
<div class="column">
<div class="holder">
<img src="http://placekitten.com/g/200/400">
<div class="caption">Superduper long Caption In Here</div>
</div>
<div class="holder"> <img src="http://placekitten.com/200/220"></div>
<div class="holder">
<img src="http://placekitten.com/g/200/260">
</div>
</div>
</div>
fix image height and use "object-fit:cover;"
#main {
width: 50%;
display: flex;
justify-content: space-between;
}
.column {
background-color: lightpink;
margin-right: 20px;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.column:last-child {
margin-right: 0;
}
.column img {
width: 100%;
align-self: center;
height:100px;
object-fit: cover;
}
<div id="main">
<div class="column">
<img src="http://placekitten.com/g/200/300">
<img src="http://placekitten.com/200/300">
<img src="http://placekitten.com/g/200/400">
</div>
<div class="column">
<img src="http://placekitten.com/g/200/200">
<img src="http://placekitten.com/200/280">
<img src="http://placekitten.com/g/200/250">
</div>
<div class="column">
<img src="http://placekitten.com/g/200/400">
<img src="http://placekitten.com/200/220">
<img src="http://placekitten.com/g/200/260">
</div>
</div>
How can I center a collection of 3 images. I would like the collection to be centered on the webpage. SIDE BY SIDE*. collection of side by side images with spacing.
.column {
float: left;
width: 30.00%;
padding: 5px;
}
/* Clear floats after image containers */
.row::after {
content: "";
clear: both;
display: table;
}
<div class="row">
<div class="column">
<img src="https://cdn.pixabay.com/photo/2017/05/09/21/49/gecko-2299365_1280.jpg" alt="BullishTrade" style="width:100%">
</div>
<div class="column">
<img src="https://cdn.pixabay.com/photo/2017/05/09/21/49/gecko-2299365_1280.jpg" alt="BullishTrade" style="width:100%">
</div>
<div class="column">
<img src="https://cdn.pixabay.com/photo/2017/05/09/21/49/gecko-2299365_1280.jpg" alt="BullishTrade" style="width:100%">
</div>
</div>
Easiest Solution to use Flex.
.row{
display:flex;
justify-content:center; //This will get your images to center.
}
Images width is purposefully reduced to 20%.
.column {
width: 20.00%;
padding: 5px;
}
/* Clear floats after image containers */
.row::after {
content: "";
clear: both;
display: table;
}
.row {
display: flex;
justify-content: center;
}
<div class="row">
<div class="column">
<img src="https://cdn.pixabay.com/photo/2017/05/09/21/49/gecko-2299365_1280.jpg" alt="BullishTrade" style="width:100%">
</div>
<div class="column">
<img src="https://cdn.pixabay.com/photo/2017/05/09/21/49/gecko-2299365_1280.jpg" alt="BullishTrade" style="width:100%">
</div>
<div class="column">
<img src="https://cdn.pixabay.com/photo/2017/05/09/21/49/gecko-2299365_1280.jpg" alt="BullishTrade" style="width:100%">
</div>
</div>
Make sure to check browser Compatibility with Flexbox.
It will work with most of the modern browsers.
One option using Grid:
body {
margin: 0;
height: 100vh;
display: grid;
align-items: center;
justify-content: center;
}
.wrapper {
display: grid;
grid-template-columns: repeat(3, 1fr);
/* change as you need */
max-width: 50vw;
}
.image img {
max-width: 100%;
height: auto;
display: block;
}
<div class="wrapper">
<div class="image">
<img src="https://unsplash.it/400" alt="BullishTrade">
</div>
<div class="image">
<img src="https://unsplash.it/400" alt="BullishTrade">
</div>
<div class="image">
<img src="https://unsplash.it/400" alt="BullishTrade">
</div>
</div>
I'm building a site using flex boxes. I have a div with 2 'columns' inside, and 2 'rows' inside of the second 'column' which I have to fill with two images each, the problem is the images doesn't fit into the 'rows' and exceeds its width.
I need my images stretch or shrink with the navigator size, so I can't use px for their size.
This is what I want:
And this is what I get:
Here is my code:
#offices {
background: peachpuff;
display: flex;
flex-wrap: wrap;
flex-direction: row;
}
.col {
background: yellow;
flex: 1;
}
.row {
background: red;
line-height: 0;
display: flex;
}
#officesImg img {
flex: 1;
width: 100%;
height: 100%;
}
<div id="offices">
<div class="col">
</div>
<div class="col" id="officesImg">
<div class="row">
<img src="http://i183.photobucket.com/albums/x312/Tiefnuker/office_01_zpsewjzabzm.jpg" />
<img src="http://i183.photobucket.com/albums/x312/Tiefnuker/office_02_zpsdz0zixcd.jpg" />
</div>
<div class="row">
<img src="http://i183.photobucket.com/albums/x312/Tiefnuker/office_01_zpsewjzabzm.jpg" />
<img src="http://i183.photobucket.com/albums/x312/Tiefnuker/office_02_zpsdz0zixcd.jpg" />
</div>
</div>
</div>
Here is a CODEPEN
PD: Please avoid float solutions.
You can set #officesImg to display:flex. And removed height:100% from the img that causes aspect ration issue on Firefox.
#offices {
background: peachpuff;
margin: 1em;
display: flex;
}
.col {
background: yellow;
margin: 1em;
flex: 1;
}
#officesImg {
line-height: 0;
display: flex;
}
#officesImg img {
width: 100%;
height: auto;
}
<div id="offices">
<div class="col">
</div>
<div class="col" id="officesImg">
<div class="row">
<img src="http://i183.photobucket.com/albums/x312/Tiefnuker/office_01_zpsewjzabzm.jpg" />
<img src="http://i183.photobucket.com/albums/x312/Tiefnuker/office_02_zpsdz0zixcd.jpg" />
</div>
<div class="row">
<img src="http://i183.photobucket.com/albums/x312/Tiefnuker/office_01_zpsewjzabzm.jpg" />
<img src="http://i183.photobucket.com/albums/x312/Tiefnuker/office_02_zpsdz0zixcd.jpg" />
</div>
</div>
</div>
Here is a slightly polished version that matches your wireframe.
#offices {
background: peachpuff;
margin: 1em;
display: flex;
}
.col {
background: yellow;
margin: 1em;
flex: 1;
}
#officesImg {
line-height: 0;
display: flex;
padding: .5em;
}
#officesImg img {
width: calc(100% - 1em);
height: auto;
margin: .5em;
}
<div id="offices">
<div class="col">
</div>
<div class="col" id="officesImg">
<div class="row">
<img src="http://i183.photobucket.com/albums/x312/Tiefnuker/office_01_zpsewjzabzm.jpg" />
<img src="http://i183.photobucket.com/albums/x312/Tiefnuker/office_02_zpsdz0zixcd.jpg" />
</div>
<div class="row">
<img src="http://i183.photobucket.com/albums/x312/Tiefnuker/office_01_zpsewjzabzm.jpg" />
<img src="http://i183.photobucket.com/albums/x312/Tiefnuker/office_02_zpsdz0zixcd.jpg" />
</div>
</div>
</div>
The quickest solution is to wrap each image element in a div.
In other words:
<div><img ... ></div>
Images remain responsive and aspect ratio is maintained.
Tested in Chrome, Firefox and IE11.
Revised Codepen