Responsive image gallery using CSS flexbox or grid-layout - css

I am working on an Image-Gallery-Widget where the user can set a thumbnail width, thumbnail height and margin (between thumbnails) and the widget will present all image-thumnails in a nice grid where each image has the same width and height.
I am wondering whether css-flexbox or css-grid makes this possible without the need to define rows and columns in code and without the need for breakpoints/media-queries.
Thumbnail-Images are wrapped in an anchor, so a gallery item (or grid-item) will look something like this:
<a href="#" class="gallery-item">
<img src="myimage" width="300" height="200" />
</a>
The gallery items should fully fill the container div, which means, there should not be a gap between the last thumbnail in a row and the container div's right edge (except if we don't have enough items to fill the row i.e. when 3 items ft in a row, but we only have 8 items, then the 3rd row will only have 2 items and a gap to the right which is as wide as one item).
Gallery items can never be wider than the thumbnail-width the user set, because we don't want to degrade the quality of the thumbnails. Let's assume 300px width for this example. The margin between gallery items is fixed and set by the user. If there are not enough items left to fill a row, simply left align them i.e. like so:
I do not want to define any breakpoints in CSS nor add any html for row/column constructs. I want the browser to simply place as much gallery items side by side as fit into the container. If there's a gap on the right (ie 3 thumbnails * 300px width = 900px, but container is 1000px wide), the browser should scale down the grid items, so that one more gallery item will fit in and thus eliminate the gap. I need to be able to define a margin around each gallery item.
You can see the desired responsive behaviour (when changing the browser width) in this gif:
What you see in the gif is done without flexbox but needs a ton of CSS which I was hoping to avoid with flexbox. I have researched flexbox quite some bit, but haven't been able to get my head around it fully just yet.
Thanks for any tips!

Using flex capabilities should be sufficient for your task. Be aware of partial support in IE11: http://caniuse.com/#feat=flexbox.
Put these styles on your container:
.gallery {
display: flex;
flex-wrap: wrap;
align-content: flex-start;
justify-content: space-between;
}
Styles for wrappers:
.gallery a {
flex-grow: 1;
flex-basis: 125px;
max-width: 300px;
margin: 5px;
}
Styles for images:
.gallery img {
height: 100%;
width: 100%;
}
Space between images can be simply defined using margin.
In order to preserve image ratio you can use for example links (<a>) as a wrappers for images (<img>).
Furthermore, in order to prevent enlarging images, you can apply flex-grow, flex-basis and max-width attributes on anchors.
There was also a problem with stretching images in the last row - hack for that is to put n - 1 (where n is number of images) empty items inside container.
Setting width and height to 100% on the images enforces them to grow automatically up to the width defined by max-width attribute, while maintaining aspect ratio.
Please check the working example:
FIDDLE

If you don't mind using media breakpoints, use new CSS Grid Layout.
Don't forget to prefix it for IE10+ support.
Grid:
.gallery {
display: grid;
grid-gap: 5px;
}
Responsive images:
.gallery img {
width: 100%;
}
Media breakpoints (values taken from Bootstrap 4)
#media (max-width: 575.98px) {
.gallery {
grid-template-columns: repeat(1, 1fr);
}
}
#media (max-width: 768.98px) and (min-width: 576px) {
.gallery {
grid-template-columns: repeat(2, 1fr);
}
}
#media (max-width: 991.98px) and (min-width: 768px) {
.gallery {
grid-template-columns: repeat(3, 1fr);
}
}
#media (max-width: 1199.98px) and (min-width: 992px) {
.gallery {
grid-template-columns: repeat(4, 1fr);
}
}
#media (min-width: 1200px) {
.gallery {
grid-template-columns: repeat(5, 1fr);
}
}
jsFiddle

Related

Grid template columns should adjust based on size of div

I am using display:grid and grid-template-columns for a div in my html page. Using media queries I am updating the number of columns in each row for this grid.
#media screen and (min-width: 200px) and (max-width:767.5px){
.options-container {
display: grid;
grid-template-columns: 100%;
}
}
#media screen and (min-width: 768px) {
.options-container {
display: grid;
grid-template-columns: 48% 48%;
column-gap: 4%;
}
}
Based on the above code, it shown one column upto 767.5px and once we cross 768px it shows 2 columns per row. All this code is working as expected.
But when the parent div width is reduced to 200px, since the screen size is still 768px it shows 2 columns per row. At this point since the parent div width is 200px I want to show only one column per row.I understand the media queries will not work since it is based on the width of the device and not the parent div. Can you please let me know how I achieve the functionality of updating number of columns per row in the grid based on parent div.

How to make a CSS grid set its height based on the size of elements without squeezing? [duplicate]

