Ein Produkt-Slider mit dem Shopify-Theme Dawn

Technisches

An English version of this post is available on Page 2.

Seit einem knappen Jahr ist Dawn das Default-Theme von Shopify; es bringt eine Reihe von Verbesserungen und erweiterten Optionen mit sich, hat aber auch einen Nachteil, über den in den Foren gerne geklagt wird: In der Standard-Produkt-Ansicht werden die Bilder einfach so allesamt gezeigt, mit merkwürdigen Lücken und je nach Seiten-Verhältnissen bizarren Abständen.

Immer mal wieder kommt folglich der Wunsch in den Foren nach einem „klassischen“ Slider auf, der nur ein Bild groß zeigt und den Rest als Thumbnails. Leider funktionieren die Anleitungen oft nach ein paar (vom User nicht steuerbaren) Updates des Themes durch Shopify nicht mehr. Die meisten verbliebenen Anleitungen setzen auf eine komplette externe JavaScript-Bibliothek oder eigene Apps. Das scheint mir übertrieben, weswegen ich eine einfache Lösung erstellt habe, die wir drüben beim Keramik-Studio Kleistone seit einiger Zeit nutzen.

Unser Ziel ist ein Slider mit kleinen Thumbnails unter den Bildern ohne wilde Sprünge beim Durchklicken.

Vorbereitungen

Um die Änderungen vorzunehmen, müssen wir in den Code-Editor von Shopify wechseln. Dafür links auf „Online Store“ klicken, in der Übersichtsseite danach auf „Actions“ und dann „Edit Code“. Es öffnet sich ein Editor-Fenster mit einer Verzeichnisstruktur links und der Dateiansicht rechts. Jetzt in dem Formularfeld oben links „main-product“ suchen. In der Listenansicht sollte jetzt die „main-product.liquid“ erscheinen. Einmal linksklicken, dann wird der Inhalt dieser Datei groß im Code-Editor rechts angezeigt.

Beispiel für eine Ansicht des Code-Editors in Shopify.

Wichtig! Jetzt einmal in den Datei-Editor klicken, alles markieren (Strg + A auf Windows, Command + A auf MacOS) und den Inhalt in eine Textdatei etwa in Notepad kopieren und abspeichern. Das ist das Rettungsboot, falls etwas schief geht! Sollte das erforderlich sein, den umgekehrten Weg gehen: in Notepad alles markieren, kopieren, im Editor alle Inhalte der Datei markieren, löschen, Inhalte einfügen.

Ich empfehle, die nachfolgenden Änderungen während einer ruhigen Phase zu machen – nicht kurz nach einer Newsletter-Versand oder einer Social-Media-Kampagne. Zwischenzeitlich wird es nämlich exakt keine Fotos auf der Seite geben.

Die Änderungen

Die folgende Stelle in der Datei finden:

<slider-component class="slider-mobile-gutter">

und ändern in

<slider-component class="slider-mobile-gutter"  style="display: none;">

