Dynamic Image Gallery

Create a flexible and engaging image gallery for your website
Responsive HTML, JS, CSS Image Gallery

Image Gallery

The photo gallery is a module used for managing images on a website. It primarily serves for browsing and enlarging pictures related to a common category. The module can be used to enlarge product photos, to present a portfolio, or as a slideshow. The following assumptions accompanied the creation of my application:

  • The gallery should use easy-to-edit and efficient CSS3 animations
  • XMLHttpRequest should be responsible for loading images
  • The photo gallery should be independent of external applications
  • The module should work in album mode and must retrieve the list of images found on other pages
  • It's desirable for the application to have an interactive thumbnail list
  • The application should automatically change images
  • The gallery should allow for the maximum enlargement of the image

According to the above assumptions, I created an application that allows for free browsing of images, creating custom animations, easy and quick customization of appearance, and the ability to create albums on the website. All options and required instructions for installation have been presented in the pages of this post (menu on the left side of the screen or in the lower right corner). I encourage you to read it.

<nav class="gallery">
  <div class="gallery-row">
    <a href="uploads/images/blog/galeria/galeria-01.jpg" class="gallery-thumbnail gallery-item"><img src="uploads/images/blog/galeria/galeria-m-01.jpg" alt="Miniatura zdjęcia"></a>
    <a href="uploads/images/blog/galeria/galeria-02.jpg" class="gallery-thumbnail gallery-item"><img src="uploads/images/blog/galeria/galeria-m-02.jpg" alt="Miniatura zdjęcia"></a>
    <a href="uploads/images/blog/galeria/galeria-03.jpg" class="gallery-thumbnail gallery-item"><img src="uploads/images/blog/galeria/galeria-m-03.jpg" alt="Miniatura zdjęcia"></a>
    <a href="uploads/images/blog/galeria/galeria-04.jpg" class="gallery-thumbnail gallery-item"><img src="uploads/images/blog/galeria/galeria-m-04.jpg" alt="Miniatura zdjęcia"></a>
    <a href="uploads/images/blog/galeria/galeria-05.jpg" class="gallery-thumbnail gallery-item"><img src="uploads/images/blog/galeria/galeria-m-05.jpg" alt="Miniatura zdjęcia"></a>
  </div>
  <div class="gallery-row">
    <a href="uploads/images/blog/galeria/galeria-06.jpg" class="gallery-thumbnail gallery-item"><img src="uploads/images/blog/galeria/galeria-m-06.jpg" alt="Miniatura zdjęcia"></a>
    <a href="uploads/images/blog/galeria/galeria-07.jpg" class="gallery-thumbnail gallery-item"><img src="uploads/images/blog/galeria/galeria-m-07.jpg" alt="Miniatura zdjęcia"></a>
    <a href="uploads/images/blog/galeria/galeria-08.jpg" class="gallery-thumbnail gallery-item"><img src="uploads/images/blog/galeria/galeria-m-08.jpg" alt="Miniatura zdjęcia"></a>
    <a href="uploads/images/blog/galeria/galeria-09.jpg" class="gallery-thumbnail gallery-item"><img src="uploads/images/blog/galeria/galeria-m-09.jpg" alt="Miniatura zdjęcia"></a>
    <a href="uploads/images/blog/galeria/galeria-10.jpg" class="gallery-thumbnail gallery-item"><img src="uploads/images/blog/galeria/galeria-m-10.jpg" alt="Miniatura zdjęcia"></a>
  </div>
</nav>
.compsoul-gallery-div, .compsoul-gallery-small, .compsoul-gallery-small,
.compsoul-gallery-big, .compsoul-gallery-hash, .compsoul-gallery-hash-test,
.compsoul-gallery-comment, .compsoul-gallery-comment-inside, .compsoul-gallery-comment-mix, .compsoul-gallery {
  display: inline-block;
  position: relative;
}

.compsoul-gallery-div:after, .compsoul-gallery-small:after, .compsoul-gallery-small:after,
.compsoul-gallery-big:after, .compsoul-gallery-hash:after, .compsoul-gallery-hash-test:after,
.compsoul-gallery-comment:after, .compsoul-gallery-comment-inside:after, .compsoul-gallery-comment-mix:after, .compsoul-gallery:after {
  bottom: 0;
  content: "";
  left: 0;
  position: absolute;
  right: 0;
  top: 0;
}

.compsoul-gallery {
  display: inline-block;
  max-width: 80%;
}

.compsoul-gallery-container {
  background: rgba(25, 25, 25, 0.96);
  bottom: 0;
  font-size: 8px;
  left: 0;
  position: fixed;
  right: 0;
  top: 0;
  will-change: auto;
  z-index: 10;
}

.compsoul-gallery-container .compsoul-hidden {
  border: 0;
  clip: rect(0 0 0 0);
  height: 1px;
  margin: -1px;
  overflow: hidden;
  position: absolute;
  padding: 0;
  width: 1px;
}

.compsoul-gallery-container.compsoul-active {
  animation: gallery-container 0.2s linear;
  will-change: opacity;
}

.compsoul-gallery-container.compsoul-inactive {
  animation: gallery-container-close 0.2s linear forwards;
  will-change: opacity;
}

