Happening now | Office Hours: Customizing Your Theme With Moeed | Ask your questions now!

I need some help with the code a previous designer implemented. PLEASE

I need some help with the code a previous designer implemented. PLEASE

LaRoja123
Visitor
1 0 1

The issue: My product page doesn't assign the correct images to the color swatches/variants. 
This is the code:

{% assign product_has_only_default_variant = product.has_only_default_variant %}
{% assign variant_images = product.images | where: 'attached_to_variant?', true | map: 'src' %}
{% assign first_3d_model = product.media | where: 'media_type', 'model' | first %}

<div class="product-detail-section" data-product-id="{{ product.id }}" data-section-id="{{ section.id }}">
  <div class="product-detail-wrapper">
    <div class="product-media-column">
      <div class="product-media-gallery">
        {% if product.media.size > 0 %}
          <div class="product-images product-main-images">
            {% for media in product.media %}
              {% case media.media_type %}
                {% when 'image' %}
                  {% assign associated_variant = false %}
{% for variant in product.variants %}
  {% if variant.featured_image and variant.featured_image.id == media.id %}
    {% assign associated_variant = variant %}
    {% break %}
  {% endif %}
{% endfor %}



                  <img
                    src="{{ media | img_url: '800x800', crop: 'center' }}"
                    alt="{{ media.alt | escape }}"
                    class="product-image {% if forloop.first %}active{% endif %}"
                    data-index="{{ forloop.index0 }}"
                    data-media-id="{{ media.id }}"
                    {% if associated_variant %}data-variant-id="{{ associated_variant.id }}"{% endif %}
                    loading="{% if forloop.first %}eager{% else %}lazy{% endif %}">
                {% when 'model' %}
                  <div class="product-model {% if forloop.first %}active{% endif %}" data-index="{{ forloop.index0 }}" data-media-id="{{ media.id }}">
                    {{ media | model_viewer_tag }}
                  </div>
                {% when 'video' %}
                  <div class="product-video {% if forloop.first %}active{% endif %}" data-index="{{ forloop.index0 }}" data-media-id="{{ media.id }}">
                    {{ media | video_tag: controls: true, autoplay: false }}
                  </div>
              {% endcase %}
            {% endfor %}
          </div>

          {% if product.media.size > 1 %}
            <div class="product-thumbnails">
              {% for media in product.media %}
                {% assign associated_variant = false %}
                {% for variant in product.variants %}
  {% if media.variant_ids contains variant.id %}
    {% assign associated_variant = variant %}
    {% break %}
  {% endif %}
{% endfor %}


                <button
                  class="thumbnail-button {% if forloop.first %}active{% endif %}"
                  data-index="{{ forloop.index0 }}"
                  data-media-id="{{ media.id }}"
                  {% if associated_variant %}data-variant-id="{{ associated_variant.id }}"{% endif %}
                  aria-label="Go to image {{ forloop.index }}"
                >
                  <img
                    src="{{ media | img_url: '100x100', crop: 'center' }}"
                    alt="{{ media.alt | escape }}"
                    loading="lazy"
                  >
                </button>
              {% endfor %}
            </div>
          {% endif %}
        {% else %}
          <div class="product-no-image">
            <div class="no-image-placeholder">NO IMAGE</div>
          </div>
        {% endif %}
      </div>
    </div>

    <div class="product-info-column">
      <div class="product-info-wrapper">
        {% if product.tags contains 'Best Seller' %}
          <div class="product-badge">Best Seller</div>
        {% endif %}

        <h1 class="product-title">{{ product.title }}</h1>

        <div class="product-price">
          {%- render 'price',
            product: product,
            use_variant: true,
            show_badges: true
          -%}
        </div>

        {% if product.metafields.reviews.rating %}
          <div class="product-reviews">
            <div class="star-rating">
              {% assign rating = product.metafields.reviews.rating.value | round %}
              {% for i in (1..5) %}
                {% if i <= rating %}
                  <span class="star filled">★</span>
                {% else %}
                  <span class="star">★</span>
                {% endif %}
              {% endfor %}
            </div>
            <a href="#reviews" class="review-count">{{ product.metafields.reviews.count }}</a>
          </div>
        {% endif %}

        {% unless product_has_only_default_variant %}
          <div class="product-variants">
            {% for option in product.options_with_values %}
              {% if option.name == 'Color' or option.name == 'Colour' %}
                <div class="variant-option">
                  <h3 class="option-name">
                    {{ option.name }}: <span class="selected-color-name"></span>
                  </h3>
                  <div class="color-options">
                    {% assign unique_values = option.values | uniq %}
                    {% for value in unique_values %}
                      {% assign color_code = value | handleize %}
                      {% assign has_image = false %}
                      {% assign variant_id = "" %}
                      {% assign media_id = "" %}

                      {% for variant in product.variants %}
                        {% if variant.options[forloop.parentloop.index0] == value %}
                          {% assign variant_id = variant.id %}
                          {% for media in product.media %}
  {% if media.variant_ids contains variant.id %}
    {% assign has_image = true %}
    {% assign media_id = media.id %}
    {% break %}
  {% endif %}
{% endfor %}

                          {% break %}
                        {% endif %}
                      {% endfor %}

                      <button
                        class="color-option {% if forloop.first %}active{% endif %}"
                        data-color="{{ color_code }}"
                        data-option-position="{{ option.position }}"
                        data-value="{{ value | escape }}"
                        data-variant-id="{{ variant_id }}"
                        {% if has_image %}data-media-id="{{ media_id }}"{% endif %}
                        style="background-color: {{ value | downcase | replace: ' ', '' | split: '/' | last | default: color_code }};"
                        title="{{ value }}"
                        {% if forloop.first %}aria-pressed="true"{% else %}aria-pressed="false"{% endif %}>
                      </button>
                    {% endfor %}
                  </div>
                </div>
              {% else %}
                <div class="variant-option">
                  <h3 class="option-name">{{ option.name }}</h3>
                  <div class="size-options">
                    {% for value in option.values %}
                      <button
                        class="size-option {% if forloop.first %}active{% endif %}"
                        data-option-position="{{ option.position }}"
                        data-value="{{ value | escape }}"
                        {% if forloop.first %}aria-pressed="true"{% else %}aria-pressed="false"{% endif %}
                      >
                        {{ value }}
                      </button>
                    {% endfor %}
                  </div>
                </div>
              {% endif %}
            {% endfor %}
          </div>
        {% endunless %}

        <div class="product-actions">
          <button
            type="button"
            class="add-to-cart-button"
            data-product-id="{{ product.id }}"
            data-variant-id="{{ product.selected_or_first_available_variant.id }}"
            {% if product.available == false %}disabled{% endif %}
          >
            {% if product.available %}
              ADD TO BAG
            {% else %}
              SOLD OUT
            {% endif %}
          </button>
        </div>

        <div class="product-accordions">
          <details class="product-accordion">
            <summary>
              <h3>DESCRIPTION</h3>
              <span class="accordion-icon">+</span>
            </summary>
            <div class="accordion-content">
              {{ product.description }}
            </div>
          </details>

          <details class="product-accordion">
            <summary>
              <h3>FREE SHIPPING & RETURNS</h3>
              <span class="accordion-icon">+</span>
            </summary>
            <div class="accordion-content">
              <p>Free standard shipping on all orders.</p>
              <p>Free returns within 30 days. See our <a href="/pages/returns">return policy</a> for more information.</p>
            </div>
          </details>
        </div>
      </div>
    </div>
  </div>
