<div id="fun">
<items-per-row :cycle="2">
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8/x8AAwMCAO+ip1sAAAAASUVORK5CYII=">
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII=">
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8/x8AAwMCAO+ip1sAAAAASUVORK5CYII=">
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII=">
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8/x8AAwMCAO+ip1sAAAAASUVORK5CYII=">
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII=">
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8/x8AAwMCAO+ip1sAAAAASUVORK5CYII=">
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII=">
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8/x8AAwMCAO+ip1sAAAAASUVORK5CYII=">
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII=">
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8/x8AAwMCAO+ip1sAAAAASUVORK5CYII=">
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII=">
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8/x8AAwMCAO+ip1sAAAAASUVORK5CYII=">
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII=">
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8/x8AAwMCAO+ip1sAAAAASUVORK5CYII=">
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII=">
</items-per-row>
</div>
// Rotating 2 styles!
// It kinda works out as long as ther is an odd number of items per row.
// But when there's not it just makes gross stripes. And we want to play chess.
.grid {
margin-top: 20px;
outline: 1px solid #ddd;
width: 600px;
display: grid;
grid-template-columns: repeat(3, auto);
grid-gap: 10px;
// this is the magic. 👇
grid-auto-flow: dense;
// 'Dense' is a little bit like float or absolute except it leaves it IN the order. Beautiful! (without it, when you reposition a grid item, it repositions every following item as well.)
}
// per row numbers! Normally this would happen per breakpoint.
.grid[data-per-row="2"]{
img:nth-child(4n+3) {
// this outline makes figuring out the nth-child stuff
// way easier 👇
outline: 2px solid red;
}
&[data-adjust] img:nth-child(4n+3) {
// push it to the last column.
grid-column: 2;
}
}
.grid[data-per-row="4"]{
img:nth-child(8n+5) {
// this outline makes figuring out the nth-child stuff
// way easier 👇
outline: 2px solid red;
}
&[data-adjust] img:nth-child(8n+5) {
// push it to the last column.
grid-column: 4;
}
}
.grid[data-per-row="6"]{
img:nth-child(12n+7) {
// this outline makes figuring out the nth-child stuff
// way easier 👇
outline: 2px solid red;
}
&[data-adjust] img:nth-child(12n+7) {
// push it to the last column.
grid-column: 6;
}
}
// We could probably collapse all these rules and have them get mathed out via a Sass Mixin, or a Vue component. But I've sunk enough time into this already 😉
// repeaty
.grid[data-per-row="1"]{
grid-template-columns: repeat(1, auto);
}
.grid[data-per-row="2"]{
grid-template-columns: repeat(2, auto);
}
.grid[data-per-row="3"]{
grid-template-columns: repeat(3, auto);
}
.grid[data-per-row="4"]{
grid-template-columns: repeat(4, auto);
}
.grid[data-per-row="5"]{
grid-template-columns: repeat(5, auto);
}
.grid[data-per-row="6"]{
grid-template-columns: repeat(6, auto);
}
.grid[data-per-row="7"]{
grid-template-columns: repeat(7, auto);
}
img {
width: 100%;
border: 1px solid black;
}
View Compiled
Vue.component('items-per-row',
{
name: 'items-per-row',
props: {
maxItems: {type: Number, default: 7},
cycle: {type: Number, default: 3}
},
data: function(){
return {
items: 4,
adjust: true
}
},
computed: {
options(){
return Array.from(Array(this.maxItems).keys())
}
},
template: `
<div>
<label>Items per row:
<select v-model="items">
<option v-for="opt in options">{{opt + 1}}</option>
</select>
</label>
<label v-if="!(items % cycle)">Adjust positions: <input type="checkbox" v-model="adjust"></label>
<div class="grid" :data-per-row="items" :data-adjust="adjust" :style="{ gridTemplateColumns: items }">
<slot></slot>
</div>
</div>
`
});
new Vue({ el: '#fun' })
View Compiled
This Pen doesn't use any external CSS resources.