@keyframes gallery-container {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

@keyframes gallery-container-close {
  from {
    opacity: 1;
  }
  to {
    opacity: 0;
  }
}

.compsoul-gallery-container button {
  background: none;
  border: none;
  cursor: pointer;
  font-size: inherit;
  line-height: 0;
  margin: 0;
  padding: 0;
}

.compsoul-gallery-content {
  bottom: 0;
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  z-index: 0;
}

.thumbnails-active .compsoul-gallery-content {
  bottom: 120px;
}

.thumbnails-inactive .compsoul-gallery-content {
  bottom: 0;
}

.compsoul-gallery-content .compsoul-gallery-item {
  height: 80vh;
  height: calc(100vh - 172px);
  left: 50%;
  position: absolute;
  top: 50%;
  transform: translate(-50%, -50%);
  user-select: none;
  visibility: hidden;
  width: 80vw;
  width: calc(100vw - 204px);
  will-change: auto;
  z-index: 0;
}

.compsoul-gallery-item.compsoul-active, .compsoul-gallery-item.compsoul-prev, .compsoul-gallery-item.compsoul-next {
  opacity: 1;
  transform: translate(-150vw, -50%);
  transition: opacity 0.3s ease-out, transform 0.3s ease-out;
  visibility: visible;
  will-change: opacity, transform;
  z-index: 1;
}

.compsoul-gallery-item.compsoul-fade {
  opacity: 0;
  transition: opacity 0.2s ease-out;
  visibility: visible;
  will-change: opacity;
}

.compsoul-direction-prev .compsoul-gallery-item.compsoul-prev,
.compsoul-direction-next .compsoul-gallery-item.compsoul-next {
  transition: unset;
  will-change: auto;
}

.compsoul-resize .compsoul-gallery-item.compsoul-prev {
  animation: compsoul-resize-prev 0.1s linear forwards;
}

@keyframes compsoul-resize-prev {
  from {
    transform: translate(-150vw, -50%);
  }
  to {
    transform: translate(-150vw, -50%);
  }
}

.compsoul-resize .compsoul-gallery-item.compsoul-next {
  animation: compsoul-resize-next 0.1s linear forwards;
}

@keyframes compsoul-resize-next {
  from {
    transform: translate(50vw, -50%);
  }
  to {
    transform: translate(50vw, -50%);
  }
}

.compsoul-gallery-item.compsoul-next {
  transform: translate(50vw, -50%);
}

.compsoul-gallery-item.compsoul-active {
  transform: translate(-50%, -50%);
}

.compsoul-disorderly .compsoul-gallery-item,
.compsoul-disorderly .compsoul-gallery-item.compsoul-prev,
.compsoul-disorderly .compsoul-gallery-item.compsoul-next {
  opacity: 0;
  transition: unset;
  visibility: hidden;
  will-change: auto;
  z-index: 2;
}

.compsoul-disorderly .compsoul-gallery-item.compsoul-past {
  animation: disorderly-past 0.2s linear;
  will-change: opacity, transform, visibility;
  z-index: 3;
}

@keyframes disorderly-past {
  0% {
    opacity: 1;
    transform: translate(-50%, -50%);
    visibility: visible;
  }
  99% {
    opacity: 0;
    transform: translate(-50%, -50%);
    visibility: visible;
  }
  100% {
    opacity: 0;
    transform: translate(-50%, -50%);
    visibility: hidden;
  }
}

.compsoul-disorderly .compsoul-gallery-item.compsoul-active {
  animation: disorderly-active 0.2s linear;
  opacity: 1;
  visibility: visible;
  will-change: opacity, transform, visibility;
  z-index: 4;
}

@keyframes disorderly-active {
  0% {
    opacity: 0;
    transform: translate(-50%, -50%);
    visibility: hidden;
  }
  1% {
    opacity: 0;
    transform: translate(-50%, -50%);
    visibility: visible;
  }
  100% {
    opacity: 1;
    transform: translate(-50%, -50%);
    visibility: visible;
  }
}

.compsoul-gallery-item .compsoul-gallery-image {
  display: inline-block;
  left: 50%;
  opacity: 0.001;
  overflow: hidden;
  position: relative;
  top: 50%;
  transform: translate(-50%, -50%);
  transform-origin: top left;
  will-change: auto;
  width: auto;
  z-index: 1;
}

.compsoul-gallery-item.compsoul-active .compsoul-gallery-image {
  transition: opacity 0.2s 0.2s linear, transform 0.2s linear;
  will-change: opacity;
}

.compsoul-gallery-item .compsoul-gallery-image:before {
  bottom: 0;
  content: "";
  left: 0;
  position: absolute;
  right: 0;
  top: 0;
}

.thumbnails-show .compsoul-gallery-image {
  transform: scale(0.8) translate(-50%, -50%);
}

.thumbnails-show .compsoul-gallery-item.compsoul-active .compsoul-gallery-image {
  will-change: transform;
}

.compsoul-gallery-item.compsoul-loaded .compsoul-gallery-image {
  opacity: 1;
}

.compsoul-gallery-item .compsoul-gallery-image img {
  display: block;
  max-height: 80vh;
  max-height: calc(100vh - 172px);
  max-width: 80vw;
  max-width: calc(100vw - 204px);
}

.compsoul-gallery-item .compsoul-gallery-comment {
  background: rgba(0, 0, 0, 0.6);
  bottom: 0;
  color: #f2f2f2;
  font-family: Calibri, Candara, Segoe, Segoe UI, Optima, Arial, sans-serif;
  font-size: 2em;
  left: 0;
  padding: 2em;
  position: absolute;
  right: 0;
  transform: translate(0, 100%);
  transition: transform 0.2s 0.4s linear;
  z-index: 1;
}

.compsoul-disorderly .compsoul-gallery-item .compsoul-gallery-comment {
  transform: translate(0, 0);
  transition: unset;
}

.compsoul-gallery-item.compsoul-active.compsoul-loaded .compsoul-gallery-comment {
  transform: translate(0, 0);
}

.compsoul-gallery-item .compsoul-gallery-comment.compsoul-inactive {
  display: none;
}

.compsoul-loader {
  left: 50%;
  opacity: 0;
  position: absolute;
  top: 50%;
  transform: translate(-50%, -50%);
  z-index: 0;
}

.compsoul-loader:before, .compsoul-loader:after {
  animation: compsoul-loading 1s linear infinite;
  animation-play-state: paused;
  border: 0.5em solid #f2f2f2;
  border-radius: 100%;
  content: "";
  display: block;
  filter: blur(1px);
  height: 8em;
  left: 50%;
  opacity: 0;
  position: absolute;
  top: 50%;
  transform: translate(-50%, -50%);
  width: 8em;
}

.compsoul-gallery-item.compsoul-active .compsoul-loader,
.compsoul-gallery-item.compsoul-prev .compsoul-loader,
.compsoul-gallery-item.compsoul-next .compsoul-loader {
  transition: opacity 0.2s linear;
}

.compsoul-gallery-item.compsoul-active .compsoul-loader {
  opacity: 1;
}

.compsoul-gallery-item.compsoul-loaded .compsoul-loader {
  opacity: 0;
}

.compsoul-gallery-item.compsoul-active.compsoul-loading .compsoul-loader:before,
.compsoul-gallery-item.compsoul-active.compsoul-loading .compsoul-loader:after {
  animation-play-state: running;
}

.compsoul-loader:after {
  animation-delay: 0.5s;
}

@keyframes compsoul-loading {
  0% {
    opacity: 0;
    transform: translate(-50%, -50%) scale(0);
  }
  50% {
    opacity: 1;
    transform: translate(-50%, -50%) scale(0.5);
  }
  100% {
    opacity: 0;
    transform: translate(-50%, -50%) scale(1);
  }
}

.compsoul-gallery-full-screen {
  background: #000;
  bottom: 0;
  font-size: 0;
  position: absolute;
  left: 0;
  opacity: 0;
  overflow: auto;
  right: 0;
  top: 0;
  transition: opacity 0.2s linear;
  z-index: -1;
}

.compsoul-gallery-full-screen.compsoul-active {
  z-index: 1;
}

.compsoul-zoom .compsoul-gallery-full-screen {
  opacity: 1;
}

.compsoul-zoom-out .compsoul-gallery-full-screen {
  opacity: 0;
  transition-delay: 0.2s;
}

.compsoul-gallery-full-screen img {
  display: block;
  margin: 0 auto;
  opacity: 0;
  transition: opacity 0.2s 0.2s linear;
}

.compsoul-zoom .compsoul-gallery-full-screen img {
  opacity: 1;
}

.compsoul-zoom-out .compsoul-gallery-full-screen img {
  opacity: 0;
  transition-delay: unset;
}

.compsoul-logo, .compsoul-gallery-close, .compsoul-gallery-next, .compsoul-gallery-prev, .thumbnails-toggle, .compsoul-gallery-progress, .compsoul-gallery-zoom {
  cursor: pointer;
  height: 7em;
  outline: 1px solid rgba(242, 242, 242, 0);
  overflow: hidden;
  position: absolute;
  right: 4em;
  top: 2em;
  transform: translate(0);
  transition: outline 0.2s linear;
  width: 7em;
}

.compsoul-logo {
  box-sizing: border-box;
  left: 4em;
  right: auto;
  transition: unset;
  width: 8em;
}

.compsoul-logo svg {
  fill: #f2f2f2;
  top: 50%;
  position: relative;
  transform: translate(0, -50%);
  transition: fill 0.2s linear;
}

.compsoul-logo:focus-within {
  outline: none;
}

.compsoul-logo:hover svg, .compsoul-logo:focus-within svg {
  fill: #e7a14f;
}

.compsoul-logo:focus-within, .compsoul-gallery-close:focus-within, .compsoul-gallery-next:focus-within, .compsoul-gallery-prev:focus-within, .thumbnails-toggle:focus-within, .compsoul-gallery-progress:focus-within, .compsoul-gallery-zoom:focus-within {
  outline-color: rgba(242, 242, 242, 0.8);
}

.compsoul-gallery-close:before, .compsoul-gallery-next:before, .compsoul-gallery-prev:before, .thumbnails-toggle:before, .compsoul-gallery-progress:before, .compsoul-gallery-zoom:before, .compsoul-gallery-close:after, .compsoul-gallery-next:after, .compsoul-gallery-prev:after, .thumbnails-toggle:after, .compsoul-gallery-progress:after, .compsoul-gallery-zoom:after {
  background: #111;
  bottom: 0;
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  z-index: -2;
}

.compsoul-gallery-close:after, .compsoul-gallery-next:after, .compsoul-gallery-prev:after, .thumbnails-toggle:after, .compsoul-gallery-progress:after, .compsoul-gallery-zoom:after {
  background: none;
  z-index: 1;
}

.compsoul-gallery-close button, .compsoul-gallery-next button, .compsoul-gallery-prev button, .thumbnails-toggle button, .compsoul-gallery-progress button, .compsoul-gallery-zoom button {
  outline: 0;
  position: relative;
  z-index: -1;
}

.compsoul-gallery-close button:before, .compsoul-gallery-close button:after, .compsoul-gallery-next button:before, .compsoul-gallery-prev button:before {
  border-top: 0.25em solid #f2f2f2;
  border-right: 0.25em solid #f2f2f2;
  box-sizing: content-box;
  content: "";
  cursor: pointer;
  display: inline-block;
  height: 1em;
  padding: 0 0 0.25em 0.25em;
  width: 1em;
}

.compsoul-gallery-close {
  z-index: 2;
}

.compsoul-gallery-close button {
  cursor: pointer;
  height: 6em;
  left: 50%;
  position: absolute;
  top: 50%;
  transform: translate(-50%, -50%) rotate(45deg);
  width: 6em;
}

.compsoul-gallery-close button:before, .compsoul-gallery-close button:after {
  bottom: 1.625em;
  left: 1.625em;
  position: absolute;
  transform: rotate(0deg);
}

.compsoul-gallery-close button:before {
  border: none;
  border-bottom: 0.25em solid #f2f2f2;
  border-left: 0.25em solid #f2f2f2;
  left: auto;
  padding: 0.25em 0.25em 0 0;
  right: 1.625em;
  top: 1.625em;
}

.compsoul-gallery-close button:after {
  border-top: 0.25em solid #f2f2f2;
  border-right: 0.25em solid #f2f2f2;
  padding: 0 0 0.25em 0.25em;
}

.compsoul-gallery-zoom {
  right: 28em;
}

.compsoul-gallery-zoom button {
  cursor: pointer;
  height: 100%;
  position: relative;
  width: 100%;
}

.compsoul-gallery-zoom button:before {
  border: 0.25em solid #f2f2f2;
  border-radius: 100%;
  content: "";
  height: 1.25em;
  left: 50%;
  position: absolute;
  top: 50%;
  transform: translate(-50%, -50%);
  width: 1.25em;
}

.compsoul-gallery-zoom button:after {
  background: #f2f2f2;
  border-radius: 0 0 0.25em 0.25em;
  content: "";
  height: 1em;
  left: 50%;
  margin: 1em 0 0 -1.5em;
  position: absolute;
  top: 50%;
  transform: rotate(45deg) translate(-50%, -50%);
  width: 0.25em;
}

.compsoul-gallery-progress {
  right: 20em;
}

.compsoul-gallery-progress button {
  cursor: pointer;
  height: 100%;
  position: relative;
  width: 100%;
}

.compsoul-gallery-progress button:before {
  border-bottom: 1em solid transparent;
  border-left: 1.2em solid #f2f2f2;
  border-top: 1em solid transparent;
  border-radius: 0.2em;
  content: "";
  height: 0;
  left: 50%;
  opacity: 1;
  position: absolute;
  top: 50%;
  transform: translate(-50%, -50%);
  transition: opacity 0.2s 0.2s linear;
  width: 0;
}

.compsoul-gallery-progress.compsoul-active button:before {
  opacity: 0;
  transition-delay: unset;
}

.compsoul-gallery-progress button:after {
  animation: gallery-progress 6s linear forwards;
  animation-play-state: paused;
  color: #f2f2f2;
  content: "10";
  font-size: 1.6em;
  left: 50%;
  opacity: 0;
  position: absolute;
  top: 50%;
  transition: opacity 0.2s linear;
  transform: translate(-50%, -50%);
}

.compsoul-gallery-progress.compsoul-active button:after {
  opacity: 1;
  transition-delay: 0.2s;
}

.compsoul-gallery-progress.compsoul-play button:after {
  animation-delay: 0.4s;
  animation-play-state: running;
}

.compsoul-gallery-progress.compsoul-unset button:after {
  animation: unset;
}

@keyframes gallery-progress {
  0% {
    content: "10";
  }
  9% {
    content: "9";
  }
  18% {
    content: "8";
  }
  27% {
    content: "7";
  }
  36% {
    content: "6";
  }
  45% {
    content: "5";
  }
  54% {
    content: "4";
  }
  63% {
    content: "3";
  }
  72% {
    content: "2";
  }
  81% {
    content: "1";
  }
  90% {
    content: "0";
  }
  100% {
    content: "0";
  }
}

.compsoul-gallery-next, .compsoul-gallery-prev {
  opacity: 0;
  right: 4em;
  top: 50%;
  transform: translate(0, -50%);
  transition: opacity 0.2s linear, outline 0.2s linear;
}

.compsoul-gallery-next.compsoul-active, .compsoul-gallery-prev.compsoul-active {
  opacity: 1;
}

.compsoul-gallery-prev {
  left: 4em;
}

.compsoul-gallery-next button, .compsoul-gallery-prev button {
  left: 50%;
  position: absolute;
  top: 50%;
  transform: translate(-1em, -50%);
}

.compsoul-gallery-prev button {
  transform: translate(-0.5em, -50%);
}

.compsoul-gallery-next button:before, .compsoul-gallery-prev button:before {
  transform: rotate(-135deg);
}

.compsoul-gallery-next button:before {
  transform: rotate(45deg);
}

.thumbnails-toggle {
  right: 12em;
}

.thumbnails-toggle button {
  cursor: pointer;
  height: 100%;
  position: relative;
  width: 100%;
}

.thumbnails-toggle button:before {
  background-color: transparent;
  background-image: linear-gradient(90deg, #f2f2f2 0.5em, transparent 0.25em),
                    linear-gradient(90deg, #f2f2f2 0.5em, transparent 0.25em),
                    linear-gradient(90deg, #f2f2f2 0.5em, transparent 0.25em);
  background-position: 0 0, 0 0.75em, 0 1.5em;
  background-repeat: repeat-x;
  background-size: 0.75em 0.5em, 0.75em 0.5em, 0.75em 0.5em;
  content: "";
  cursor: pointer;
  height: 2em;
  left: 50%;
  opacity: 0.6;
  position: absolute;
  top: 50%;
  transition: opacity 0.4s linear;
  transform: translate(-50%, -50%);
  width: 2em;
}

.thumbnails-toggle:active button:before, .thumbnails-toggle button:active:before {
  background-image: linear-gradient(90deg, #f2f2f2 0.5em, transparent 0.125em),
                    linear-gradient(90deg, #f2f2f2 0.5em, transparent 0.125em),
                    linear-gradient(90deg, #f2f2f2 0.5em, transparent 0.125em);
  background-position: 0 0, 0 0.625em, 0 1.25em;
  background-size: 0.625em 0.5em, 0.625em 0.5em, 0.625em 0.5em;
  height: 1.75em;
  width: 1.75em;
}

.thumbnails-show .thumbnails-toggle button:before {
  opacity: 1;
}

.thumbnails-container {
  background: #111;
  bottom: 0;
  font-size: 0;
  height: 72px;
  left: 0;
  letter-spacing: 0;
  position: fixed;
  right: 0;
  transition: transform 0.2s linear;
  transform: translateY(100%);
}

.thumbnails-show .thumbnails-container {
  transform: translateY(0);
}

.thumbnails-content {
  bottom: 0;
  left: 0;
  position: absolute;
  top: 0;
  white-space: nowrap;
}

.thumbnails-show .thumbnails-content  {
  transition: transform 0.2s linear;
}

.thumbnails-content.compsoul-drag {
  transition: unset;
}

.thumbnails-content.compsoul-drag:before {
  bottom: 0;
  content: "";
  left: 0;
  position: absolute;
  right: 0;
  top: 0;
  z-index: 2;
}

.thumbnails-content .thumbnails-image {
  background: none;
  border: none;
  cursor: pointer;
  display: inline-block;
  font-size: 0;
  height: 100%;
  position: relative;
  user-select: none;
}

.thumbnails-content .thumbnails-image:before, .thumbnails-content .thumbnails-image:after {
  bottom: 0;
  content: "";
  left: 0;
  opacity: 0;
  outline: 1px solid #f2f2f2;
  outline-offset: -1px;
  position: absolute;
  right: 0;
  top: 0;
  transition: opacity 0.2s linear;
  z-index: 1;
}

.thumbnails-content .thumbnails-image:after {
  outline-color: #e7a14f;
}

.thumbnails-content .thumbnails-image button:focus {
  outline: none;
}

.thumbnails-content .thumbnails-image:focus-within:before {
  opacity: 1;
}

.thumbnails-content .thumbnails-image.compsoul-active:after {
  opacity: 1;
}

.thumbnails-content .thumbnails-image img {
  display: block;
  max-height: 72px;
}

.gallery {
  display: flex;
  flex-flow: row wrap;
  gap: 10px;
}

.gallery-row {
  display: flex;
  flex: 1 100%;
  flex-flow: row nowrap;
  gap: 10px;
}

.gallery-thumbnail * {
  pointer-events: none;
}

.gallery-thumbnail img {
  height: 100%;
  object-fit: cover;
  width: 100%;
}

@media (max-width: 1000px) {
  .compsoul-gallery-container {
    font-size: 5.4px;
  }

  .compsoul-gallery-content .compsoul-gallery-item {
    height: 100vh;
    height: calc(100vh - 16px);
    width: 100vw;
    width: calc(100vw - 16px);
  }

  .thumbnails-show .compsoul-gallery-image {
    transform: scale(0.68) translate(-50%, -50%);
  }

  .compsoul-gallery-item .compsoul-gallery-image img {
    max-height: 100vh;
    max-height: calc(100vh - 16px);
    max-width: 100vw;
    max-width: calc(100vw - 16px);
  }
}

@media (max-width: 380px) {
  .compsoul-gallery-content .compsoul-gallery-item {
    height: 100vh;
    width: 100vw;
  }

  .thumbnails-show .compsoul-gallery-image {
    transform: scale(0.75) translate(-50%, -50%);
  }

  .compsoul-gallery-item .compsoul-gallery-image img {
    max-height: 100vh;
    max-width: 100vw;
  }
}
<script src="https://compsoul.dev/uploads/js/compsoul.js"></script><script src="https://compsoul.dev/uploads/js/gallery.js"></script><script>
  new Gallery(".gallery-item").init();
</script>

Installation

The module installation process can be divided into the following steps:

  1. Installation of the Compsoul library
  2. Installation of the Gallery module
  3. Instance with settings
  4. HTML code
  5. CSS code

Due to the asynchrony of the module, it requires running through a server for proper operation. Running the module directly from the disk through the browser is not possible due to security reasons.

JS

Installing JavaScript on a website involves downloading the files, copying the code responsible for importing the files, and declaring the instance. Remember that the script requires a server to work correctly. You can freely edit the instance settings and the module file itself.

Installing the Compsoul Library

Installation Instructions:

  • Click on the link to download the library: Compsoul Library
  • Save the file to a specific location and add its path to the src attribute of the <script> tag. It's important to pay close attention to the file path to avoid common installation errors.
  • Place the <script> tag just before the closing body tag.

Example Code:

    <!-- Page content -->
    <script src="[YOUR PATH HERE]/compsoul.js"></script>
    <script src="[YOUR PATH HERE]/[YOUR MODULE FILE HERE]"></script>
    <script>
      new Example(".example").init();
    </script>
  </body>
</html>

Installation of the Gallery Module

  • Download the module by clicking this link.
  • Save the file in a specific location and then place it in the src attribute of the <script> tag. Incorrect path settings often occur during installation, so special attention should be paid to this point.
  • Place the <script> tag just after the previously added Compsoul library.

The gallery application requires the download and inclusion of the appropriate file (click to download) in the page code. The file is imported by placing a <script> tag in the page code and setting the appropriate src attribute to point to the file (click to download).

    <!-- Page content -->
    <script src="[YOUR PATH HERE]/compsoul.js"></script>
    <script src="[YOUR PATH HERE]/[YOUR MODULE FILE HERE]"></script>
    <script>
      new Example(".example").init();
    </script>
  </body>
</html>

Instance of the Gallery Module

Below, I have presented all possible gallery settings. I tried to give them names analogous to their purpose, which allows for quick configuration without the need to search the documentation (no one likes that). The following sub-pages of the entry (menu on the left side of the screen or in the lower right corner) accurately present the settings with all possible options and their description.

    <!-- Content -->
    <script src="compsoul.js"></script>
    <script src="gallery.js"></script>
    <script>
      new Gallery(".gallery-item").options({
        galleryClassContainer: "compsoul-gallery-container",
        galleryClassContent: "compsoul-gallery-content",
        galleryClassClose: "compsoul-gallery-close",
        galleryClassNext: "compsoul-gallery-next",
        galleryClassPrev: "compsoul-gallery-prev",
        galleryClassProgress: "compsoul-gallery-progress",
        galleryClassItem: "compsoul-gallery-item",
        galleryClassImage: "compsoul-gallery-image",
        galleryClassComment: "compsoul-gallery-comment",
        galleryClassZoom: "compsoul-gallery-zoom",
        galleryClassFullScreen: "compsoul-gallery-full-screen",

        thumbnailsClassContainer: "thumbnails-container",
        thumbnailsClassContent: "thumbnails-content",
        thumbnailsClassToggle: "thumbnails-toggle",
        thumbnailsClassShow: "thumbnails-show",
        thumbnailsClassImage: "thumbnails-image",

        classActive: "compsoul-active",
        classInactive: "compsoul-inactive",
        classNext: "compsoul-next",
        classPrev: "compsoul-prev",
        classFade: "compsoul-fade",
        classPast: "compsoul-past",
        classReady: "compsoul-ready",
        classResize: "compsoul-resize",
        classLoader: "compsoul-loader",
        classLoading: "compsoul-loading",
        classLoaded: "compsoul-loaded",
        classError: "compsoul-error",
        classZoom: "compsoul-zoom",
        classZoomOut: "compsoul-zoom-out",
        classOverflow: "compsoul-overflow",
        classDirectionNext: "compsoul-direction-next",
        classDirectionPrev: "compsoul-direction-prev",
        classPlay: "compsoul-play",
        classHidden: "compsoul-hidden",
        classUnset: "compsoul-unset",
        classDrag: "compsoul-drag",
        classDisorderly: "compsoul-disorderly",
        classLogo: "compsoul-logo",
        selector: selector,

        close: true,
        closeDelay: 200,
        next: true,
        prev: true,

        album: false,
        albumStart: 0,
        preload: true,
        counter: true,
        loop: true,
        zoom: true,
        zoomDelay: 400,
        overflow: true,
        hash: true,
        thumbnails: true,

        keyNext: ["ArrowRight", "d", "KeyD"],
        keyPrev: ["ArrowLeft", "a", "KeyA"],
        keyClose: ["Escape", "x", "KeyX"],
        keyCounter: ["Space"],
        keyThumbnails: ["t", "KeyT"],
        keyZoom: ["z", "KeyZ"],
        responsive: {
          400: {
            loop: false
          },
          800: {
            loop: true
          },
          1300: {
            loop: false
          }
        }
      }).init();
    </script>
  </body>
</html>

HTML

The HTML code of the application is a thumbnail list, with the parent element being the <a> tag, containing the address of the target photo or album. The code of the application must be placed before the declaration of the instance and import of the JavaScript files. Additionally, we must pay special attention to the clickable element of our thumbnails, as the module requires that the event (click) be performed on the <a> element for it to work correctly. To correctly configure the content of each thumbnail, it must have the following style: pointer-events: none;. In the default CSS code, all elements inside the thumbnail have been "deprived" of the ability to click.

<nav class="gallery">
  <div class="gallery-row">
    <a href="uploads/images/blog/galeria/galeria-01.jpg" class="gallery-thumbnail gallery-item"><img src="uploads/images/blog/galeria/galeria-m-01.jpg" alt="Miniatura zdjęcia"></a>
    <a href="uploads/images/blog/galeria/galeria-02.jpg" class="gallery-thumbnail gallery-item"><img src="uploads/images/blog/galeria/galeria-m-02.jpg" alt="Miniatura zdjęcia"></a>
    <a href="uploads/images/blog/galeria/galeria-03.jpg" class="gallery-thumbnail gallery-item"><img src="uploads/images/blog/galeria/galeria-m-03.jpg" alt="Miniatura zdjęcia"></a>
    <a href="uploads/images/blog/galeria/galeria-04.jpg" class="gallery-thumbnail gallery-item"><img src="uploads/images/blog/galeria/galeria-m-04.jpg" alt="Miniatura zdjęcia"></a>
    <a href="uploads/images/blog/galeria/galeria-05.jpg" class="gallery-thumbnail gallery-item"><img src="uploads/images/blog/galeria/galeria-m-05.jpg" alt="Miniatura zdjęcia"></a>
  </div>
  <div class="gallery-row">
    <a href="uploads/images/blog/galeria/galeria-06.jpg" class="gallery-thumbnail gallery-item"><img src="uploads/images/blog/galeria/galeria-m-06.jpg" alt="Miniatura zdjęcia"></a>
    <a href="uploads/images/blog/galeria/galeria-07.jpg" class="gallery-thumbnail gallery-item"><img src="uploads/images/blog/galeria/galeria-m-07.jpg" alt="Miniatura zdjęcia"></a>
    <a href="uploads/images/blog/galeria/galeria-08.jpg" class="gallery-thumbnail gallery-item"><img src="uploads/images/blog/galeria/galeria-m-08.jpg" alt="Miniatura zdjęcia"></a>
    <a href="uploads/images/blog/galeria/galeria-09.jpg" class="gallery-thumbnail gallery-item"><img src="uploads/images/blog/galeria/galeria-m-09.jpg" alt="Miniatura zdjęcia"></a>
    <a href="uploads/images/blog/galeria/galeria-10.jpg" class="gallery-thumbnail gallery-item"><img src="uploads/images/blog/galeria/galeria-m-10.jpg" alt="Miniatura zdjęcia"></a>
  </div>
</nav>

CSS

The appearance of the gallery and thumbnail list is set via CSS styles, which are added to our stylesheet. This is a pure CSS code, which should not conflict with external libraries.

.compsoul-gallery-div, .compsoul-gallery-small, .compsoul-gallery-small,
.compsoul-gallery-big, .compsoul-gallery-hash, .compsoul-gallery-hash-test,
.compsoul-gallery-comment, .compsoul-gallery-comment-inside, .compsoul-gallery-comment-mix, .compsoul-gallery {
  display: inline-block;
  position: relative;
}

.compsoul-gallery-div:after, .compsoul-gallery-small:after, .compsoul-gallery-small:after,
.compsoul-gallery-big:after, .compsoul-gallery-hash:after, .compsoul-gallery-hash-test:after,
.compsoul-gallery-comment:after, .compsoul-gallery-comment-inside:after, .compsoul-gallery-comment-mix:after, .compsoul-gallery:after {
  bottom: 0;
  content: "";
  left: 0;
  position: absolute;
  right: 0;
  top: 0;
}

.compsoul-gallery {
  display: inline-block;
  max-width: 80%;
}

.compsoul-gallery-container {
  background: rgba(25, 25, 25, 0.96);
  bottom: 0;
  font-size: 8px;
  left: 0;
  position: fixed;
  right: 0;
  top: 0;
  will-change: auto;
  z-index: 10;
}

.compsoul-gallery-container .compsoul-hidden {
  border: 0;
  clip: rect(0 0 0 0);
  height: 1px;
  margin: -1px;
  overflow: hidden;
  position: absolute;
  padding: 0;
  width: 1px;
}

.compsoul-gallery-container.compsoul-active {
  animation: gallery-container 0.2s linear;
  will-change: opacity;
}

.compsoul-gallery-container.compsoul-inactive {
  animation: gallery-container-close 0.2s linear forwards;
  will-change: opacity;
}

@keyframes gallery-container {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

@keyframes gallery-container-close {
  from {
    opacity: 1;
  }
  to {
    opacity: 0;
  }
}

.compsoul-gallery-container button {
  background: none;
  border: none;
  cursor: pointer;
  font-size: inherit;
  line-height: 0;
  margin: 0;
  padding: 0;
}

.compsoul-gallery-content {
  bottom: 0;
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  z-index: 0;
}

.thumbnails-active .compsoul-gallery-content {
  bottom: 120px;
}

.thumbnails-inactive .compsoul-gallery-content {
  bottom: 0;
}

.compsoul-gallery-content .compsoul-gallery-item {
  height: 80vh;
  height: calc(100vh - 172px);
  left: 50%;
  position: absolute;
  top: 50%;
  transform: translate(-50%, -50%);
  user-select: none;
  visibility: hidden;
  width: 80vw;
  width: calc(100vw - 204px);
  will-change: auto;
  z-index: 0;
}

.compsoul-gallery-item.compsoul-active, .compsoul-gallery-item.compsoul-prev, .compsoul-gallery-item.compsoul-next {
  opacity: 1;
  transform: translate(-150vw, -50%);
  transition: opacity 0.3s ease-out, transform 0.3s ease-out;
  visibility: visible;
  will-change: opacity, transform;
  z-index: 1;
}

.compsoul-gallery-item.compsoul-fade {
  opacity: 0;
  transition: opacity 0.2s ease-out;
  visibility: visible;
  will-change: opacity;
}

.compsoul-direction-prev .compsoul-gallery-item.compsoul-prev,
.compsoul-direction-next .compsoul-gallery-item.compsoul-next {
  transition: unset;
  will-change: auto;
}

.compsoul-resize .compsoul-gallery-item.compsoul-prev {
  animation: compsoul-resize-prev 0.1s linear forwards;
}

@keyframes compsoul-resize-prev {
  from {
    transform: translate(-150vw, -50%);
  }
  to {
    transform: translate(-150vw, -50%);
  }
}

.compsoul-resize .compsoul-gallery-item.compsoul-next {
  animation: compsoul-resize-next 0.1s linear forwards;
}

@keyframes compsoul-resize-next {
  from {
    transform: translate(50vw, -50%);
  }
  to {
    transform: translate(50vw, -50%);
  }
}

.compsoul-gallery-item.compsoul-next {
  transform: translate(50vw, -50%);
}

.compsoul-gallery-item.compsoul-active {
  transform: translate(-50%, -50%);
}

.compsoul-disorderly .compsoul-gallery-item,
.compsoul-disorderly .compsoul-gallery-item.compsoul-prev,
.compsoul-disorderly .compsoul-gallery-item.compsoul-next {
  opacity: 0;
  transition: unset;
  visibility: hidden;
  will-change: auto;
  z-index: 2;
}

.compsoul-disorderly .compsoul-gallery-item.compsoul-past {
  animation: disorderly-past 0.2s linear;
  will-change: opacity, transform, visibility;
  z-index: 3;
}

@keyframes disorderly-past {
  0% {
    opacity: 1;
    transform: translate(-50%, -50%);
    visibility: visible;
  }
  99% {
    opacity: 0;
    transform: translate(-50%, -50%);
    visibility: visible;
  }
  100% {
    opacity: 0;
    transform: translate(-50%, -50%);
    visibility: hidden;
  }
}

.compsoul-disorderly .compsoul-gallery-item.compsoul-active {
  animation: disorderly-active 0.2s linear;
  opacity: 1;
  visibility: visible;
  will-change: opacity, transform, visibility;
  z-index: 4;
}

@keyframes disorderly-active {
  0% {
    opacity: 0;
    transform: translate(-50%, -50%);
    visibility: hidden;
  }
  1% {
    opacity: 0;
    transform: translate(-50%, -50%);
    visibility: visible;
  }
  100% {
    opacity: 1;
    transform: translate(-50%, -50%);
    visibility: visible;
  }
}

.compsoul-gallery-item .compsoul-gallery-image {
  display: inline-block;
  left: 50%;
  opacity: 0.001;
  overflow: hidden;
  position: relative;
  top: 50%;
  transform: translate(-50%, -50%);
  transform-origin: top left;
  will-change: auto;
  width: auto;
  z-index: 1;
}

.compsoul-gallery-item.compsoul-active .compsoul-gallery-image {
  transition: opacity 0.2s 0.2s linear, transform 0.2s linear;
  will-change: opacity;
}

.compsoul-gallery-item .compsoul-gallery-image:before {
  bottom: 0;
  content: "";
  left: 0;
  position: absolute;
  right: 0;
  top: 0;
}

.thumbnails-show .compsoul-gallery-image {
  transform: scale(0.8) translate(-50%, -50%);
}

.thumbnails-show .compsoul-gallery-item.compsoul-active .compsoul-gallery-image {
  will-change: transform;
}

.compsoul-gallery-item.compsoul-loaded .compsoul-gallery-image {
  opacity: 1;
}

.compsoul-gallery-item .compsoul-gallery-image img {
  display: block;
  max-height: 80vh;
  max-height: calc(100vh - 172px);
  max-width: 80vw;
  max-width: calc(100vw - 204px);
}

.compsoul-gallery-item .compsoul-gallery-comment {
  background: rgba(0, 0, 0, 0.6);
  bottom: 0;
  color: #f2f2f2;
  font-family: Calibri, Candara, Segoe, Segoe UI, Optima, Arial, sans-serif;
  font-size: 2em;
  left: 0;
  padding: 2em;
  position: absolute;
  right: 0;
  transform: translate(0, 100%);
  transition: transform 0.2s 0.4s linear;
  z-index: 1;
}

.compsoul-disorderly .compsoul-gallery-item .compsoul-gallery-comment {
  transform: translate(0, 0);
  transition: unset;
}

.compsoul-gallery-item.compsoul-active.compsoul-loaded .compsoul-gallery-comment {
  transform: translate(0, 0);
}

.compsoul-gallery-item .compsoul-gallery-comment.compsoul-inactive {
  display: none;
}

.compsoul-loader {
  left: 50%;
  opacity: 0;
  position: absolute;
  top: 50%;
  transform: translate(-50%, -50%);
  z-index: 0;
}

.compsoul-loader:before, .compsoul-loader:after {
  animation: compsoul-loading 1s linear infinite;
  animation-play-state: paused;
  border: 0.5em solid #f2f2f2;
  border-radius: 100%;
  content: "";
  display: block;
  filter: blur(1px);
  height: 8em;
  left: 50%;
  opacity: 0;
  position: absolute;
  top: 50%;
  transform: translate(-50%, -50%);
  width: 8em;
}

.compsoul-gallery-item.compsoul-active .compsoul-loader,
.compsoul-gallery-item.compsoul-prev .compsoul-loader,
.compsoul-gallery-item.compsoul-next .compsoul-loader {
  transition: opacity 0.2s linear;
}

.compsoul-gallery-item.compsoul-active .compsoul-loader {
  opacity: 1;
}

.compsoul-gallery-item.compsoul-loaded .compsoul-loader {
  opacity: 0;
}

.compsoul-gallery-item.compsoul-active.compsoul-loading .compsoul-loader:before,
.compsoul-gallery-item.compsoul-active.compsoul-loading .compsoul-loader:after {
  animation-play-state: running;
}

.compsoul-loader:after {
  animation-delay: 0.5s;
}

@keyframes compsoul-loading {
  0% {
    opacity: 0;
    transform: translate(-50%, -50%) scale(0);
  }
  50% {
    opacity: 1;
    transform: translate(-50%, -50%) scale(0.5);
  }
  100% {
    opacity: 0;
    transform: translate(-50%, -50%) scale(1);
  }
}

.compsoul-gallery-full-screen {
  background: #000;
  bottom: 0;
  font-size: 0;
  position: absolute;
  left: 0;
  opacity: 0;
  overflow: auto;
  right: 0;
  top: 0;
  transition: opacity 0.2s linear;
  z-index: -1;
}

.compsoul-gallery-full-screen.compsoul-active {
  z-index: 1;
}

.compsoul-zoom .compsoul-gallery-full-screen {
  opacity: 1;
}

.compsoul-zoom-out .compsoul-gallery-full-screen {
  opacity: 0;
  transition-delay: 0.2s;
}

.compsoul-gallery-full-screen img {
  display: block;
  margin: 0 auto;
  opacity: 0;
  transition: opacity 0.2s 0.2s linear;
}

.compsoul-zoom .compsoul-gallery-full-screen img {
  opacity: 1;
}

.compsoul-zoom-out .compsoul-gallery-full-screen img {
  opacity: 0;
  transition-delay: unset;
}

.compsoul-logo, .compsoul-gallery-close, .compsoul-gallery-next, .compsoul-gallery-prev, .thumbnails-toggle, .compsoul-gallery-progress, .compsoul-gallery-zoom {
  cursor: pointer;
  height: 7em;
  outline: 1px solid rgba(242, 242, 242, 0);
  overflow: hidden;
  position: absolute;
  right: 4em;
  top: 2em;
  transform: translate(0);
  transition: outline 0.2s linear;
  width: 7em;
}

.compsoul-logo {
  box-sizing: border-box;
  left: 4em;
  right: auto;
  transition: unset;
  width: 8em;
}

.compsoul-logo svg {
  fill: #f2f2f2;
  top: 50%;
  position: relative;
  transform: translate(0, -50%);
  transition: fill 0.2s linear;
}

.compsoul-logo:focus-within {
  outline: none;
}

.compsoul-logo:hover svg, .compsoul-logo:focus-within svg {
  fill: #e7a14f;
}

.compsoul-logo:focus-within, .compsoul-gallery-close:focus-within, .compsoul-gallery-next:focus-within, .compsoul-gallery-prev:focus-within, .thumbnails-toggle:focus-within, .compsoul-gallery-progress:focus-within, .compsoul-gallery-zoom:focus-within {
  outline-color: rgba(242, 242, 242, 0.8);
}

.compsoul-gallery-close:before, .compsoul-gallery-next:before, .compsoul-gallery-prev:before, .thumbnails-toggle:before, .compsoul-gallery-progress:before, .compsoul-gallery-zoom:before, .compsoul-gallery-close:after, .compsoul-gallery-next:after, .compsoul-gallery-prev:after, .thumbnails-toggle:after, .compsoul-gallery-progress:after, .compsoul-gallery-zoom:after {
  background: #111;
  bottom: 0;
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  z-index: -2;
}

.compsoul-gallery-close:after, .compsoul-gallery-next:after, .compsoul-gallery-prev:after, .thumbnails-toggle:after, .compsoul-gallery-progress:after, .compsoul-gallery-zoom:after {
  background: none;
  z-index: 1;
}

.compsoul-gallery-close button, .compsoul-gallery-next button, .compsoul-gallery-prev button, .thumbnails-toggle button, .compsoul-gallery-progress button, .compsoul-gallery-zoom button {
  outline: 0;
  position: relative;
  z-index: -1;
}

.compsoul-gallery-close button:before, .compsoul-gallery-close button:after, .compsoul-gallery-next button:before, .compsoul-gallery-prev button:before {
  border-top: 0.25em solid #f2f2f2;
  border-right: 0.25em solid #f2f2f2;
  box-sizing: content-box;
  content: "";
  cursor: pointer;
  display: inline-block;
  height: 1em;
  padding: 0 0 0.25em 0.25em;
  width: 1em;
}

.compsoul-gallery-close {
  z-index: 2;
}

.compsoul-gallery-close button {
  cursor: pointer;
  height: 6em;
  left: 50%;
  position: absolute;
  top: 50%;
  transform: translate(-50%, -50%) rotate(45deg);
  width: 6em;
}

.compsoul-gallery-close button:before, .compsoul-gallery-close button:after {
  bottom: 1.625em;
  left: 1.625em;
  position: absolute;
  transform: rotate(0deg);
}

.compsoul-gallery-close button:before {
  border: none;
  border-bottom: 0.25em solid #f2f2f2;
  border-left: 0.25em solid #f2f2f2;
  left: auto;
  padding: 0.25em 0.25em 0 0;
  right: 1.625em;
  top: 1.625em;
}

.compsoul-gallery-close button:after {
  border-top: 0.25em solid #f2f2f2;
  border-right: 0.25em solid #f2f2f2;
  padding: 0 0 0.25em 0.25em;
}

.compsoul-gallery-zoom {
  right: 28em;
}

.compsoul-gallery-zoom button {
  cursor: pointer;
  height: 100%;
  position: relative;
  width: 100%;
}

.compsoul-gallery-zoom button:before {
  border: 0.25em solid #f2f2f2;
  border-radius: 100%;
  content: "";
  height: 1.25em;
  left: 50%;
  position: absolute;
  top: 50%;
  transform: translate(-50%, -50%);
  width: 1.25em;
}

.compsoul-gallery-zoom button:after {
  background: #f2f2f2;
  border-radius: 0 0 0.25em 0.25em;
  content: "";
  height: 1em;
  left: 50%;
  margin: 1em 0 0 -1.5em;
  position: absolute;
  top: 50%;
  transform: rotate(45deg) translate(-50%, -50%);
  width: 0.25em;
}

.compsoul-gallery-progress {
  right: 20em;
}

.compsoul-gallery-progress button {
  cursor: pointer;
  height: 100%;
  position: relative;
  width: 100%;
}

.compsoul-gallery-progress button:before {
  border-bottom: 1em solid transparent;
  border-left: 1.2em solid #f2f2f2;
  border-top: 1em solid transparent;
  border-radius: 0.2em;
  content: "";
  height: 0;
  left: 50%;
  opacity: 1;
  position: absolute;
  top: 50%;
  transform: translate(-50%, -50%);
  transition: opacity 0.2s 0.2s linear;
  width: 0;
}

.compsoul-gallery-progress.compsoul-active button:before {
  opacity: 0;
  transition-delay: unset;
}

.compsoul-gallery-progress button:after {
  animation: gallery-progress 6s linear forwards;
  animation-play-state: paused;
  color: #f2f2f2;
  content: "10";
  font-size: 1.6em;
  left: 50%;
  opacity: 0;
  position: absolute;
  top: 50%;
  transition: opacity 0.2s linear;
  transform: translate(-50%, -50%);
}

.compsoul-gallery-progress.compsoul-active button:after {
  opacity: 1;
  transition-delay: 0.2s;
}

.compsoul-gallery-progress.compsoul-play button:after {
  animation-delay: 0.4s;
  animation-play-state: running;
}

.compsoul-gallery-progress.compsoul-unset button:after {
  animation: unset;
}

@keyframes gallery-progress {
  0% {
    content: "10";
  }
  9% {
    content: "9";
  }
  18% {
    content: "8";
  }
  27% {
    content: "7";
  }
  36% {
    content: "6";
  }
  45% {
    content: "5";
  }
  54% {
    content: "4";
  }
  63% {
    content: "3";
  }
  72% {
    content: "2";
  }
  81% {
    content: "1";
  }
  90% {
    content: "0";
  }
  100% {
    content: "0";
  }
}

.compsoul-gallery-next, .compsoul-gallery-prev {
  opacity: 0;
  right: 4em;
  top: 50%;
  transform: translate(0, -50%);
  transition: opacity 0.2s linear, outline 0.2s linear;
}

.compsoul-gallery-next.compsoul-active, .compsoul-gallery-prev.compsoul-active {
  opacity: 1;
}

.compsoul-gallery-prev {
  left: 4em;
}

.compsoul-gallery-next button, .compsoul-gallery-prev button {
  left: 50%;
  position: absolute;
  top: 50%;
  transform: translate(-1em, -50%);
}

.compsoul-gallery-prev button {
  transform: translate(-0.5em, -50%);
}

.compsoul-gallery-next button:before, .compsoul-gallery-prev button:before {
  transform: rotate(-135deg);
}

.compsoul-gallery-next button:before {
  transform: rotate(45deg);
}

.thumbnails-toggle {
  right: 12em;
}

.thumbnails-toggle button {
  cursor: pointer;
  height: 100%;
  position: relative;
  width: 100%;
}

.thumbnails-toggle button:before {
  background-color: transparent;
  background-image: linear-gradient(90deg, #f2f2f2 0.5em, transparent 0.25em),
                    linear-gradient(90deg, #f2f2f2 0.5em, transparent 0.25em),
                    linear-gradient(90deg, #f2f2f2 0.5em, transparent 0.25em);
  background-position: 0 0, 0 0.75em, 0 1.5em;
  background-repeat: repeat-x;
  background-size: 0.75em 0.5em, 0.75em 0.5em, 0.75em 0.5em;
  content: "";
  cursor: pointer;
  height: 2em;
  left: 50%;
  opacity: 0.6;
  position: absolute;
  top: 50%;
  transition: opacity 0.4s linear;
  transform: translate(-50%, -50%);
  width: 2em;
}

.thumbnails-toggle:active button:before, .thumbnails-toggle button:active:before {
  background-image: linear-gradient(90deg, #f2f2f2 0.5em, transparent 0.125em),
                    linear-gradient(90deg, #f2f2f2 0.5em, transparent 0.125em),
                    linear-gradient(90deg, #f2f2f2 0.5em, transparent 0.125em);
  background-position: 0 0, 0 0.625em, 0 1.25em;
  background-size: 0.625em 0.5em, 0.625em 0.5em, 0.625em 0.5em;
  height: 1.75em;
  width: 1.75em;
}

.thumbnails-show .thumbnails-toggle button:before {
  opacity: 1;
}

.thumbnails-container {
  background: #111;
  bottom: 0;
  font-size: 0;
  height: 72px;
  left: 0;
  letter-spacing: 0;
  position: fixed;
  right: 0;
  transition: transform 0.2s linear;
  transform: translateY(100%);
}

.thumbnails-show .thumbnails-container {
  transform: translateY(0);
}

.thumbnails-content {
  bottom: 0;
  left: 0;
  position: absolute;
  top: 0;
  white-space: nowrap;
}

.thumbnails-show .thumbnails-content  {
  transition: transform 0.2s linear;
}

.thumbnails-content.compsoul-drag {
  transition: unset;
}

.thumbnails-content.compsoul-drag:before {
  bottom: 0;
  content: "";
  left: 0;
  position: absolute;
  right: 0;
  top: 0;
  z-index: 2;
}

.thumbnails-content .thumbnails-image {
  background: none;
  border: none;
  cursor: pointer;
  display: inline-block;
  font-size: 0;
  height: 100%;
  position: relative;
  user-select: none;
}

.thumbnails-content .thumbnails-image:before, .thumbnails-content .thumbnails-image:after {
  bottom: 0;
  content: "";
  left: 0;
  opacity: 0;
  outline: 1px solid #f2f2f2;
  outline-offset: -1px;
  position: absolute;
  right: 0;
  top: 0;
  transition: opacity 0.2s linear;
  z-index: 1;
}

.thumbnails-content .thumbnails-image:after {
  outline-color: #e7a14f;
}

.thumbnails-content .thumbnails-image button:focus {
  outline: none;
}

.thumbnails-content .thumbnails-image:focus-within:before {
  opacity: 1;
}

.thumbnails-content .thumbnails-image.compsoul-active:after {
  opacity: 1;
}

.thumbnails-content .thumbnails-image img {
  display: block;
  max-height: 72px;
}

.gallery {
  display: flex;
  flex-flow: row wrap;
  gap: 10px;
}

.gallery-row {
  display: flex;
  flex: 1 100%;
  flex-flow: row nowrap;
  gap: 10px;
}

.gallery-thumbnail * {
  pointer-events: none;
}

.gallery-thumbnail img {
  height: 100%;
  object-fit: cover;
  width: 100%;
}

@media (max-width: 1000px) {
  .compsoul-gallery-container {
    font-size: 5.4px;
  }

  .compsoul-gallery-content .compsoul-gallery-item {
    height: 100vh;
    height: calc(100vh - 16px);
    width: 100vw;
    width: calc(100vw - 16px);
  }

  .thumbnails-show .compsoul-gallery-image {
    transform: scale(0.68) translate(-50%, -50%);
  }

  .compsoul-gallery-item .compsoul-gallery-image img {
    max-height: 100vh;
    max-height: calc(100vh - 16px);
    max-width: 100vw;
    max-width: calc(100vw - 16px);
  }
}

@media (max-width: 380px) {
  .compsoul-gallery-content .compsoul-gallery-item {
    height: 100vh;
    width: 100vw;
  }

  .thumbnails-show .compsoul-gallery-image {
    transform: scale(0.75) translate(-50%, -50%);
  }

  .compsoul-gallery-item .compsoul-gallery-image img {
    max-height: 100vh;
    max-width: 100vw;
  }
}

Demo

Below is a demo of the application with the default settings. A correct installation on your server should result in an identical module appearing. The gallery uses photos by Retrato Feminino. The author placed their work in a free photo bank, specifying their copyrights as "free to use".

<nav class="gallery">
  <div class="gallery-row">
    <a href="uploads/images/blog/galeria/galeria-01.jpg" class="gallery-thumbnail gallery-demo"><img src="uploads/images/blog/galeria/galeria-m-01.jpg" alt="Miniatura zdjęcia"></a>
    <a href="uploads/images/blog/galeria/galeria-02.jpg" class="gallery-thumbnail gallery-demo"><img src="uploads/images/blog/galeria/galeria-m-02.jpg" alt="Miniatura zdjęcia"></a>
    <a href="uploads/images/blog/galeria/galeria-03.jpg" class="gallery-thumbnail gallery-demo"><img src="uploads/images/blog/galeria/galeria-m-03.jpg" alt="Miniatura zdjęcia"></a>
    <a href="uploads/images/blog/galeria/galeria-04.jpg" class="gallery-thumbnail gallery-demo"><img src="uploads/images/blog/galeria/galeria-m-04.jpg" alt="Miniatura zdjęcia"></a>
    <a href="uploads/images/blog/galeria/galeria-05.jpg" class="gallery-thumbnail gallery-demo"><img src="uploads/images/blog/galeria/galeria-m-05.jpg" alt="Miniatura zdjęcia"></a>
  </div>
  <div class="gallery-row">
    <a href="uploads/images/blog/galeria/galeria-06.jpg" class="gallery-thumbnail gallery-demo"><img src="uploads/images/blog/galeria/galeria-m-06.jpg" alt="Miniatura zdjęcia"></a>
    <a href="uploads/images/blog/galeria/galeria-07.jpg" class="gallery-thumbnail gallery-demo"><img src="uploads/images/blog/galeria/galeria-m-07.jpg" alt="Miniatura zdjęcia"></a>
    <a href="uploads/images/blog/galeria/galeria-08.jpg" class="gallery-thumbnail gallery-demo"><img src="uploads/images/blog/galeria/galeria-m-08.jpg" alt="Miniatura zdjęcia"></a>
    <a href="uploads/images/blog/galeria/galeria-09.jpg" class="gallery-thumbnail gallery-demo"><img src="uploads/images/blog/galeria/galeria-m-09.jpg" alt="Miniatura zdjęcia"></a>
    <a href="uploads/images/blog/galeria/galeria-10.jpg" class="gallery-thumbnail gallery-demo"><img src="uploads/images/blog/galeria/galeria-m-10.jpg" alt="Miniatura zdjęcia"></a>
  </div>
</nav>
.compsoul-gallery-div, .compsoul-gallery-small, .compsoul-gallery-small,
.compsoul-gallery-big, .compsoul-gallery-hash, .compsoul-gallery-hash-test,
.compsoul-gallery-comment, .compsoul-gallery-comment-inside, .compsoul-gallery-comment-mix, .compsoul-gallery {
  display: inline-block;
  position: relative;
}

.compsoul-gallery-div:after, .compsoul-gallery-small:after, .compsoul-gallery-small:after,
.compsoul-gallery-big:after, .compsoul-gallery-hash:after, .compsoul-gallery-hash-test:after,
.compsoul-gallery-comment:after, .compsoul-gallery-comment-inside:after, .compsoul-gallery-comment-mix:after, .compsoul-gallery:after {
  bottom: 0;
  content: "";
  left: 0;
  position: absolute;
  right: 0;
  top: 0;
}

.compsoul-gallery {
  display: inline-block;
  max-width: 80%;
}

.compsoul-gallery-container {
  background: rgba(25, 25, 25, 0.96);
  bottom: 0;
  font-size: 8px;
  left: 0;
  position: fixed;
  right: 0;
  top: 0;
  will-change: auto;
  z-index: 10;
}

.compsoul-gallery-container .compsoul-hidden {
  border: 0;
  clip: rect(0 0 0 0);
  height: 1px;
  margin: -1px;
  overflow: hidden;
  position: absolute;
  padding: 0;
  width: 1px;
}

.compsoul-gallery-container.compsoul-active {
  animation: gallery-container 0.2s linear;
  will-change: opacity;
}

.compsoul-gallery-container.compsoul-inactive {
  animation: gallery-container-close 0.2s linear forwards;
  will-change: opacity;
}

@keyframes gallery-container {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

@keyframes gallery-container-close {
  from {
    opacity: 1;
  }
  to {
    opacity: 0;
  }
}

.compsoul-gallery-container button {
  background: none;
  border: none;
  cursor: pointer;
  font-size: inherit;
  line-height: 0;
  margin: 0;
  padding: 0;
}

.compsoul-gallery-content {
  bottom: 0;
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  z-index: 0;
}

.thumbnails-active .compsoul-gallery-content {
  bottom: 120px;
}

.thumbnails-inactive .compsoul-gallery-content {
  bottom: 0;
}

.compsoul-gallery-content .compsoul-gallery-item {
  height: 80vh;
  height: calc(100vh - 172px);
  left: 50%;
  position: absolute;
  top: 50%;
  transform: translate(-50%, -50%);
  user-select: none;
  visibility: hidden;
  width: 80vw;
  width: calc(100vw - 204px);
  will-change: auto;
  z-index: 0;
}

.compsoul-gallery-item.compsoul-active, .compsoul-gallery-item.compsoul-prev, .compsoul-gallery-item.compsoul-next {
  opacity: 1;
  transform: translate(-150vw, -50%);
  transition: opacity 0.3s ease-out, transform 0.3s ease-out;
  visibility: visible;
  will-change: opacity, transform;
  z-index: 1;
}

.compsoul-gallery-item.compsoul-fade {
  opacity: 0;
  transition: opacity 0.2s ease-out;
  visibility: visible;
  will-change: opacity;
}

.compsoul-direction-prev .compsoul-gallery-item.compsoul-prev,
.compsoul-direction-next .compsoul-gallery-item.compsoul-next {
  transition: unset;
  will-change: auto;
}

.compsoul-resize .compsoul-gallery-item.compsoul-prev {
  animation: compsoul-resize-prev 0.1s linear forwards;
}

@keyframes compsoul-resize-prev {
  from {
    transform: translate(-150vw, -50%);
  }
  to {
    transform: translate(-150vw, -50%);
  }
}

.compsoul-resize .compsoul-gallery-item.compsoul-next {
  animation: compsoul-resize-next 0.1s linear forwards;
}

@keyframes compsoul-resize-next {
  from {
    transform: translate(50vw, -50%);
  }
  to {
    transform: translate(50vw, -50%);
  }
}

.compsoul-gallery-item.compsoul-next {
  transform: translate(50vw, -50%);
}

.compsoul-gallery-item.compsoul-active {
  transform: translate(-50%, -50%);
}

.compsoul-disorderly .compsoul-gallery-item,
.compsoul-disorderly .compsoul-gallery-item.compsoul-prev,
.compsoul-disorderly .compsoul-gallery-item.compsoul-next {
  opacity: 0;
  transition: unset;
  visibility: hidden;
  will-change: auto;
  z-index: 2;
}

.compsoul-disorderly .compsoul-gallery-item.compsoul-past {
  animation: disorderly-past 0.2s linear;
  will-change: opacity, transform, visibility;
  z-index: 3;
}

@keyframes disorderly-past {
  0% {
    opacity: 1;
    transform: translate(-50%, -50%);
    visibility: visible;
  }
  99% {
    opacity: 0;
    transform: translate(-50%, -50%);
    visibility: visible;
  }
  100% {
    opacity: 0;
    transform: translate(-50%, -50%);
    visibility: hidden;
  }
}

.compsoul-disorderly .compsoul-gallery-item.compsoul-active {
  animation: disorderly-active 0.2s linear;
  opacity: 1;
  visibility: visible;
  will-change: opacity, transform, visibility;
  z-index: 4;
}

@keyframes disorderly-active {
  0% {
    opacity: 0;
    transform: translate(-50%, -50%);
    visibility: hidden;
  }
  1% {
    opacity: 0;
    transform: translate(-50%, -50%);
    visibility: visible;
  }
  100% {
    opacity: 1;
    transform: translate(-50%, -50%);
    visibility: visible;
  }
}

.compsoul-gallery-item .compsoul-gallery-image {
  display: inline-block;
  left: 50%;
  opacity: 0.001;
  overflow: hidden;
  position: relative;
  top: 50%;
  transform: translate(-50%, -50%);
  transform-origin: top left;
  will-change: auto;
  width: auto;
  z-index: 1;
}

.compsoul-gallery-item.compsoul-active .compsoul-gallery-image {
  transition: opacity 0.2s 0.2s linear, transform 0.2s linear;
  will-change: opacity;
}

.compsoul-gallery-item .compsoul-gallery-image:before {
  bottom: 0;
  content: "";
  left: 0;
  position: absolute;
  right: 0;
  top: 0;
}

.thumbnails-show .compsoul-gallery-image {
  transform: scale(0.8) translate(-50%, -50%);
}

.thumbnails-show .compsoul-gallery-item.compsoul-active .compsoul-gallery-image {
  will-change: transform;
}

.compsoul-gallery-item.compsoul-loaded .compsoul-gallery-image {
  opacity: 1;
}

.compsoul-gallery-item .compsoul-gallery-image img {
  display: block;
  max-height: 80vh;
  max-height: calc(100vh - 172px);
  max-width: 80vw;
  max-width: calc(100vw - 204px);
}

.compsoul-gallery-item .compsoul-gallery-comment {
  background: rgba(0, 0, 0, 0.6);
  bottom: 0;
  color: #f2f2f2;
  font-family: Calibri, Candara, Segoe, Segoe UI, Optima, Arial, sans-serif;
  font-size: 2em;
  left: 0;
  padding: 2em;
  position: absolute;
  right: 0;
  transform: translate(0, 100%);
  transition: transform 0.2s 0.4s linear;
  z-index: 1;
}

.compsoul-disorderly .compsoul-gallery-item .compsoul-gallery-comment {
  transform: translate(0, 0);
  transition: unset;
}

.compsoul-gallery-item.compsoul-active.compsoul-loaded .compsoul-gallery-comment {
  transform: translate(0, 0);
}

.compsoul-gallery-item .compsoul-gallery-comment.compsoul-inactive {
  display: none;
}

.compsoul-loader {
  left: 50%;
  opacity: 0;
  position: absolute;
  top: 50%;
  transform: translate(-50%, -50%);
  z-index: 0;
}

.compsoul-loader:before, .compsoul-loader:after {
  animation: compsoul-loading 1s linear infinite;
  animation-play-state: paused;
  border: 0.5em solid #f2f2f2;
  border-radius: 100%;
  content: "";
  display: block;
  filter: blur(1px);
  height: 8em;
  left: 50%;
  opacity: 0;
  position: absolute;
  top: 50%;
  transform: translate(-50%, -50%);
  width: 8em;
}

.compsoul-gallery-item.compsoul-active .compsoul-loader,
.compsoul-gallery-item.compsoul-prev .compsoul-loader,
.compsoul-gallery-item.compsoul-next .compsoul-loader {
  transition: opacity 0.2s linear;
}

.compsoul-gallery-item.compsoul-active .compsoul-loader {
  opacity: 1;
}

.compsoul-gallery-item.compsoul-loaded .compsoul-loader {
  opacity: 0;
}

.compsoul-gallery-item.compsoul-active.compsoul-loading .compsoul-loader:before,
.compsoul-gallery-item.compsoul-active.compsoul-loading .compsoul-loader:after {
  animation-play-state: running;
}

.compsoul-loader:after {
  animation-delay: 0.5s;
}

@keyframes compsoul-loading {
  0% {
    opacity: 0;
    transform: translate(-50%, -50%) scale(0);
  }
  50% {
    opacity: 1;
    transform: translate(-50%, -50%) scale(0.5);
  }
  100% {
    opacity: 0;
    transform: translate(-50%, -50%) scale(1);
  }
}

.compsoul-gallery-full-screen {
  background: #000;
  bottom: 0;
  font-size: 0;
  position: absolute;
  left: 0;
  opacity: 0;
  overflow: auto;
  right: 0;
  top: 0;
  transition: opacity 0.2s linear;
  z-index: -1;
}

.compsoul-gallery-full-screen.compsoul-active {
  z-index: 1;
}

.compsoul-zoom .compsoul-gallery-full-screen {
  opacity: 1;
}

.compsoul-zoom-out .compsoul-gallery-full-screen {
  opacity: 0;
  transition-delay: 0.2s;
}

.compsoul-gallery-full-screen img {
  display: block;
  margin: 0 auto;
  opacity: 0;
  transition: opacity 0.2s 0.2s linear;
}

.compsoul-zoom .compsoul-gallery-full-screen img {
  opacity: 1;
}

.compsoul-zoom-out .compsoul-gallery-full-screen img {
  opacity: 0;
  transition-delay: unset;
}

.compsoul-logo, .compsoul-gallery-close, .compsoul-gallery-next, .compsoul-gallery-prev, .thumbnails-toggle, .compsoul-gallery-progress, .compsoul-gallery-zoom {
  cursor: pointer;
  height: 7em;
  outline: 1px solid rgba(242, 242, 242, 0);
  overflow: hidden;
  position: absolute;
  right: 4em;
  top: 2em;
  transform: translate(0);
  transition: outline 0.2s linear;
  width: 7em;
}

.compsoul-logo {
  box-sizing: border-box;
  left: 4em;
  right: auto;
  transition: unset;
  width: 8em;
}

.compsoul-logo svg {
  fill: #f2f2f2;
  top: 50%;
  position: relative;
  transform: translate(0, -50%);
  transition: fill 0.2s linear;
}

.compsoul-logo:focus-within {
  outline: none;
}

.compsoul-logo:hover svg, .compsoul-logo:focus-within svg {
  fill: #e7a14f;
}

.compsoul-logo:focus-within, .compsoul-gallery-close:focus-within, .compsoul-gallery-next:focus-within, .compsoul-gallery-prev:focus-within, .thumbnails-toggle:focus-within, .compsoul-gallery-progress:focus-within, .compsoul-gallery-zoom:focus-within {
  outline-color: rgba(242, 242, 242, 0.8);
}

.compsoul-gallery-close:before, .compsoul-gallery-next:before, .compsoul-gallery-prev:before, .thumbnails-toggle:before, .compsoul-gallery-progress:before, .compsoul-gallery-zoom:before, .compsoul-gallery-close:after, .compsoul-gallery-next:after, .compsoul-gallery-prev:after, .thumbnails-toggle:after, .compsoul-gallery-progress:after, .compsoul-gallery-zoom:after {
  background: #111;
  bottom: 0;
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  z-index: -2;
}

.compsoul-gallery-close:after, .compsoul-gallery-next:after, .compsoul-gallery-prev:after, .thumbnails-toggle:after, .compsoul-gallery-progress:after, .compsoul-gallery-zoom:after {
  background: none;
  z-index: 1;
}

.compsoul-gallery-close button, .compsoul-gallery-next button, .compsoul-gallery-prev button, .thumbnails-toggle button, .compsoul-gallery-progress button, .compsoul-gallery-zoom button {
  outline: 0;
  position: relative;
  z-index: -1;
}

.compsoul-gallery-close button:before, .compsoul-gallery-close button:after, .compsoul-gallery-next button:before, .compsoul-gallery-prev button:before {
  border-top: 0.25em solid #f2f2f2;
  border-right: 0.25em solid #f2f2f2;
  box-sizing: content-box;
  content: "";
  cursor: pointer;
  display: inline-block;
  height: 1em;
  padding: 0 0 0.25em 0.25em;
  width: 1em;
}

.compsoul-gallery-close {
  z-index: 2;
}

.compsoul-gallery-close button {
  cursor: pointer;
  height: 6em;
  left: 50%;
  position: absolute;
  top: 50%;
  transform: translate(-50%, -50%) rotate(45deg);
  width: 6em;
}

.compsoul-gallery-close button:before, .compsoul-gallery-close button:after {
  bottom: 1.625em;
  left: 1.625em;
  position: absolute;
  transform: rotate(0deg);
}

.compsoul-gallery-close button:before {
  border: none;
  border-bottom: 0.25em solid #f2f2f2;
  border-left: 0.25em solid #f2f2f2;
  left: auto;
  padding: 0.25em 0.25em 0 0;
  right: 1.625em;
  top: 1.625em;
}

.compsoul-gallery-close button:after {
  border-top: 0.25em solid #f2f2f2;
  border-right: 0.25em solid #f2f2f2;
  padding: 0 0 0.25em 0.25em;
}

.compsoul-gallery-zoom {
  right: 28em;
}

.compsoul-gallery-zoom button {
  cursor: pointer;
  height: 100%;
  position: relative;
  width: 100%;
}

.compsoul-gallery-zoom button:before {
  border: 0.25em solid #f2f2f2;
  border-radius: 100%;
  content: "";
  height: 1.25em;
  left: 50%;
  position: absolute;
  top: 50%;
  transform: translate(-50%, -50%);
  width: 1.25em;
}

.compsoul-gallery-zoom button:after {
  background: #f2f2f2;
  border-radius: 0 0 0.25em 0.25em;
  content: "";
  height: 1em;
  left: 50%;
  margin: 1em 0 0 -1.5em;
  position: absolute;
  top: 50%;
  transform: rotate(45deg) translate(-50%, -50%);
  width: 0.25em;
}

.compsoul-gallery-progress {
  right: 20em;
}

.compsoul-gallery-progress button {
  cursor: pointer;
  height: 100%;
  position: relative;
  width: 100%;
}

.compsoul-gallery-progress button:before {
  border-bottom: 1em solid transparent;
  border-left: 1.2em solid #f2f2f2;
  border-top: 1em solid transparent;
  border-radius: 0.2em;
  content: "";
  height: 0;
  left: 50%;
  opacity: 1;
  position: absolute;
  top: 50%;
  transform: translate(-50%, -50%);
  transition: opacity 0.2s 0.2s linear;
  width: 0;
}

.compsoul-gallery-progress.compsoul-active button:before {
  opacity: 0;
  transition-delay: unset;
}

.compsoul-gallery-progress button:after {
  animation: gallery-progress 6s linear forwards;
  animation-play-state: paused;
  color: #f2f2f2;
  content: "10";
  font-size: 1.6em;
  left: 50%;
  opacity: 0;
  position: absolute;
  top: 50%;
  transition: opacity 0.2s linear;
  transform: translate(-50%, -50%);
}

.compsoul-gallery-progress.compsoul-active button:after {
  opacity: 1;
  transition-delay: 0.2s;
}

.compsoul-gallery-progress.compsoul-play button:after {
  animation-delay: 0.4s;
  animation-play-state: running;
}

.compsoul-gallery-progress.compsoul-unset button:after {
  animation: unset;
}

@keyframes gallery-progress {
  0% {
    content: "10";
  }
  9% {
    content: "9";
  }
  18% {
    content: "8";
  }
  27% {
    content: "7";
  }
  36% {
    content: "6";
  }
  45% {
    content: "5";
  }
  54% {
    content: "4";
  }
  63% {
    content: "3";
  }
  72% {
    content: "2";
  }
  81% {
    content: "1";
  }
  90% {
    content: "0";
  }
  100% {
    content: "0";
  }
}

.compsoul-gallery-next, .compsoul-gallery-prev {
  opacity: 0;
  right: 4em;
  top: 50%;
  transform: translate(0, -50%);
  transition: opacity 0.2s linear, outline 0.2s linear;
}

.compsoul-gallery-next.compsoul-active, .compsoul-gallery-prev.compsoul-active {
  opacity: 1;
}

.compsoul-gallery-prev {
  left: 4em;
}

.compsoul-gallery-next button, .compsoul-gallery-prev button {
  left: 50%;
  position: absolute;
  top: 50%;
  transform: translate(-1em, -50%);
}

.compsoul-gallery-prev button {
  transform: translate(-0.5em, -50%);
}

.compsoul-gallery-next button:before, .compsoul-gallery-prev button:before {
  transform: rotate(-135deg);
}

.compsoul-gallery-next button:before {
  transform: rotate(45deg);
}

.thumbnails-toggle {
  right: 12em;
}

.thumbnails-toggle button {
  cursor: pointer;
  height: 100%;
  position: relative;
  width: 100%;
}

.thumbnails-toggle button:before {
  background-color: transparent;
  background-image: linear-gradient(90deg, #f2f2f2 0.5em, transparent 0.25em),
                    linear-gradient(90deg, #f2f2f2 0.5em, transparent 0.25em),
                    linear-gradient(90deg, #f2f2f2 0.5em, transparent 0.25em);
  background-position: 0 0, 0 0.75em, 0 1.5em;
  background-repeat: repeat-x;
  background-size: 0.75em 0.5em, 0.75em 0.5em, 0.75em 0.5em;
  content: "";
  cursor: pointer;
  height: 2em;
  left: 50%;
  opacity: 0.6;
  position: absolute;
  top: 50%;
  transition: opacity 0.4s linear;
  transform: translate(-50%, -50%);
  width: 2em;
}

.thumbnails-toggle:active button:before, .thumbnails-toggle button:active:before {
  background-image: linear-gradient(90deg, #f2f2f2 0.5em, transparent 0.125em),
                    linear-gradient(90deg, #f2f2f2 0.5em, transparent 0.125em),
                    linear-gradient(90deg, #f2f2f2 0.5em, transparent 0.125em);
  background-position: 0 0, 0 0.625em, 0 1.25em;
  background-size: 0.625em 0.5em, 0.625em 0.5em, 0.625em 0.5em;
  height: 1.75em;
  width: 1.75em;
}

.thumbnails-show .thumbnails-toggle button:before {
  opacity: 1;
}

.thumbnails-container {
  background: #111;
  bottom: 0;
  font-size: 0;
  height: 72px;
  left: 0;
  letter-spacing: 0;
  position: fixed;
  right: 0;
  transition: transform 0.2s linear;
  transform: translateY(100%);
}

.thumbnails-show .thumbnails-container {
  transform: translateY(0);
}

.thumbnails-content {
  bottom: 0;
  left: 0;
  position: absolute;
  top: 0;
  white-space: nowrap;
}

.thumbnails-show .thumbnails-content  {
  transition: transform 0.2s linear;
}

.thumbnails-content.compsoul-drag {
  transition: unset;
}

.thumbnails-content.compsoul-drag:before {
  bottom: 0;
  content: "";
  left: 0;
  position: absolute;
  right: 0;
  top: 0;
  z-index: 2;
}

.thumbnails-content .thumbnails-image {
  background: none;
  border: none;
  cursor: pointer;
  display: inline-block;
  font-size: 0;
  height: 100%;
  position: relative;
  user-select: none;
}

.thumbnails-content .thumbnails-image:before, .thumbnails-content .thumbnails-image:after {
  bottom: 0;
  content: "";
  left: 0;
  opacity: 0;
  outline: 1px solid #f2f2f2;
  outline-offset: -1px;
  position: absolute;
  right: 0;
  top: 0;
  transition: opacity 0.2s linear;
  z-index: 1;
}

.thumbnails-content .thumbnails-image:after {
  outline-color: #e7a14f;
}

.thumbnails-content .thumbnails-image button:focus {
  outline: none;
}

.thumbnails-content .thumbnails-image:focus-within:before {
  opacity: 1;
}

.thumbnails-content .thumbnails-image.compsoul-active:after {
  opacity: 1;
}

.thumbnails-content .thumbnails-image img {
  display: block;
  max-height: 72px;
}

.gallery {
  display: flex;
  flex-flow: row wrap;
  gap: 10px;
}

.gallery-row {
  display: flex;
  flex: 1 100%;
  flex-flow: row nowrap;
  gap: 10px;
}

.gallery-thumbnail * {
  pointer-events: none;
}

.gallery-thumbnail img {
  height: 100%;
  object-fit: cover;
  width: 100%;
}

@media (max-width: 1000px) {
  .compsoul-gallery-container {
    font-size: 5.4px;
  }

  .compsoul-gallery-content .compsoul-gallery-item {
    height: 100vh;
    height: calc(100vh - 16px);
    width: 100vw;
    width: calc(100vw - 16px);
  }

  .thumbnails-show .compsoul-gallery-image {
    transform: scale(0.68) translate(-50%, -50%);
  }

  .compsoul-gallery-item .compsoul-gallery-image img {
    max-height: 100vh;
    max-height: calc(100vh - 16px);
    max-width: 100vw;
    max-width: calc(100vw - 16px);
  }
}

@media (max-width: 380px) {
  .compsoul-gallery-content .compsoul-gallery-item {
    height: 100vh;
    width: 100vw;
  }

  .thumbnails-show .compsoul-gallery-image {
    transform: scale(0.75) translate(-50%, -50%);
  }

  .compsoul-gallery-item .compsoul-gallery-image img {
    max-height: 100vh;
    max-width: 100vw;
  }
}
<script src="https://compsoul.dev/uploads/js/compsoul.js"></script><script src="https://compsoul.dev/uploads/js/gallery.js"></script><script>
  new Gallery(".gallery-demo").init();
</script>

Thank You for Reading

We hope you enjoyed this post! If you did, please consider following us on Facebook and leaving a like and a comment. If you have any questions or need assistance, feel free to use our contact form or email us at daniel@compsoul.dev. For urgent inquiries, you can reach us by phone at +48 732 846 416.

Comments

Magal

Adding a new response to check the other user gets an email

Magal

Second test

Magal

test content

Daniel

Is it working?