</div>

<script>
document.addEventListener('DOMContentLoaded', function() {
  const productSection = document.querySelector('.product-detail-section');
  if (!productSection) return;

  const productId = productSection.dataset.productId;

  const mainImages = Array.from(productSection.querySelectorAll('.product-main-images .product-image, .product-main-images .product-video, .product-main-images .product-model'));
  const thumbnailButtons = Array.from(productSection.querySelectorAll('.thumbnail-button'));
  const colorOptions = Array.from(productSection.querySelectorAll('.color-option'));
  const sizeOptions = Array.from(productSection.querySelectorAll('.size-option'));
  const addToCartButton = productSection.querySelector('.add-to-cart-button');
  const selectedColorNameSpan = productSection.querySelector('.selected-color-name'); // Added selector

  const colorInfo = colorOptions.map((option, index) => {
    return {
      element: option,
      value: option.getAttribute('data-value') || option.getAttribute('title') || `Color ${index + 1}`,
      variantId: option.getAttribute('data-variant-id') || null,
      mediaId: option.getAttribute('data-media-id') || null,
      index: index
    };
  });

  let allVariantData = [];
  let currentIndex = 0;

  const getProductHandle = () => {
    const path = window.location.pathname;
    const pathParts = path.split('/');
    let handle = '';
    for (let i = 0; i < pathParts.length; i++) {
      if (pathParts[i] === 'products' && i + 1 < pathParts.length) {
        handle = pathParts[i + 1].split('?')[0];
        break;
      }
    }
    return handle;
  };

  const fetchProductData = async () => {
    const handle = getProductHandle();
    if (!handle) return null;
    try {
      const response = await fetch(`/products/${handle}.js`);
      if (!response.ok) throw new Error(`HTTP Error: ${response.status}`);
      return await response.json();
    } catch (error) {
      console.error('Error getting product data:', error);
      return null;
    }
  };

  const buildVariantDataList = (productData) => {
    if (!productData || !productData.variants || productData.variants.length === 0) return [];

    let colorOptionPosition = -1;
    if (productData.options && Array.isArray(productData.options)) {
      colorOptionPosition = productData.options.findIndex(opt =>
        opt.name.toLowerCase() === 'color' || opt.name.toLowerCase() === 'colour'
      );
    }

    const useDirectMapping = productData.variants.length === colorOptions.length;
    const variantMediaMap = {};

    if (productData.media && Array.isArray(productData.media)) {
      productData.media.forEach(media => {
        if (media.id && media.variant_ids && Array.isArray(media.variant_ids)) {
          media.variant_ids.forEach(variantId => {
            variantMediaMap[variantId] = String(media.id);
          });
        }
      });
    }

    const variants = [];

    productData.variants.forEach((variant, variantIndex) => {
      let colorValue = '';
      if (colorOptionPosition !== -1) {
        const optionKey = `option${colorOptionPosition + 1}`;
        colorValue = variant[optionKey] || '';
      } else {
        const colorData = useDirectMapping && variantIndex < colorInfo.length ? colorInfo[variantIndex] : null;
        colorValue = colorData ? colorData.value : '';
      }

      let variantImage = variant.featured_image || null;
      let mediaId = variantImage ? String(variantImage.id) : variantMediaMap[variant.id] || null;

      if (!mediaId && useDirectMapping && variantIndex < colorInfo.length && colorInfo[variantIndex].mediaId) {
         mediaId = colorInfo[variantIndex].mediaId;
      }

      let imageElement = null;
      if (mediaId) {
        imageElement = mainImages.find(img => img.getAttribute('data-media-id') === mediaId);
      }
      if (!imageElement && useDirectMapping && variantIndex < mainImages.length) {
        imageElement = mainImages[variantIndex];
      }

      let colorElement = null;
      for (const color of colorOptions) {
        if (color.getAttribute('data-variant-id') === String(variant.id)) {
          colorElement = color;
          break;
        }
      }
      if (!colorElement && useDirectMapping && variantIndex < colorOptions.length) {
        colorElement = colorOptions[variantIndex];
      }

      variants.push({
        id: String(variant.id),
        colorValue: colorValue,
        colorElement: colorElement,
        mediaId: mediaId,
        imageElement: imageElement,
        imageIndex: imageElement ? mainImages.indexOf(imageElement) : -1,
        price: variant.price,
        available: variant.available,
        variantIndex: variantIndex
      });

      if (colorElement) {
        colorElement.setAttribute('data-variant-id', String(variant.id));
        if (mediaId) {
          colorElement.setAttribute('data-media-id', mediaId);
        }
         // Ensure title attribute reflects the actual color value from variant
         if (colorValue) {
             colorElement.setAttribute('title', colorValue);
             if (!colorElement.hasAttribute('data-value')) {
                 colorElement.setAttribute('data-value', colorValue);
             }
         }
      }
    });
    return variants;
  };

  function updateDisplay(variantIndex) {
    if (variantIndex < 0 || variantIndex >= allVariantData.length) return;

    currentIndex = variantIndex;
    const variant = allVariantData[currentIndex];

    colorOptions.forEach(btn => {
      btn.classList.remove('active');
      btn.setAttribute('aria-pressed', 'false');
    });

    if (variant.colorElement) {
      variant.colorElement.classList.add('active');
      variant.colorElement.setAttribute('aria-pressed', 'true');
    }

    mainImages.forEach(img => img.classList.remove('active'));
    let imageIndex = -1;

    if (variant.imageElement) {
      variant.imageElement.classList.add('active');
      imageIndex = mainImages.indexOf(variant.imageElement);
    } else if (variant.mediaId) {
      for (let i = 0; i < mainImages.length; i++) {
        if (mainImages[i].getAttribute('data-media-id') === variant.mediaId) {
          mainImages[i].classList.add('active');
          imageIndex = i;
          break;
        }
      }
    }
    if (imageIndex === -1 && variant.variantIndex < mainImages.length) {
        imageIndex = variant.variantIndex; // Fallback to index if lengths match
    }
    if (imageIndex === -1 && mainImages.length > 0) {
        imageIndex = 0; // Fallback to first image
    }
     if (imageIndex !== -1 && imageIndex < mainImages.length) {
         mainImages[imageIndex].classList.add('active');
     }


    thumbnailButtons.forEach(btn => btn.classList.remove('active'));
    if (imageIndex >= 0 && imageIndex < thumbnailButtons.length) {
      thumbnailButtons[imageIndex].classList.add('active');
    }

    // Update selected color name display
    if (selectedColorNameSpan) {
      selectedColorNameSpan.textContent = variant.colorValue || '';
    }

    if (addToCartButton) {
      addToCartButton.setAttribute('data-variant-id', variant.id);
      addToCartButton.disabled = !variant.available;
      addToCartButton.textContent = variant.available ? 'ADD TO BAG' : 'SOLD OUT';
    }

    // Trigger price update (assumes a 'price' snippet handles this via events or direct update)
    const priceElement = productSection.querySelector('.product-price');
    if (priceElement) {
        const event = new CustomEvent('variant:changed', {
            bubbles: true,
            detail: { variant: variant }
        });
        priceElement.dispatchEvent(event);
        // If the price snippet doesn't listen for events, you might need direct manipulation here
        // e.g., update price based on variant.price
    }
  }

  function updateCartState() {
    fetch('/cart.js')
      .then(response => response.json())
      .then(cart => {
        const event = new CustomEvent('cart:updated', {
          bubbles: true,
          detail: cart
        });
        document.dispatchEvent(event);

        const cartTotalElements = document.querySelectorAll('#cart-total');
        cartTotalElements.forEach(element => {
          element.textContent = `$ ${(cart.total_price / 100).toFixed(2)}`;
        });

        const cartCountElements = document.querySelectorAll('.cart-count, .cart-quantity, .cart-item-count, .js-cart-count');
        cartCountElements.forEach(element => {
          element.textContent = cart.item_count;
          if (cart.item_count > 0 && element.classList.contains('hidden')) {
            element.classList.remove('hidden');
          } else if (cart.item_count === 0 && !element.classList.contains('hidden')) {
             element.classList.add('hidden'); // Hide if empty
          }
        });

        // Update section rendering for cart total if needed
        fetch('/?sections=cart-total')
          .then(response => response.text())
          .then(sectionsText => {
             try {
                const sectionsJson = JSON.parse(sectionsText);
                const cartTotalHtml = sectionsJson['cart-total'];
                 if (cartTotalHtml) {
                    const parser = new DOMParser();
                    const doc = parser.parseFromString(cartTotalHtml, 'text/html');
                    const newCartTotalContent = doc.querySelector('#cart-total')?.innerHTML;
                    if (newCartTotalContent) {
                         document.querySelectorAll('#cart-total').forEach(el => {
                             el.innerHTML = newCartTotalContent;
                         });
                     }
                 }
             } catch(e) {
                 console.warn("Could not parse cart-total section response");
             }

          })
          .catch(error => console.error('Error updating cart total section:', error));
      })
      .catch(error => console.error('Error updating cart information:', error));
  }

  function setupColorButtons() {
    colorOptions.forEach((btn, index) => {
      btn.addEventListener('click', function(e) {
        e.preventDefault();
        e.stopPropagation();

        const variantId = btn.getAttribute('data-variant-id');
        const colorValue = btn.getAttribute('data-value') || btn.getAttribute('title');

        let targetIndex = -1;
        if (variantId) {
          targetIndex = allVariantData.findIndex(v => v.id === variantId);
        }
        if (targetIndex === -1) {
          targetIndex = allVariantData.findIndex(v => v.colorElement === btn);
        }
        if (targetIndex === -1 && allVariantData.length === colorOptions.length) {
          targetIndex = index;
        }

        if (targetIndex !== -1) {
          updateDisplay(targetIndex);
        }
      });
    });
  }

  function setupThumbnails() {
    thumbnailButtons.forEach((btn, index) => {
      btn.addEventListener('click', function(e) {
        e.preventDefault();
        e.stopPropagation();

        if (index >= mainImages.length) return;

        const mediaId = mainImages[index].getAttribute('data-media-id');
        let targetIndex = -1;

        if (mediaId) {
          targetIndex = allVariantData.findIndex(v => v.mediaId === mediaId);
        }
        if (targetIndex === -1) {
          targetIndex = allVariantData.findIndex(v => v.imageElement === mainImages[index]);
        }
        if (targetIndex === -1 && allVariantData.length === mainImages.length) {
            targetIndex = index;
        }


        if (targetIndex !== -1) {
          updateDisplay(targetIndex);
        } else {
          mainImages.forEach(img => img.classList.remove('active'));
          mainImages[index].classList.add('active');
          thumbnailButtons.forEach(button => button.classList.remove('active'));
          btn.classList.add('active');
        }
      });
    });
  }

  function setupAddToCartButton() {
    if (!addToCartButton) return;

    addToCartButton.addEventListener('click', function(e) {
      e.preventDefault();
      e.stopPropagation();

      if (this.disabled || this.classList.contains('adding')) return;

      const variantId = this.getAttribute('data-variant-id');
      if (!variantId) return;

      this.classList.add('adding');
      const originalText = this.textContent;
      this.textContent = 'Adding...';

      const formData = { 'items': [{ 'id': variantId, 'quantity': 1 }] };

      fetch('/cart/add.js', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(formData)
      })
      .then(response => {
        if (!response.ok) {
          return response.json().then(data => {
            throw { status: response.status, message: data.description || 'Error' };
          });
        }
        return response.json();
      })
      .then(data => {
        this.textContent = 'Added!';
        updateCartState();
        setTimeout(() => {
          this.classList.remove('adding');
          this.textContent = originalText;
        }, 1500);
      })
      .catch(error => {
        this.classList.remove('adding');
        this.textContent = error.message || 'Error';
        setTimeout(() => {
          this.textContent = originalText;
          // Re-evaluate button state based on current variant availability
          const currentVariant = allVariantData[currentIndex];
           if(currentVariant) {
              this.disabled = !currentVariant.available;
              this.textContent = currentVariant.available ? 'ADD TO BAG' : 'SOLD OUT';
           } else {
               this.textContent = 'ADD TO BAG'; // Default fallback
               this.disabled = false;
           }
        }, 2000);
      });
    });
  }

  async function init() {
    try {
      const productData = await fetchProductData();
      if (!productData) return;

      allVariantData = buildVariantDataList(productData);
      if (allVariantData.length === 0) return;

      setupColorButtons();
      setupThumbnails();
      setupAddToCartButton();

      // Initialize display with the first available variant or just the first one
      let initialIndex = allVariantData.findIndex(v => v.available);
      if (initialIndex === -1) initialIndex = 0; // Fallback to the first variant if none are available
      if(allVariantData.length > 0) {
          updateDisplay(initialIndex);
      }


    } catch (error) {
      console.error('Error during initialization:', error);
    }
  }

  init();

  const accordions = productSection.querySelectorAll('.product-accordion');
  accordions.forEach(accordion => {
    const summary = accordion.querySelector('summary');
    if (summary) {
      summary.addEventListener('click', (e) => {
         // Only prevent default if we're managing the open state manually
         // e.preventDefault(); // Might not be needed with <details> default behavior

         const currentlyOpen = accordion.hasAttribute('open');

        // Close others only if we are opening this one
         if (!currentlyOpen) {
             accordions.forEach(acc => {
                 if (acc !== accordion && acc.hasAttribute('open')) {
                     acc.removeAttribute('open');
                     // Update icon if needed
                     const otherIcon = acc.querySelector('.accordion-icon');
                     if (otherIcon) otherIcon.textContent = '+';
                 }
             });
         }

         // Toggle current accordion (browser might do this automatically, check if needed)
         // accordion.toggleAttribute('open'); // Only if preventing default

         // Update icon for the clicked accordion
         const icon = summary.querySelector('.accordion-icon');
         if (icon) {
             // Check state *after* potential toggle
             icon.textContent = accordion.hasAttribute('open') ? '-' : '+';
         }
      });

       // Set initial icon state for pre-opened accordions
       const icon = summary.querySelector('.accordion-icon');
       if (icon) {
           icon.textContent = accordion.hasAttribute('open') ? '-' : '+';
       }
    }
  });
});
</script>