Dadurch wird der entsprechende Abschnitt nicht mehr dargestellt. Direkt darüber fügen wir jetzt folgendes ein:

 <style>
        .product-gallery {
          display: flex;
          flex-wrap: wrap;
          position: relative;
        }

        .product-gallery > img {
          display: none;
          height: 400px;
          width: 100%;
          max-width: 760px;
          object-fit: contain;
        }

        .product-gallery img:first-of-type {
          display: block;
        }

        .product-gallery button {
          height: 24px;
          width: 24px;
          position: absolute;
          z-index: 5;
 	  top: calc(50% - 38px);
          cursor: pointer;
          color: #fff;
          -webkit-appearance: none;
          -moz-appearance: none;
          appearance: none;
          box-shadow: none;
          border-radius: 0;
          border: 0;
          background: none;
          padding: 0;
        }
        
        .product-gallery svg {
          fill: rgb(96, 95, 90);
        }

        .product-gallery .prev {
          left: 5px;
          transform: rotate(180deg)
        }

        .product-gallery .next {
          right: 5px;
        }

        .product-gallery.initialized > img {
          display: none;
        }

        .product-gallery.initialized > img.active {
          display: block;
        }

        .product-gallery .thumbs {
          padding-top: 8px;
          width: 100%;
        }

        .product-gallery .thumbs img {
          cursor: pointer;
          margin-right: 8px;
          display: inline-block;
          max-height: 50px;
        }
      </style>
      <div class="product-gallery grid">
         {%- for media in product.media -%}
              <img src="{{ media | img_url: '720x' }}" />
          {%- endfor -%}
      </div>
      <script>
        const productGalleryContainer = document.querySelector(".product-gallery");
        const images =  productGalleryContainer.querySelectorAll("img");
        const imageArray = Array.from(images);
        const imageSources = imageArray.map(img => {
         return img.getAttribute("src");
        });

        const thumbContainer = document.createElement("div");
        thumbContainer.setAttribute("class", "thumbs");
        productGalleryContainer.append(thumbContainer);

        const svgArrow = '<svg aria-hidden="true" focusable="false" role="presentation" class="icon icon-submit" viewBox="0 0 1024 1024"><path d="M1023.998 511.724v-6.44a4.818 4.818 0 00-1.605-3.215l-.005-.005c0-1.61-1.61-1.61-1.61-3.22s-1.61-1.61-1.61-3.22c-.89 0-1.61-.72-1.61-1.61L652.074 115.649c-6.058-5.789-14.286-9.354-23.346-9.354s-17.288 3.564-23.358 9.366l.013-.013c-6.101 5.61-9.909 13.631-9.909 22.541s3.81 16.931 9.888 22.52l.022.02 307.522 318.793H32.201C14.416 479.522 0 493.939 0 511.723s14.417 32.201 32.201 32.201h887.145L605.384 862.717a32.062 32.062 0 00-8.429 21.72c0 9.19 3.851 17.481 10.025 23.347l.014.013c5.61 6.101 13.631 9.909 22.541 9.909s16.931-3.81 22.52-9.888l.02-.022 363.874-370.315c0-1.61 0-1.61 1.61-3.22.89 0 1.61-.72 1.61-1.61 0-1.61 1.61-1.61 1.61-3.22h1.61v-3.22a4.81 4.81 0 001.608-3.203l.002-.017v-11.27z"></path></svg>'

        const prevButton = document.createElement("button");
        prevButton.innerHTML = svgArrow;
        prevButton.classList.add("prev");
        prevButton.addEventListener("click", (e) => {
          e.preventDefault();
          const activeImage = productGalleryContainer.querySelector("img.active");
          let currentIndex = [...activeImage.parentNode.children].indexOf(activeImage);

          if (currentIndex === 0) {
            currentIndex = images.length;
          }
          images.forEach((image, index) => {
             image.classList.toggle("active", index === currentIndex - 1);
          })
        })
        productGalleryContainer.append(prevButton);


        const nextButton = document.createElement("button");
        nextButton.innerHTML = svgArrow;
        nextButton.classList.add("next");
        nextButton.addEventListener("click", (e) => {
          e.preventDefault();
          const activeImage = productGalleryContainer.querySelector("img.active");
          let currentIndex = [...activeImage.parentNode.children].indexOf(activeImage);

          if (currentIndex + 1 === images.length) {
            currentIndex = -1
          }
          images.forEach((image, index) => {
             image.classList.toggle("active", index === currentIndex + 1);
          })
        })
        productGalleryContainer.append(nextButton);


        imageSources.forEach((imageSource, index) => {
          const thumb = document.createElement("img");
          thumb.setAttribute("src", imageSource);
          thumb.addEventListener("click", (e) => {
            e.preventDefault();
            images.forEach(image => {
              image.classList.toggle("active", image.getAttribute("src") === imageSource);
            })
            const correspondingImage = document.querySelector(`.product-gallery > img[src='${imageSource}']`);
            correspondingImage.classList.add("active");
          })
          thumbContainer.append(thumb);
        })
        images[0].classList.add("active");
        productGalleryContainer.classList.add("initialized");
      </script>

Ja, das ist relativ viel Code auf einmal, aber es sorgt dafür, dass wir nicht in mehreren Dateien pfriemeln müssen. Der tatsächliche Mehraufwand für den Browser für die wiederholt geladenen Styles und Scripte ist minimal.

Jetzt „Save“ drücken – Das war’s! Folgende Modifikationen sind möglich für Menschen, die sich etwas CSS zutrauen:

.product-gallery > img {
   ... /* alles andere so lassen */
   object-fit: contain; /* statt 'contain' mal 'cover' ausprobieren*/
}

 .product-gallery button {
         ... /* alles andere so lassen */
         color: #fff; /* hier kann eine beliebige Farbe (Hexcode) stehen*/
         ...
}

Dieser Guide wurde für Dawn Version 2.1.0 erstellt. Ich hoffe, der hilft anderen beim Versuch, einen Produkt-Slider in ihre Shopify-Theme zu bekommen!

Next

Comments are closed.