CSS Image grid spacing issue - css

Im trying to add a image grid to a section in my page.
I've used this code:
<div class="champ-container">
<img src="image" />
<img src="image" />
<img src="image" />
<img src="image" />
<img src="image" />
</div>
CSS:
#champ-container {
display: grid;
grid-gap: 10px;
grid-template-columns: repeat(3, max-content);
}
#champ-container img {
width: 100%;
}
here is what it currently doing:
There is a large space between each image, and I can't figure out why. I want maybe a 10px gap between the images. For this grid, I'm looking for three across and the rest wrapping to the next row. I dont understand how the third image ended up as its own row. all images are the same size: 288x164.

#champ-container {
display: grid;
grid-gap: 10px;
grid-template-columns: repeat(3, max-content);
}
#champ-container img {
width: 100%;
}
<div id="champ-container">
<img src="image" />
<img src="image" />
<img src="image" />
<img src="image" />
<img src="image" />
</div>

You have used champ-container class in html but you have used it as an id. Change your css to this
Correct CSS:
.champ-container {
display: grid;
grid-gap: 10px;
grid-template-columns: repeat(3, max-content);
}
.champ-container img {
width: 100%;
}

Related

How do I remove this white space while using CSS grid layout?

I am just learning how to use CSS grid layout from a crash course. While tinkering around with the grid-template-columns property, a white space has appeared under one of my cat images that I cannot get rid of.
This is my HTML:
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.gallery {
display: grid;
grid-template-columns: 200px 200px 1fr;
}
.gallery img {
width: 100%;
}
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<main>
<div class="gallery">
<img src="https://placeimg.com/640/480/animals" alt='' />
<img src="https://placeimg.com/640/480/arch" alt='' />
<img src="https://placeimg.com/640/480/nature" alt='' />
<img src="https://placeimg.com/640/480/people" alt='' />
<img src="https://placeimg.com/640/480/tech" alt='' />
</div>
</main>
Can someone help me resolve this?
Make the third image into 3 rows:
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.gallery {
display: grid;
grid-template-columns: 200px 200px 1fr;
}
.gallery img {
width: 100%;
}
.gallery img:nth-child(3) {
grid-row: span 3;
}
<div class="gallery">
<img src="https://placeimg.com/640/480/animals" >
<img src="https://placeimg.com/640/480/arch" >
<img src="https://placeimg.com/640/480/nature" >
<img src="https://placeimg.com/640/480/people" >
<img src="https://placeimg.com/640/480/tech" >
</div>
This depends on what you want to have happen instead.
grid-template-columns specifies your grid columns. By setting it to: 200px 200px 1fr you're basically instructing the browser:
There should be 3 columns for my content.
Set the first and second columns to 200px wide
Use flex for the third column.
So instead, one option would be to make use of a repeat function. The following will make 3 equal columns:
.gallery {
display: grid;
grid-template-columns: repeat(3, 1fr);
}
img {
width: 100%;
}
Also, FWIW keep an eye on both your HTML and CSS. In the HTML, you should have closing tag for <main></main>. And if you're working with vanilla CSS (not Sass or Less), your declarations for img should be outside those for .gallery.

How to achieve a responsive masonry-like layout which is continuous and results in no gaps?