<style>
.product-price,
.sold-out-badge,
.product-badge,
.option-name,
.accordion-content {
  font-family: "NHaasGroteskTXPro";
}

.product-accordion summary h3{
  font-family: "SweetSansProBold";
  font-size: 12px;
}

.product-detail-section {
  max-width: 1350px;
  margin: 0 auto 50px;
  padding: 0 20px;
}

.product-detail-wrapper {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: 40px;
  align-items: start;
}

/* Media Column Styles */
.product-media-column {
  position: relative;
  grid-column: 1 / 7;
}

/* Info Column Styles */
.product-info-column {
  padding-top: 20px;
  grid-column: 8 / 13; /* Usando 13 para asegurar que llegue hasta el final (12 inclusive) */
}

.product-images {
  position: relative;
  padding-bottom: 100%;
  overflow: hidden;
  background: #f7f7f7;
}

.product-image,
.product-video,
.product-model {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  transition: opacity 0.3s;
  pointer-events: none;
}

.product-image.active,
.product-video.active,
.product-model.active {
  opacity: 1;
  pointer-events: auto;
}

.no-image-placeholder {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #f8f8f8;
  color: #999;
  font-size: 12px;
  font-weight: bold;
}

.product-thumbnails {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 15px;
}

.thumbnail-button {
  width: 70px;
  height: 70px;
  padding: 0;
  border: 1px solid #e8e8e8;
  background: none;
  cursor: pointer;
  overflow: hidden;
}

