- const IMG_DATA = {
- 'dessert 1': 'https://images.unsplash.com/photo-1564844536308-75c540dbf14e?ixlib=rb-1.2.1&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=950&fit=max&ixid=eyJhcHBfaWQiOjE0NTg5fQ',
- 'dessert 2': 'https://images.unsplash.com/photo-1548865164-c4e93ca471aa?ixlib=rb-1.2.1&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=950&fit=max&ixid=eyJhcHBfaWQiOjE0NTg5fQ',
- 'dessert 3': 'https://images.unsplash.com/photo-1502004960551-dc67f7c24cb3?ixlib=rb-1.2.1&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=950&fit=max&ixid=eyJhcHBfaWQiOjE0NTg5fQ',
- 'dessert 4': 'https://images.unsplash.com/photo-1551276705-0503a4b9d38c?ixlib=rb-1.2.1&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=950&fit=max&ixid=eyJhcHBfaWQiOjE0NTg5fQ',
- 'dessert 5': 'https://images.unsplash.com/photo-1551529563-9dd66d188764?ixlib=rb-1.2.1&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=950&fit=max&ixid=eyJhcHBfaWQiOjE0NTg5fQ',
- 'dessert 6': 'https://images.unsplash.com/photo-1473340186413-a68ba9c2564e?ixlib=rb-1.2.1&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=950&fit=max&ixid=eyJhcHBfaWQiOjE0NTg5fQ'
- };
- let min = 1, max = 6, val = 6;
mixin grid(col_rule = 'auto-fit')
article(style=`--col-rule: ${col_rule}`)
pre.dark
span.token--prop grid-template-columns
span.token--punc :
|
span.token--func repeat
span.token--punc (
span.token--args
span.token--arg.token--keyw #{col_rule}
span.token--punc ,
|
span.token--arg
span.token--func minmax
span.token--punc (
span.token--args
span.token--arg.token--len
span.token--num 15
span.token--unit %
span.token--punc ,
|
span.token--arg.token--len
span.token--num 1
span.token--unit fr
span.token--punc )
span.token--punc )
section.grid
- for(let i in IMG_DATA)
img(src=IMG_DATA[i])
body(style=`--min: ${min}; --val: ${val}; --max: ${max}`)
a(href='https://codepen.io/thebabydino/pen/gOayvpb' target='_blank') Also check out the second version! 😼
+grid
+grid('auto-fill')
form.dark
label(for='val') Thumbnails per grid:
input#val(type='range' min=min value=val max=max)
output(for='val')
View Compiled
$pad: .5em;
$gap: .5vw;
$c: orange;
$b-arrow: .5*$pad;
$track-w: 15em;
$track-h: .25em;
$track-r: .5*$track-h;
$thumb-d: 1em;
$thumb-r: .5*$thumb-d;
$mover-w: $track-w - $thumb-d;
@mixin track() {
border: none;
width: $track-w; height: $track-h;
border-radius: $track-r;
background: #e9e9e9
}
@mixin thumb($f: 0) {
margin-top: $f*($track-r - $thumb-r);
border: none;
width: $thumb-d; height: $thumb-d;
border-radius: 50%;
background: $c;
transition: all calc(var(--f)*2s)
}
* {
box-sizing: inherit;
margin: 0;
padding: 0;
background: transparent;
font: inherit
}
body {
box-sizing: border-box;
display: grid;
grid-gap: 2*$pad;
grid-template-rows: max-content 1fr 1fr max-content;
overflow-x: hidden;
margin: 0;
padding: $pad;
min-width: 375px; min-height: 100vh;
background: whitesmoke;
font: 1.25em ubuntu mono, consolas, monaco, monospace;
}
.dark {
background: #262626;
color: #d9d9d9
}
a {
place-self: center;
padding: .25em .5em;
border-radius: 5px;
background: crimson;
color: #fff;
font-weight: 900;
text-decoration: none
}
article { place-self: center stretch }
pre {
margin: $pad 0;
padding: $pad;
border-radius: 5px;
}
.token {
&--prop { color: #B7E3C0 }
&--func { color: #B8D0DD }
&--keyw {
display: inline-block;
padding: 0 .25em;
border-radius: 3px;
background: #F8F087;
color: #222;
font-weight: 900
}
&--num { color: #DBBAE5 }
&--unit { color: #F39DD4 }
@media (max-width: 680px) {
&--prop ~ &--func::before { content: '\A ' }
}
@media (max-width: 450px) {
&--prop ~ &--args > &--arg:not(:first-child)::before { content: '\A ' }
}
}
.grid {
display: grid;
grid-gap: $gap;
grid-template-columns: repeat(var(--col-rule, auto-fit), minmax(15%, 1fr));
[style*='auto-fill'] > & {
background:
repeating-linear-gradient(90deg,
transparent 0 1px,
#e9e9e9 0 calc((100% + #{$gap})/var(--max) - #{$gap} - 1px),
transparent 0 calc((100% + #{$gap})/var(--max))) 0 50%/ 100% calc(100% - 2px) no-repeat
}
}
img {
place-self: stretch;
height: Min(25vh, calc(var(--max)*26vh/var(--val)));
object-fit: cover;
border-radius: 3px;
box-shadow: 2px 2px 5px rgba(#000, .5)
}
form {
--i: var(--wide, 1);
--not-i: calc(1 - var(--i));
--focus: 0;
--not-focus: calc(1 - var(--focus));
display: grid;
place-content: center;
grid-template-columns: max-content $track-w max-content;
grid-gap: $pad;
margin: -$pad;
padding: $pad;
filter: grayScale(var(--not-focus));
&:focus-within { --focus: 1 }
@media (max-width: 610px) {
--wide: 0
}
}
label {
grid-column: calc(1 + var(--not-i));
place-self: center var(--wide, end)
}
[type='range'] {
&, &::-webkit-slider-thumb,
&::-webkit-slider-runnable-track { -webkit-appearance: none }
grid-column: 2;
grid-row: calc(1 + var(--not-i));
cursor: pointer;
&::-webkit-slider-runnable-track {
@include track()
}
&::-moz-range-track {
@include track()
}
&::-webkit-slider-thumb {
@include thumb(1)
}
&::-moz-range-thumb {
@include thumb()
}
&:focus { outline: solid 0 transparent }
}
output {
grid-column: calc(3 - var(--not-i));
grid-row: calc(1 + var(--not-i));
place-self: start;
transform:
translate(calc(var(--not-i)*(#{$thumb-r} + (var(--val) - var(--min))/(var(--max) - var(--min))*#{$mover-w} - 50%)),
calc(var(--not-i)*(#{$b-arrow} - 100%)));
&::after {
display: block;
border: solid $b-arrow transparent;
padding: 0 .5em;
border-radius: calc(#{$b-arrow} + 3px);
transform-origin: 50% 100%;
transform: scale(calc(var(--i) + var(--not-i)*var(--focus)));
background: nth($c, 1) border-box;
color: #222;
text-align: center;
--xy: calc(var(--not-i)*50%) calc(50%*(1 + var(--not-i)));
--mask:
linear-gradient(red, red) padding-box,
conic-gradient(
from calc(45deg - var(--not-i)*90deg)
at var(--xy),
red 0% 25%, transparent 0%)
var(--xy)/ 50% 50% no-repeat border-box;
-webkit-mask: var(--mask);
mask: var(--mask);
transition: transform .3s, filter .3s;
counter-reset: val var(--val);
content: counter(val)
}
}
View Compiled
const _BODY = document.body,
_GRIDS = [...document.querySelectorAll('.grid')].map(c => ({
_el: c,
_imgs: [...c.querySelectorAll('img')]
})),
_VAL = document.getElementById('val'),
FN = ['append', 'remove'];
let val = + _VAL.value;
_VAL.addEventListener('input', e => {
let new_val = +_VAL.value;
if(val !== new_val) {
_GRIDS.forEach(g => {
let dif = new_val - val,
sgn = Math.sign(dif),
bit = .5*(1 - sgn);
while(dif !== 0) {
g._el[`${FN[bit]}Child`](g._imgs[new_val - dif - bit])
dif -= sgn
}
});
}
_BODY.style.setProperty('--val', val = new_val)
}, false);
View Compiled
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.