How to achieve a layout with similar properties to Pintrest?
Specifically:
Responsive layout where all pictures are the same width.
All pictures are contained in a single div. There are no multiple containers trying to replicate "columns", e.g. using flexbox.
The order of the layout is such that there are no gaps. For example, if the layout is two columns, and the pictures are of width, heights: [(100,400), (100,100), (100,400), (100,100), (100,400), (100,100)], the columns will be around the same height and not 1200 for the left and 400 for the right. The screenshots below illustrate this.
Here is a screenshot showing that all photos are in a single div container.
The responsive layout:
An example of the third bullet point: the dark shower picture went below the hanging seat picture and not the external house picture. This is because the hanging seat picture has a smaller height.
Similarly when the layout is two columns wide: the picture of the bedroom goes below the handing chairs because the hanging seat picture has a smaller height.
Although this post appears similar to CSS-only masonry layout, the solutions do not result in desired outcome:
Using #Oliver Joseph Ash solution results in:
grid-container {
display: flex;
flex-flow: column wrap;
align-content: space-between;
/* Your container needs a fixed height, and it
* needs to be taller than your tallest column. */
height: 960px;
/* Optional */
background-color: #f7f7f7;
border-radius: 3px;
padding: 20px;
width: 60%;
margin: 40px auto;
counter-reset: items;
}
grid-item {
width: 24%;
/* Optional */
position: relative;
margin-bottom: 2%;
border-radius: 3px;
background-color: #a1cbfa;
border: 1px solid #4290e2;
box-shadow: 0 2px 2px rgba(0, 90, 250, 0.05), 0 4px 4px rgba(0, 90, 250, 0.05), 0 8px 8px rgba(0, 90, 250, 0.05), 0 16px 16px rgba(0, 90, 250, 0.05);
color: #fff;
padding: 15px;
box-sizing: border-box;
}
<grid-container>
<grid-item>
<a href="https://g.foolcdn.com/image/?url=https%3A%2F%2Fg.foolcdn.com%2Feditorial%2Fimages%2F492452%2Fgettyimages-1014028076.jpg&w=700&op=resize">
<img src="https://g.foolcdn.com/image/?url=https%3A%2F%2Fg.foolcdn.com%2Feditorial%2Fimages%2F492452%2Fgettyimages-1014028076.jpg&w=700&op=resize">
</a>
</grid-item>
<grid-item>
<a href="https://image.jimcdn.com/app/cms/image/transf/none/path/sa716b1500dd60f05/image/ic839a74ed6a8a054/version/1519833130/image.jpg">
<img src="https://image.jimcdn.com/app/cms/image/transf/none/path/sa716b1500dd60f05/image/ic839a74ed6a8a054/version/1519833130/image.jpg">
</a>
</grid-item>
<grid-item>
<a href="https://c8.alamy.com/comp/AXBEXR/stock-photograph-of-a-asian-teen-with-a-trumpet-to-her-ear-AXBEXR.jpg">
<img src="https://c8.alamy.com/comp/AXBEXR/stock-photograph-of-a-asian-teen-with-a-trumpet-to-her-ear-AXBEXR.jpg">
</a>
</grid-item>
<grid-item>
<a href="https://thumbs.dreamstime.com/z/cyber-woman-orange-11363555.jpg">
<img src="https://thumbs.dreamstime.com/z/cyber-woman-orange-11363555.jpg">
</a>
</grid-item>
<grid-item>
<a href="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcThObqAcFeb4byMcwLVkU1JVMYonpavYmEukk9r3rqF2oBTnd1q">
<img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcThObqAcFeb4byMcwLVkU1JVMYonpavYmEukk9r3rqF2oBTnd1q">
</a>
</grid-item>
<grid-item>
<a href="https://www.demilked.com/magazine/wp-content/uploads/2018/03/5aaa1cce4180b-funny-weird-wtf-stock-photos-57-5a3bb7ba3c266__700.jpg">
<img src="https://www.demilked.com/magazine/wp-content/uploads/2018/03/5aaa1cce4180b-funny-weird-wtf-stock-photos-57-5a3bb7ba3c266__700.jpg">
</a>
</grid-item>
<grid-item>
<a href="https://static.boredpanda.com/blog/wp-content/uploads/2018/05/emilia-clarke-making-stock-photos-5-5b0801c7504b2__700.jpg">
<img src="https://static.boredpanda.com/blog/wp-content/uploads/2018/05/emilia-clarke-making-stock-photos-5-5b0801c7504b2__700.jpg">
</a>
</grid-item>
<grid-item>
<a href="https://static.boredpanda.com/blog/wp-content/uploads/2018/05/emilia-clarke-making-stock-photos-8-5b0801cd0f33d__700.jpg">
<img src="https://static.boredpanda.com/blog/wp-content/uploads/2018/05/emilia-clarke-making-stock-photos-8-5b0801cd0f33d__700.jpg">
</a>
</grid-item>
<grid-item>
<a href="https://www.atomix.com.au/media/2017/07/StockPhotoBanner.jpg">
<img src="https://www.atomix.com.au/media/2017/07/StockPhotoBanner.jpg">
</a>
</grid-item>
</grid-container>
Which makes the output look like:
Whereas #Michael_B solution:
grid-container {
display: grid;
grid-auto-rows: 50px;
grid-gap: 10px;
grid-template-columns: repeat(auto-fill, minmax(30%, 1fr));
}
grid-item {
display: flex;
align-items: center;
justify-content: center;
font-size: 1.3em;
font-weight: bold;
color: white;
}
img {
width: 200px;
}
<grid-container>
<grid-item>
<a href="https://g.foolcdn.com/image/?url=https%3A%2F%2Fg.foolcdn.com%2Feditorial%2Fimages%2F492452%2Fgettyimages-1014028076.jpg&w=700&op=resize">
<img src="https://g.foolcdn.com/image/?url=https%3A%2F%2Fg.foolcdn.com%2Feditorial%2Fimages%2F492452%2Fgettyimages-1014028076.jpg&w=700&op=resize">
</a>
</grid-item>
<grid-item>
<a href="https://image.jimcdn.com/app/cms/image/transf/none/path/sa716b1500dd60f05/image/ic839a74ed6a8a054/version/1519833130/image.jpg">
<img src="https://image.jimcdn.com/app/cms/image/transf/none/path/sa716b1500dd60f05/image/ic839a74ed6a8a054/version/1519833130/image.jpg">
</a>
</grid-item>
<grid-item>
<a href="https://c8.alamy.com/comp/AXBEXR/stock-photograph-of-a-asian-teen-with-a-trumpet-to-her-ear-AXBEXR.jpg">
<img src="https://c8.alamy.com/comp/AXBEXR/stock-photograph-of-a-asian-teen-with-a-trumpet-to-her-ear-AXBEXR.jpg">
</a>
</grid-item>
<grid-item>
<a href="https://thumbs.dreamstime.com/z/cyber-woman-orange-11363555.jpg">
<img src="https://thumbs.dreamstime.com/z/cyber-woman-orange-11363555.jpg">
</a>
</grid-item>
<grid-item>
<a href="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcThObqAcFeb4byMcwLVkU1JVMYonpavYmEukk9r3rqF2oBTnd1q">
<img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcThObqAcFeb4byMcwLVkU1JVMYonpavYmEukk9r3rqF2oBTnd1q">
</a>
</grid-item>
<grid-item>
<a href="https://www.demilked.com/magazine/wp-content/uploads/2018/03/5aaa1cce4180b-funny-weird-wtf-stock-photos-57-5a3bb7ba3c266__700.jpg">
<img src="https://www.demilked.com/magazine/wp-content/uploads/2018/03/5aaa1cce4180b-funny-weird-wtf-stock-photos-57-5a3bb7ba3c266__700.jpg">
</a>
</grid-item>
<grid-item>
<a href="https://static.boredpanda.com/blog/wp-content/uploads/2018/05/emilia-clarke-making-stock-photos-5-5b0801c7504b2__700.jpg">
<img src="https://static.boredpanda.com/blog/wp-content/uploads/2018/05/emilia-clarke-making-stock-photos-5-5b0801c7504b2__700.jpg">
</a>
</grid-item>
<grid-item>
<a href="https://static.boredpanda.com/blog/wp-content/uploads/2018/05/emilia-clarke-making-stock-photos-8-5b0801cd0f33d__700.jpg">
<img src="https://static.boredpanda.com/blog/wp-content/uploads/2018/05/emilia-clarke-making-stock-photos-8-5b0801cd0f33d__700.jpg">
</a>
</grid-item>
<grid-item>
<a href="https://www.atomix.com.au/media/2017/07/StockPhotoBanner.jpg">
<img src="https://www.atomix.com.au/media/2017/07/StockPhotoBanner.jpg">
</a>
</grid-item>
</grid-container>
Is a lot better but results in height overlapping pictures:
My recommendation would be to set up a few "span" classes and contrain the images/masonry-items to have a height that is a multiple of the smallest unit. This approach allows for a CSS only masonry, but we need to know what multiple of the smallest unit items are beforehand (e.g. while rendering the HTML) so we can apply these span classes that could look like this:
.grid-span-2 {
grid-row-end: span 2;
}
.grid-span-3 {
grid-row-end: span 3;
}
.grid-span-4 {
grid-row-end: span 4;
}
...
If this is not possible, the next best approach is to use a little JS to dynamically calculate the row-span based on an items height. The snippet below should give an idea of how to approach this.
The most important part is the following:
const sizeItems = () => {
// only trigger DOM repaint when necessary
if ( $('.grid-container')[0].style.gridAutoRows !== '1px' ) {
$('.grid-container')[0].style.gridAutoRows = '1px';
}
$('.grid-item > *').forEach(el => {
const height = Math.floor(el.getBoundingClientRect().height);
// only trigger DOM repaint when necessary
if ( el.parentElement.style.gridRowEnd !== `span ${height}` ) {
el.parentElement.style.gridRowEnd = `span ${height}`;
}
});
}
We need to wait for images to load before we can do that, and also do it again when the viewport is resized, that's basically the rest of the JS code.
What we're doing here is to get the real/true height of the content within a grid-item. I prefer to use a wrapper element inside each grid-item and use that to measure. Why?
a) There are properties from the grid-module that can mess with the actual height of the grid-item without you seeing it and can then lead to incorrect height-calculations.
b) With this approach we can't use grid-gap (because in this extreme case we are making 1px-rows for the most precise sizing) as it would mess up the cell-heights, so to still be able to have a gap, we can use this wrapper div as well and apply padding to it to imitate the grid-gap.
For the JS approach we set grid-auto-rows: 1px;, this gives us the most flexibility in terms of item height, as basically each grid-cell can be sized to fit its content exactly, note though that there can be some small glitches of 1px, most likely due to subpixel rendering...
// micro DOM helper, just for convenience
const $ = window.$ = function(a,b){return Array.prototype.slice.call(document.querySelectorAll(a, b));};
const sizeItems = () => {
// only trigger DOM repaint when necessary
if ( $('.grid-container')[0].style.gridAutoRows !== '1px' ) {
$('.grid-container')[0].style.gridAutoRows = '1px';
}
$('.grid-item > *').forEach(el => {
const height = Math.floor(el.getBoundingClientRect().height);
// only trigger DOM repaint when necessary
if ( el.parentElement.style.gridRowEnd !== `span ${height}` ) {
el.parentElement.style.gridRowEnd = `span ${height}`;
}
});
}
Promise.all($('img').map(img => {
return new Promise(resolve => {
img.onload = () => {
resolve();
}
img.onerror = () => {
resolve();
}
});
})).then(() => {
const emit = new Event('images');
window.dispatchEvent(emit);
});
window.addEventListener('images', function(e) {
console.log('onImagesLoaded');
sizeItems();
});
window.addEventListener('load', function(e) {
console.log('onLoad');
sizeItems();
});
window.addEventListener('resize', function(e) {
console.log('onResize');
sizeItems();
});
* {
box-sizing: border-box;
margin: 0;
}
body {
font-family: sans-serif;
}
.grid-container {
background: gold;
display: grid;
grid-template-columns: repeat(auto-fill, minmax(calc(100%/3), 1fr));
grid-gap: 0; /* can't use grid gap! */
/* grid-auto-rows: auto; */
grid-auto-flow: dense;
/* if you don't want a gap on the outside of the grid when working with padding */
/* margin: -4px; */
}
#media screen and (max-width: 600px) {
.grid-container {
grid-template-columns: repeat(auto-fill, minmax(50%, 1fr));
}
}
#media screen and (max-width: 400px) {
.grid-container {
display: block;
}
}
.grid-item {
display: flex;
align-items: flex-start;
justify-content: center;
font-size: 1.3em;
font-weight: bold;
color: hsl(0,0%,14%);
}
.grid-gap {
/* if you need a grid-gap, apply padding to a wrapper element INSIDE the grid-item */
/* padding: 4px; */
overflow: hidden;
width: 100%;
}
.grid-item a,
.grid-item img {
display: block;
width: 100%; height: 100%;
}
.grid-item figcaption {
background: lightcoral;
color: white;
font-size: 14px;
font-style: italic;
padding: 4px 0;
text-align: center;
}
<div class="grid-container">
<div class="grid-item">
<div class="grid-gap">
<figure>
<a href="https://via.placeholder.com/397x625">
<img src="https://via.placeholder.com/397x625/255a60/FFFFFF" />
</a>
<figcaption>This is a caption!</figcaption>
</figure>
</div>
</div>
<div class="grid-item">
<div class="grid-gap">
<a href="https://via.placeholder.com/678x765">
<img src="https://via.placeholder.com/678x765/4496a1/FFFFFF" />
</a>
</div>
</div>
<div class="grid-item">
<div class="grid-gap">
<a href="https://via.placeholder.com/567x987">
<img src="https://via.placeholder.com/567x987/eaf8ab/FFFFFF" />
</a>
</div>
</div>
<div class="grid-item">
<div class="grid-gap">
<a href="https://via.placeholder.com/968x956">
<img src="https://via.placeholder.com/968x956/ccd47e/FFFFFF" />
</a>
</div>
</div>
<div class="grid-item">
<div class="grid-gap">
<a href="https://via.placeholder.com/987x687">
<img src="https://via.placeholder.com/987x687/255a60/FFFFFF" />
</a>
</div>
</div>
<div class="grid-item">
<div class="grid-gap">
<a href="https://via.placeholder.com/620x345">
<img src="https://via.placeholder.com/620x345/255a60/FFFFFF" />
</a>
</div>
</div>
<div class="grid-item">
<div class="grid-gap">
<a href="https://via.placeholder.com/543x789">
<img src="https://via.placeholder.com/543x789/4496a1/FFFFFF" />
</a>
</div>
</div>
<div class="grid-item">
<div class="grid-gap">
<a href="https://via.placeholder.com/376x274">
<img src="https://via.placeholder.com/376x274/eaf8ab/FFFFFF" />
</a>
</div>
</div>
<div class="grid-item">
<div class="grid-gap">
<a href="https://via.placeholder.com/468x623">
<img src="https://via.placeholder.com/468x623/9fb828/FFFFFF" />
</a>
</div>
</div>
</div>