.thumbnail-button.active {
  border-color: #000;
}

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

.product-badge {
  font-size: 12px;
  margin-bottom: 10px;
  color: #616161;
}

.product-title {
  font-size: 24px;
  font-weight: 400;
  margin-bottom: 0px;
  line-height: 1.4;
  letter-spacing: 0.75px;
  text-transform: uppercase;
  font-family: "SweetSansProRegular";
}

.product-price {
  font-size: 16px;
  color: #000;
  margin-bottom: 15px;
  letter-spacing: 0.75px;
}

/* Reviews */
.product-reviews {
  display: flex;
  align-items: center;
  margin-bottom: 20px;
}

.star-rating {
  display: flex;
}

.star {
  color: #d8d8d8;
  font-size: 16px;
}

.star.filled {
  color: #000;
}

.review-count {
  margin-left: 5px;
  color: #616161;
  text-decoration: underline;
}

/* Variant Selectors */
.product-variants {
  margin-bottom: 20px;
}

.variant-option {
  margin-bottom: 20px;
  display: flex;
  gap: 5rem;
}

.option-name {
  font-size: 12px;
  margin-bottom: 10px;
  font-weight: 400;
  min-width: 50px;
}

.color-options {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  align-items: center;
}

.color-option {
  width: 24px;
  height: 24px;
  border-radius: 50%;
  border: 2px solid #8d8d8d;
  cursor: pointer;
  transition: transform 0.2s, box-shadow 0.2s;
  padding: 0;
  background-clip: content-box;
}

