- 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 150
              span.token--unit px
            span.token--punc ,
            |
            span.token--arg.token--len
              span.token--num 300
              span.token--unit px
          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: 0.5em;
$gap: 0.5vw;
$c: orange;

$b-arrow: 0.5 * $pad;

$track-w: 15em;
$track-h: 0.25em;
$track-r: 0.5 * $track-h;

$thumb-d: 1em;
$thumb-r: 0.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: 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: 0.25em 0.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 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(150px, 300px)
  );

  // [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, 0.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 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 0.3s, filter 0.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 = 0.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
);

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.