Automatically take the biggest height CSS stylus

simple problem, sometime i have more content in card (make it bigger), and i want the one that is smaller to take automatically the height of the bigger one.
You can see explicitly what i mean on the picture attached.
I'm using quasar (vuejs framework) and stylus
Here is my code for the css of the box :
<style lang="stylus" scoped>
.q-card {
margin: 10px;
width : auto;
img {
height : 150px;
}
}
</style>
UPDATE
And the html concerned :
<ais-results :stack="true" class="row">
<template slot-scope="{ result }">
<div class="col-md-3 col-xs-6">
<q-card>
<q-card-media>
<img :src="result.picture">
</q-card-media>
<q-card-title>
{{result.name_event}}
<q-rating slot="subtitle" :max="5" />
<div slot="right" class="row items-center">
<q-icon name="place" /> 250 ft
</div>
</q-card-title>
<q-card-main>
<p v-if="result.place.location" style="color:#48C8B8">
<q-icon name="place" />{{result.place.name}}, {{result.place.location.city}}
</p>
<p class="text-faded">{{result.start_time}}</p>
</q-card-main>
<q-card-separator />
<q-card-actions>
<q-btn flat round dense icon="event" />
<q-btn flat color="primary" label="Reserve" />
</q-card-actions>
</q-card>
</div>
</template>
</ais-results>
Thanks in advance to the community !
Just use a simple CSS grid:
.grid-container {
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-row-gap: 10px;
grid-column-gap: 10px;
}
.q-card {
background-color: #f8f8f8;
box-shadow: 0 0 3px #666;
text-align: center;
}
.q-card img {
max-width: 100%;
}
<div class="grid-container">
<div class="q-card">1 <br />1.1<br />1.1.1</div>
<div class="q-card">2</div>
<div class="q-card">3
<img src="https://lorempixel.com/420/320/abstract/1/Sample" alt="" />
3.1
</div>
<div class="q-card">4</div>
</div>
All grid items will automatically have equal height on a per-row basis, which seems to be exactly what you are looking for.
If you need fixed-width columns, there you go:
grid-template-columns: repeat(2, 500px);