.color-option[style*="background-color: white"] {
  border-color: #ccc;
}

.color-option:hover {
  transform: scale(1.1);
}

.color-option.active {
  box-shadow: 0 0 0 1px white, 0 0 0 2px #000;
}

.size-options {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}

.size-option {
  min-width: 40px;
  height: 40px;
  padding: 0 15px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid #e8e8e8;
  background: white;
  cursor: pointer;
  font-size: 12px;
  transition: all 0.2s;
}

.size-option:hover {
  border-color: #999;
}

.size-option.active {
  border-color: #000;
  background: #000;
  color: white;
}

/* Add to Cart */
.product-actions {
  margin-bottom: 30px;
}

.add-to-cart-button {
  width: 100%;
  padding: 12px;
  cursor: pointer;
  transition: all 0.3s;
  font-weight: 400;
  text-align: center;
  background-color: #000;
  color: #fff;
  border: 1px solid #000;
  font-family: "SweetSansProBold";
}

.add-to-cart-button:hover:not([disabled]) {
  background-color: #333;
}

.add-to-cart-button[disabled] {
  background-color: #f8f8f8;
  border-color: #e8e8e8;
  color: #999;
  cursor: not-allowed;
}

/* Accordions */
.product-accordions {
  border-top: 1px solid #e8e8e8;
}