I have a CSS grid layout where I have the top row spanning the entire grid using the grid-column property.
Does anyone know how I can set this row to be 100px high and have all the subsequent rows set to a grid-auto-rows height of 200px?
I know I can input individual values with grid-template-rows for all the specific rows, but there are going to be a lot of divs on the page and don't want to input 100px and then a load of 200px values using this grid-template-rows property.
I'm thinking there must be a way to set individual pixel values on certain rows and then have everything else as grid-auto-rows?
I can't seem to find how to do this in the docs.
Any help would be awesome!
https://codepen.io/emilychews/pen/dZPJGQ
.gridwrapper {
display: grid;
grid-template-columns: repeat(2, 2fr);
grid-auto-rows: 200px;
grid-template-rows: 100px 200px;
grid-gap: 10px;
}
nav {
background: yellow;
}
.gridwrapper div {
padding: 1em;
background: red;
color: white;
box-sizing: border-box;
}
.gridwrapper div:nth-child(odd) {
background: blue;
}
nav {
grid-column: 1 / -1;
}
/*MAKE DIVS 1FR ON MOBILE*/
#media only screen and (max-width: 736px) {
.gridwrapper {
grid-template-columns: 1fr;
}
}
<div class="gridwrapper">
<nav class="grid">1</nav>
<div class="grid">2</div>
<div class="grid">3</div>
<div class="grid">4</div>
<div class="grid">5</div>
<div class="grid">6</div>
</div>
Does anyone know how I can set this row to be 100px high and have all the subsequent rows set to a grid-auto-rows height of 200px?
Yes. Grid can do this cleanly and easily.
First, you don't need to set a height value on the grid item itself. That overrides one of the great benefits of CSS Grid: the ability to control the dimensions of grid items at the container level.
You know that your grid will always have at least one row: the top row. That's your explicit grid.
You don't know how many additional rows there will be. That number is variable and unpredictable. That's your implicit grid.
The grid-template-rows and grid-template-columns properties set track sizes in the explicit grid.
The grid-auto-rows and grid-auto-columns properties set track sizes in the implicit grid.
Therefore, this is probably what you're looking for:
.gridwrapper{
display: grid;
grid-template-rows: 100px; /* top row is 100px in height */
grid-auto-rows: 200px; /* any new rows created are 200px in height */
}
revised codepen
You can use grid-template-rows property.
I guess you are looking for something like this:
https://codepen.io/harora/pen/EbaQxr
Here is a nice reference to the Grid model:
Grid Model Explained

CSS grid: Animate transition of number of columns using pure CSS (media queries)

I'm using different media queries to change the number of columns of my CSS grid depending on the browser width. I would like to achieve some kind of animation effect when the grid boxes are changing their position according to this. How can this be achieved using pure CSS?
Parts of the code:
.wrapper {
width: 100%;
display: grid;
grid-gap: 20px;
grid-template-columns: repeat(6, 300px);
grid-template-rows: repeat(10), 300px);
}
#media only screen and (max-width: 1960px) {
.wrapper {
grid-template-columns: repeat(5, 300px);
}
}
#media only screen and (max-width: 1460px) {
.wrapper {
grid-template-columns: repeat(4, 300px);
}
}
This is not possible with CSS.
The number of columns or rows is not animatable. Equally, grid areas are not elements and so cannot be selected with CSS.
Grid Template Columns
Animation type:simple list of length, percentage, or calc, provided the only differences are in the values of the length, percentage, or calc components in the list.

Row of images that fit to scale in Flexbox/Grid?

I'm trying to display a row of images using pure CSS, where the result would be that all images have the same height. For example, a taller image would shrink if it was next to a smaller image. There can be 2-6 images in a row. Given a 9:16 image and a 16:9 image, the result would ideally look something like this:
I initially tried to use Flexbox, but the column widths don't change - the image inside just scales to fit inside. I thought CSS Grid might work instead, but I can't get that working either.
Here's the HTML:
<p class="side-by-side-images">
<img src=""> // Tall image
<img src=""> // wide image
</p>
The current CSS Grid implementation:
.side-by-side-images {
display: grid;
grid-auto-rows: 1fr;
grid-template-columns: repeat(auto-fit);
grid-column-gap: 5px;
}
img {
width: 100%;
}
The current result:
Expanding from jons' answer:
You can set your fixed height (the height you want for all of your images, regardless of width) in the image container:
.image-container {
display:flex;
height:200px;
background:gray;
}
And set the height of all images to that of its container:
.image-container img {
width:auto;
height:100%;
}
Result:
view on codepen
Alternatively, including the gaps as shown in your image: view on codepen
I would just do
img {
height: 300px; // or whatever value you want
width: auto;
}
.container {
display: flex;
flex-wrap: wrap;
}
If you know the sizes of the images, the math could be more specific.

CSS - change div's display from grid to flexbox with media queries

I have a div that is a css grid container. When the page width drops below a certain size, I would like all elements of the grid to be placed on a line. I think you should be able to change the display type to flex box, I tried doing this and the grid stays the same. Here is the code I am using:
See the Pen NYjOmL by biltimi#gmail.com (#MeaningOf42) on CodePen.
/* The important part of the CSS*/
#media (max-width: 40em) {
.image {
visibility:hidden;
}
.grid-container {
display: inline-flex;
}
}
/* The Styling of the container class: */
.grid-container {
display: grid;
width: 75%;
margin: auto;
padding: 10px;
height: 100px;
grid-template-columns: 16.6% 16.6% 33% 16% 16%;
grid-template-rows: 2fr 3fr 3fr 1fr;
grid-template-areas:
". . Image . ."
"blog bikes Image about links"
"shop events Image contact team"
". . Image . ."
}
For context, I am trying to replicate deaf pigeon's website ( http://www.deafpigeon.co.uk) using as close to pure vanilla HTML and CSS to practice laying out pages. I want my div to do the same thing as the deaf pigeon navigation bar.
Does anyone have solutions? I might be going about this the wrong way if so be sure to let me know.
As Pete said, your media query needs to follow your base rules in order to override when the condition is met. The preferred approach would be to declare your mobile styles first followed by a desktop override in your media query.
.grid-container {
display: inline-flex;
}
#media all and (min-width: 40em) {
.grid-container {
display: grid;
}
}
Notice the change from max-width to min-width to ensure that this override kicks in when the viewport is larger than 40em
Just move your media query declaration to the end of the file. The media query rule you defined is getting executed but it is getting overwritten by the .grid-container rule that comes after it.

Resources