Responsive Design evenly spaced boxes

I have the below HTML/CSS, which is then followed by media queries in the file for the various max/min pixel sizes.
<div class="header-flags-wrapper">
<div class="flagbox1">
<img src="https://**********.blob.core.windows.net/flags/014-UK.png" />
<img src="https://**********.blob.core.windows.net/flags/015-spain.png" />
<img src="https://**********.blob.core.windows.net/flags/006-portugal.png" />
<img src="https://**********.blob.core.windows.net/flags/007-brazil.png" />
</div>
<div class="flagbox2">
<img src="https://**********.blob.core.windows.net/flags/002-cuba.png" />
<img src="https://**********.blob.core.windows.net/flags/003-venezuela.png" />
<img src="https://**********.blob.core.windows.net/flags/004-bolivia.png" />
<img src="https://**********.blob.core.windows.net/flags/005-paraguay.png" />
</div>
<div class="flagbox3">
<img src="https://**********.blob.core.windows.net/flags/001-uruguay.png" />
<img src="https://**********.blob.core.windows.net/flags/008-argentina.png" />
<img src="https://**********.blob.core.windows.net/flags/009-colombia.png" />
<img src="https://**********.blob.core.windows.net/flags/010-chile.png" />
</div>
<div class="flagbox4">
<img src="https://**********.blob.core.windows.net/flags/011-peru.png" />
<img src="https://********.blob.core.windows.net/flags/012-ecuador.png" />
<img src="https://*********.blob.core.windows.net/flags/017-angola.png" />
<img src="https://**********.blob.core.windows.net/flags/018-european-union.png" />
</div>
<span class="flagstretch"></span>
</div>
The default view on a screen 1200px wide looks good. What I can't get my head around is how to make this responsive. All other elements shrink closer together until they hit a boundary and then they change shape or wrap etc. What is the best approach to achieve this please? What I would like is that the margin on the flagboxes decreases bringing them closer together until they are touching each other then I hide the wrapper all together. Every attempt to do so has failed and like most things is probably easy when you know how.
.header-flags-wrapper {
float: left;
height: 50px;
width: 1500px;
}
.flagbox1, .flagbox2, .flagbox3, .flagbox4 {
width: 310px;
/*height: 30px;*/
/*vertical-align: top;*/
display: inline-block;
*display: inline;
zoom: 1
}
.flagbox1, .flagbox2, .flagbox3, .flagbox4 a {
float: left;
/*width: 30px;*/
padding: 2px;
margin-top: 5px;
}
.stretch {
width: 100%;
display: inline-block;
font-size: 0;
line-height: 0
}
Example of code can be seen at http://globaleyes.azurewebsites.net