.product-accordion {
  border-bottom: 1px solid #e8e8e8;
}

.product-accordion summary {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 15px 0;
  cursor: pointer;
  list-style: none;
}

.product-accordion summary h3 {
  font-size: 12px;
  font-weight: 400;
  margin: 0;
}

.product-accordion .accordion-icon {
  font-size: 16px;
  transition: transform 0.3s;
}

.product-accordion[open] .accordion-icon {
  transform: rotate(45deg);
}

.accordion-content {
  padding: 0 0 20px 0;
  font-size: 12px;
  line-height: 1.6;
}

/* Responsive */
@media (max-width: 991px) {
  .product-detail-wrapper {
    gap: 30px;
  }
  
  .product-media-column {
    grid-column: 1 / 7;
  }
  
  .product-info-column {
    grid-column: 7 / 13;
  }
}

@media (max-width: 767px) {
  .product-detail-wrapper {
    grid-template-columns: 1fr;
  }
  
  .product-media-column,
  .product-info-column {
    grid-column: 1 / -1;
  }
  
  .product-media-column {
    margin-bottom: 20px;
  }
}
</style>
Replies 2 (2)

Shadab_dev
Shopify Partner
1511 81 166

It's tough to just see the snippet without actually seeing it in action. Collaboration would be a better option. 

 

You could may be double check if you have the right images on your variants in the admin backend 

Buy me Coffee, if you feel i was helpful. Email Me here or WhatsApp me with this link for any help with shopify theme customizations or any project in web dev. If this is helpful, please Like and Accept the solution.

tim
Shopify Partner
4689 570 1698

To start with, I see the problem with this pat of the code:

  {% for option in product.options_with_values %}
    {% if option.name == 'Color' or option.name == 'Colour' %}
      <div class="variant-option">
        <h3 class="option-name">
          {{ option.name }}: <span class="selected-color-name"></span>
        </h3>
        <div class="color-options">
          {% assign unique_values = option.values | uniq %}
          {% for value in unique_values %}
            {% assign color_code = value | handleize %}
            {% assign has_image = false %}
            {% assign variant_id = "" %}
            {% assign media_id = "" %}

            {% for variant in product.variants %}
              {% if variant.options[forloop.parentloop.index0] == value %}

We have 3 nested loops:

  1. loop over product options
  2. loop over option values 
  3. loop over variants

Then, a condition is checked:

            {% if variant.options[forloop.parentloop.index0] == value %}

The forloop.parentloop.index0 refers to the index in the second loop, but it should refer to the index in the first loop!

So the code should be modified like this:

  {% for option in product.options_with_values %}
    {% if option.name == 'Color' or option.name == 'Colour' %}
      {% assign option_index = forloop.index0 %}
      <div class="variant-option">
        <h3 class="option-name">
          {{ option.name }}: <span class="selected-color-name"></span>
        </h3>
        <div class="color-options">
          {% assign unique_values = option.values | uniq %}
          {% for value in unique_values %}
            {% assign color_code = value | handleize %}
            {% assign has_image = false %}
            {% assign variant_id = "" %}
            {% assign media_id = "" %}

            {% for variant in product.variants %}
              {% if variant.options[option_index] == value %}

I've added a variable option_index and use this variable instead.

 

There may be other problems...

If my post is helpful, hit the thumb up button -- it will help others with similar problem to find a solution.
I can be reached via e-mail tairli@yahoo.com