Photowall with double sized highlight pictures

We are working on a picture gallery site and can't find a solution for following problem.
The picture wall contains several images. Some image (n Percent) should by highlighted and get displayed double sized on the wall.
The issue is, that I have no idea to fill the empty space left of the large picture, because its a new line.
Any ideas.
I created a fiddle for this sample here: Fiddle
<body>
<div class="size1">
</div>
<div class="size1">
</div>
<div class="size2">
</div>
<div class="size1">
</div>
<div class="size1">
</div>
<div class="size1">
</div>
<div class="size1">
</div>
<div class="size1">
</div>
<div class="size1">
</div>
<div class="size1">
</div>
<div class="size1">
</div>
<div class="size1">
</div>
<div class="size1">
</div>
<div class="size1">
</div>
</body>
div {
background-color: #f00;
float: left;
}
.size1{
width: 100px;
height: 100px;
margin: 5px;
}
.size2{
width: 210px;
height: 210px;
margin: 5px;
}
Update:
The following browsers now natively support CSS Grid Layout.
Firefox v52
Chrome v57 for Linux, macOS, Windows, iOS, and Android
Safari v10.1
iOS Safari v10.3
Opera v44
This kind of layout requirement is what the CSS Grid Layout spec aims to address. The introduction to the spec reads:
Grid Layout is a new layout model for CSS that has powerful abilities to control the sizing and positioning of boxes and their contents. Unlike Flexible Box Layout, which is single-axis–oriented, Grid Layout is optimized for 2-dimensional layouts: those in which alignment of content is desired in both dimensions.
Native browser support for CSS Grid Layout is likely to start landing in major browsers soon (as shown here) and is currently featured behind a flag in some. For non-supporting browsers this JavaScript polyfill will be necessary.
As an example, CSS Grid Layout syntax is shown in the following CSS:
HTML
<div class="wrapper">
<div class="box">1</div>
<div class="box">2</div>
<div class="box">3</div>
<div class="box">4</div>
<div class="box box--double">5</div>
<div class="box">7</div>
<div class="box">8</div>
...
</div>
</div>
CSS using the Grid layout model
.wrapper {
width: 600px;
display: grid;
grid-gap: 10px;
grid-template-columns: repeat(7, 100px);
grid-template-rows: 100px 100px 100px;
grid-auto-flow: row;
}
.box {
background-color: #444;
color: #fff;
padding: 20px;
font-size: 150%;
margin: 5px;
}
.box--double {
background-color: red;
grid-column: 3 / span 2;
grid-row: 2 / span 2;
}
DEMO
Here is a fiddle which utilizes CSS Grid Layout syntax (inc. the polyfill) to provide a general gist.
Alternatively, Masonry may be able to achieve this, however long term this will always be dependent on JavaScript.
Responsive Web Design (RWD)
The CSS Grid Layout module includes several features to simplify the creation of responsive designs. Two pertinent features which address the issues raised in the comments are:
1 Flexible Lengths
The fr unit should be used instead of specifying the relative column width as a percentage. The main benefit of the fr unit is that it avoids having to manually recalculate the percentage when the number of columns change via a media query - (You simply change the value for the number of columns only):
/* Avoid using percentages like this */
.wrapper {
grid-template-columns: repeat(7, 14.286%);
...
}
/* Use the 'fr' unit instead */
.wrapper {
grid-template-columns: repeat(7, 1fr);
...
}
2 grid-auto-flow-dense
Three values that can be assigned to the grid-auto-flow property, namely row, column, and dense.
.wrapper {
grid-auto-flow: dense;
...
}
In some situations when row, or column values are used it can produce unwanted holes/gaps in the layout. When specifying dense an algorithm attempts to fill those holes/gaps in, however this can sometimes change the the order of the items. This feature is very similar to the way Masonry places items in a different position based on available vertical space.
DEMO FOR RWD
Here is a responsive fiddle that uses both the fr unit and the dense value to avoid any gaps/holes in the layout.
EDIT(5): Updated list of browsers supporting CSS Grid Layout.
EDIT(4): Added note regarding Chrome 57 implementing CSS Grid Layout spec.
EDIT(3): Added note regarding Firefox 52 implementing CSS Grid Layout spec.
EDIT(2): Add useful CSS Grid Layout features for achieving RWD
EDIT(1): Changed sample code to terse version and updated link to external fiddle
Here's a CSS only solution, fully responsive, based on CSS columns
.columns >div {
background-color: #f00;
float: left;
-webkit-column-break-inside: avoid;
page-break-inside: avoid;
break-inside: avoid;
}
.size1{
width: 100px;
height: 100px;
margin: 5px;
}
.size2{
width: 210px;
height: 210px;
margin: 5px;
}
.columns {
width: 660px;
margin: 0 auto;
-webkit-columns: 200px 3;
-moz-columns: 200px 3;
columns: 200px 3;
-webkit-column-gap: 0;
-moz-column-gap: 0;
column-gap: 0;
}
#media (max-width: 689px) {
.columns {
width: 440px;
margin: 0 auto;
-webkit-columns: 200px 2;
-moz-columns: 200px 2;
columns: 200px 2;
}
}
#media (max-width: 459px) {
.columns {
display: flex;
flex-wrap: wrap;
max-width: 220px;
}
.columns div {
flex: 1 0 auto;
}
.columns .size1 {
flex-basis: calc(50% - 10px)
}
.columns .size2 {
flex-basis: calc(100% - 10px)
}
}
body {
padding: 0;
text-align: center;
}
#media (min-width: 920px) { /* 4 columns */
.columns {
width: 880px;
-webkit-columns: 200px 4;
-moz-columns: 200px 4;
columns: 200px 4;
}
}
#media (min-width: 1140px) { /* 5 columns */
.columns {
width: 1100px;
-webkit-columns: 200px 5;
-moz-columns: 200px 5;
columns: 200px 5;
}
}
#media (min-width: 1360px) { /* 6 columns */
.columns {
width: 1320px;
-webkit-columns: 200px 6;
-moz-columns: 200px 6;
columns: 200px 6;
}
}
#media (min-width: 1580px) {
/* respect the principle above to add as many columns as you like */
}
<div class="columns">
<div class="size2"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size2"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size2"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size2"></div>
<div class="size1"></div>
<div class="size1"></div>
</div>
For mobiles media query interval, I used flexbox, but it's just to show it's possible. You really don't have to, you can stick to box-model.
Note: You can define further media intervals. The basic idea is to have a multiple of 220px and limit it to widths that have sufficient room for all columns.
Here's the fiddle (I added it as, for some reason, SO won't allow me to resize the snippet window under ~480px, while jsFiddle does.)
fiddle here
This solution assumes you will always pair 2 small items together (so they occupy 1 row). If you want a solution where this condition doesn't have to be met by whoever adds content, and automatically tries to pair small items when they are single, you need javascript.
Timeline solution (based on comments info)
I'm guessing this is what you need? (If you decide to change classnames, you'll need to adjust both js and CSS).
$('.timeline .size2').each(function(){
//moving required number of small'uns so they fill the column
var prevIndex = $(this).prevAll('.size2,.wrap').eq(0).index(),
diff = $(this).index() - (prevIndex + 1),
toMove = (3 - (diff % 3)) %3;
if (toMove) {
for (var i = 1; i < toMove + 1; i++) {
$(this).nextAll('.size1').eq(0).addClass('moved').insertBefore($(this))
}
}
var wrap = $('<div />', {
class:'wrap'
})
//wrap 2 small'uns to make a row under a big'un
for (var i = 0; i < 2; i++) {
wrap.append($(this).nextAll('.size1').eq(0));
}
wrap.insertAfter($(this));
})
.timeline [class^="size"] {
background-color: red;
}
.size1{
width: 100px;
height: 100px;
margin: 5px;
}
.size2{
width: 210px;
height: 210px;
margin: 5px;
}
.timeline {
display: flex;
flex-direction: column;
align-content: flex-start;
height: 330px;
flex-wrap: wrap;
}
.timeline .wrap {
display: inline-flex;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="timeline">
<div class="size1"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size2"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size2"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size2"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size2"></div>
<div class="size1"></div>
<div class="size1"></div>
</div>
I tried to shorten the fiddle from RobC and replaced the fixed width in pixels with relative width in percent. So it is a little more responsive. But still have some gaps which you may prevent with some rules, like "no 2 big boxes side by side" and so on.
The Html
<div class="wrapper">
<img src="https://dummyimage.com/300x200/333/fff" class="" />
<img src="https://dummyimage.com/300x200/333/fff" class="" />
<img src="https://dummyimage.com/300x200/333/fff" class="" />
<img src="https://dummyimage.com/300x200/333/fff" class="" />
<img src="https://dummyimage.com/600x400/f33/fff" class="box--double" />
<img src="https://dummyimage.com/600x400/f33/fff" class="box--double" />
<img src="https://dummyimage.com/300x200/333/fff" class="" />
<img src="https://dummyimage.com/300x200/333/fff" class="" />
<img src="https://dummyimage.com/300x200/333/fff" class="" />
<img src="https://dummyimage.com/300x200/333/fff" class="" />
<img src="https://dummyimage.com/300x200/333/fff" class="" />
<img src="https://dummyimage.com/600x400/f33/fff" class="box--double" />
<img src="https://dummyimage.com/300x200/333/fff" class="" />
<img src="https://dummyimage.com/300x200/333/fff" class="" />
<img src="https://dummyimage.com/300x200/333/fff" class="" />
<img src="https://dummyimage.com/600x400/f33/fff" class="box--double" />
<img src="https://dummyimage.com/300x200/333/fff" class="" />
<img src="https://dummyimage.com/300x200/333/fff" class="" />
<img src="https://dummyimage.com/300x200/333/fff" class="" />
<img src="https://dummyimage.com/300x200/333/fff" class="" />
<img src="https://dummyimage.com/300x200/333/fff" class="" />
<img src="https://dummyimage.com/600x400/f33/fff" class="box--double" />
<img src="https://dummyimage.com/300x200/333/fff" class="" />
<img src="https://dummyimage.com/300x200/333/fff" class="" />
<img src="https://dummyimage.com/300x200/333/fff" class="" />
<img src="https://dummyimage.com/300x200/333/fff" class="" />
</div>
The CSS
.wrapper {
width: 100%;
display: grid;
grid-template-columns: repeat(6, 16.666%);
grid-auto-flow: row;
}
#media screen and (max-width: 940px) {
.wrapper {
grid-template-columns: repeat(5, 20%);
}
}
#media screen and (max-width: 540px) {
.wrapper {
grid-template-columns: repeat(3, 33.333%);
}
}
.wrapper > img {
background-color: #444;
color: #fff;
border: solid 1px white;
}
.box::before {
content: ' ';
display: block;
padding-top: 100%;
}
.box--double {
background-color: red;
grid-column: auto / span 2;
grid-row: auto / span 2;
}
The fiddle

Resources