Skip to main content
Nexus Theme’s product pages are designed to maximize conversions with advanced features like image galleries, variant selectors, product recommendations, and customer reviews. Every element is optimized for both user experience and performance.

Overview

Product pages in Nexus Theme include:
  • Advanced Image Gallery with zoom, thumbnails, and video support
  • Smart Variant Selectors with color swatches and size guides
  • Product Information Tabs for organized content display
  • Related Products and recommendations
  • Customer Reviews and ratings system
  • Social Sharing and wishlist functionality
  • Mobile-Optimized responsive design
  • Performance Optimized with lazy loading and critical CSS
The product image gallery is one of the most important features for converting visitors to customers.
  • High-Resolution Images: Support for multiple image formats (WebP, JPEG, PNG)
  • Zoom Functionality: Hover to zoom for detailed product inspection
  • Thumbnail Navigation: Easy browsing through all product images
  • Video Support: Embed product videos for enhanced engagement
  • Lazy Loading: Images load as needed for better performance
  • Mobile Touch: Swipe gestures for mobile users
{% if product.media.size > 0 %}
  <div class="product-gallery" data-product-gallery>
    <div class="product-gallery__main">
      {% for media in product.media %}
        <div class="product-gallery__item" data-gallery-item="{{ forloop.index0 }}">
          {% case media.media_type %}
            {% when 'image' %}
              <img src="{{ media | image_url: width: 800 }}" 
                   alt="{{ media.alt | escape }}"
                   loading="{{ forloop.first | ternary: 'eager', 'lazy' }}"
                   class="product-gallery__image"
                   data-zoom-src="{{ media | image_url: width: 1200 }}">
            {% when 'video' %}
              <video controls class="product-gallery__video">
                <source src="{{ media.sources[0].url }}" type="{{ media.sources[0].mime_type }}">
              </video>
          {% endcase %}
        </div>
      {% endfor %}
    </div>
    
    {% if product.media.size > 1 %}
      <div class="product-gallery__thumbnails">
        {% for media in product.media %}
          <button class="product-gallery__thumbnail" 
                  data-gallery-thumbnail="{{ forloop.index0 }}"
                  aria-label="View image {{ forloop.index }}">
            <img src="{{ media | image_url: width: 100 }}" 
                 alt="{{ media.alt | escape }}"
                 loading="lazy">
          </button>
        {% endfor %}
      </div>
    {% endif %}
  </div>
{% endif %}
.product-gallery {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1rem;
}

.product-gallery__main {
  position: relative;
  aspect-ratio: 1;
  overflow: hidden;
  border-radius: 0.5rem;
}

.product-gallery__item {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  opacity: 0;
  transition: opacity 0.3s ease;
}

.product-gallery__item.active {
  opacity: 1;
}

.product-gallery__image {
  width: 100%;
  height: 100%;
  object-fit: cover;
  cursor: zoom-in;
}

.product-gallery__thumbnails {
  display: flex;
  gap: 0.5rem;
  overflow-x: auto;
  padding: 0.5rem 0;
}

.product-gallery__thumbnail {
  flex-shrink: 0;
  width: 80px;
  height: 80px;
  border: 2px solid transparent;
  border-radius: 0.25rem;
  cursor: pointer;
  transition: border-color 0.2s ease;
}

.product-gallery__thumbnail.active {
  border-color: var(--color-primary);
}

.product-gallery__thumbnail img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 0.125rem;
}

Product Information

Product Title and Price

<div class="product-info">
  <h1 class="product-title">{{ product.title }}</h1>
  
  <div class="product-price">
    {% if product.compare_at_price > product.price %}
      <span class="product-price__current">{{ product.price | money }}</span>
      <span class="product-price__compare">{{ product.compare_at_price | money }}</span>
      <span class="product-price__savings">
        Save {{ product.compare_at_price | minus: product.price | money }}
      </span>
    {% else %}
      <span class="product-price__current">{{ product.price | money }}</span>
    {% endif %}
  </div>
  
  {% if product.available %}
    <p class="product-availability product-availability--in-stock">
      ✓ In Stock
    </p>
  {% else %}
    <p class="product-availability product-availability--out-of-stock">
      Out of Stock
    </p>
  {% endif %}
</div>

Product Description

<div class="product-description">
  <div class="product-tabs">
    <div class="product-tabs__nav">
      <button class="product-tabs__tab active" data-tab="description">
        Description
      </button>
      <button class="product-tabs__tab" data-tab="details">
        Details
      </button>
      <button class="product-tabs__tab" data-tab="shipping">
        Shipping
      </button>
      {% if product.metafields.custom.size_guide %}
        <button class="product-tabs__tab" data-tab="size-guide">
          Size Guide
        </button>
      {% endif %}
    </div>
    
    <div class="product-tabs__content">
      <div class="product-tabs__panel active" data-tab="description">
        {{ product.description }}
      </div>
      
      <div class="product-tabs__panel" data-tab="details">
        {% if product.vendor %}
          <p><strong>Brand:</strong> {{ product.vendor }}</p>
        {% endif %}
        {% if product.type %}
          <p><strong>Type:</strong> {{ product.type }}</p>
        {% endif %}
        {% if product.tags.size > 0 %}
          <p><strong>Tags:</strong> {{ product.tags | join: ', ' }}</p>
        {% endif %}
      </div>
      
      <div class="product-tabs__panel" data-tab="shipping">
        <p>Free shipping on orders over $50</p>
        <p>Standard delivery: 3-5 business days</p>
        <p>Express delivery: 1-2 business days</p>
      </div>
      
      {% if product.metafields.custom.size_guide %}
        <div class="product-tabs__panel" data-tab="size-guide">
          {{ product.metafields.custom.size_guide }}
        </div>
      {% endif %}
    </div>
  </div>
</div>

Variant Selector

The variant selector allows customers to choose product options like size, color, material, etc.

Variant Selector Implementation

{% unless product.has_only_default_variant %}
  <form class="product-form" data-product-form>
    <div class="product-variants">
      {% for option in product.options_with_values %}
        <div class="product-variant">
          <label class="product-variant__label">
            {{ option.name }}:
            <span class="product-variant__selected" data-selected-option="{{ option.name | handleize }}">
              {{ option.selected_value }}
            </span>
          </label>
          
          <div class="product-variant__options">
            {% for value in option.values %}
              {% assign variant = product.variants | where: "option1", value | first %}
              {% if option.name == "Color" or option.name == "Colour" %}
                <button type="button"
                        class="product-variant__option product-variant__option--color"
                        data-variant-option="{{ option.name | handleize }}"
                        data-value="{{ value | escape }}"
                        data-variant-id="{{ variant.id }}"
                        style="background-color: {{ value | downcase }}"
                        aria-label="{{ value }}">
                  <span class="sr-only">{{ value }}</span>
                </button>
              {% else %}
                <button type="button"
                        class="product-variant__option"
                        data-variant-option="{{ option.name | handleize }}"
                        data-value="{{ value | escape }}"
                        data-variant-id="{{ variant.id }}">
                  {{ value }}
                </button>
              {% endif %}
            {% endfor %}
          </div>
        </div>
      {% endfor %}
    </div>
    
    <input type="hidden" name="id" value="{{ product.selected_or_first_available_variant.id }}">
    
    <div class="product-form__actions">
      <div class="product-quantity">
        <label for="quantity">Quantity:</label>
        <div class="quantity-selector">
          <button type="button" class="quantity-selector__btn" data-quantity-minus>-</button>
          <input type="number" id="quantity" name="quantity" value="1" min="1" class="quantity-selector__input">
          <button type="button" class="quantity-selector__btn" data-quantity-plus>+</button>
        </div>
      </div>
      
      <button type="submit" 
              class="btn btn--primary btn--large product-form__submit"
              {% unless product.available %}disabled{% endunless %}>
        {% if product.available %}
          Add to Cart
        {% else %}
          Sold Out
        {% endif %}
      </button>
    </div>
  </form>
{% else %}
  <form class="product-form" data-product-form>
    <input type="hidden" name="id" value="{{ product.selected_or_first_available_variant.id }}">
    
    <div class="product-form__actions">
      <div class="product-quantity">
        <label for="quantity">Quantity:</label>
        <div class="quantity-selector">
          <button type="button" class="quantity-selector__btn" data-quantity-minus>-</button>
          <input type="number" id="quantity" name="quantity" value="1" min="1" class="quantity-selector__input">
          <button type="button" class="quantity-selector__btn" data-quantity-plus>+</button>
        </div>
      </div>
      
      <button type="submit" 
              class="btn btn--primary btn--large product-form__submit"
              {% unless product.available %}disabled{% endunless %}>
        {% if product.available %}
          Add to Cart
        {% else %}
          Sold Out
        {% endif %}
      </button>
    </div>
  </form>
{% endunless %}

Variant Selector CSS

.product-variants {
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
  margin-bottom: 2rem;
}

.product-variant__label {
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-weight: 600;
  margin-bottom: 0.5rem;
}

.product-variant__selected {
  font-weight: normal;
  color: var(--color-text-secondary);
}

.product-variant__options {
  display: flex;
  gap: 0.5rem;
  flex-wrap: wrap;
}

.product-variant__option {
  padding: 0.5rem 1rem;
  border: 2px solid var(--color-border);
  border-radius: 0.25rem;
  background: none;
  cursor: pointer;
  transition: all 0.2s ease;
  font-size: 0.875rem;
}

.product-variant__option:hover {
  border-color: var(--color-primary);
}

.product-variant__option.selected {
  border-color: var(--color-primary);
  background-color: var(--color-primary);
  color: white;
}

.product-variant__option--color {
  width: 40px;
  height: 40px;
  padding: 0;
  border-radius: 50%;
  position: relative;
}

.product-variant__option--color.selected::after {
  content: '';
  position: absolute;
  top: -4px;
  left: -4px;
  right: -4px;
  bottom: -4px;
  border: 2px solid var(--color-primary);
  border-radius: 50%;
}

Product Recommendations

Show related products to increase average order value.

Recommendations Implementation

{% if recommendations.performed and recommendations.products_count > 0 %}
  <section class="product-recommendations">
    <h2 class="product-recommendations__title">You might also like</h2>
    
    <div class="product-recommendations__grid">
      {% for product in recommendations.products limit: 4 %}
        <div class="product-card">
          <a href="{{ product.url }}" class="product-card__link">
            <div class="product-card__image">
              <img src="{{ product.featured_image | image_url: width: 400 }}" 
                   alt="{{ product.title | escape }}"
                   loading="lazy">
            </div>
            
            <div class="product-card__content">
              <h3 class="product-card__title">{{ product.title }}</h3>
              <div class="product-card__price">
                {% if product.compare_at_price > product.price %}
                  <span class="product-card__price-current">{{ product.price | money }}</span>
                  <span class="product-card__price-compare">{{ product.compare_at_price | money }}</span>
                {% else %}
                  <span class="product-card__price-current">{{ product.price | money }}</span>
                {% endif %}
              </div>
            </div>
          </a>
        </div>
      {% endfor %}
    </div>
  </section>
{% endif %}

Customer Reviews

Display customer reviews to build trust and social proof.

Reviews Implementation

{% if product.metafields.spr.reviews %}
  <section class="product-reviews">
    <h2 class="product-reviews__title">Customer Reviews</h2>
    
    <div class="product-reviews__summary">
      <div class="product-reviews__rating">
        <span class="product-reviews__stars">
          {% assign rating = product.metafields.spr.reviews | split: '"rating":' | last | split: ',' | first %}
          {% for i in (1..5) %}
            {% if i <= rating %}

            {% else %}

            {% endif %}
          {% endfor %}
        </span>
        <span class="product-reviews__count">
          {{ product.metafields.spr.reviews | split: '"reviewCount":' | last | split: ',' | first }} reviews
        </span>
      </div>
    </div>
    
    <div class="product-reviews__content">
      {{ product.metafields.spr.reviews }}
    </div>
  </section>
{% endif %}

Social Sharing

Allow customers to share products on social media.

Social Sharing Implementation

<div class="product-social">
  <h3 class="product-social__title">Share this product</h3>
  
  <div class="product-social__buttons">
    <a href="https://www.facebook.com/sharer/sharer.php?u={{ shop.url | append: product.url | url_encode }}"
       target="_blank"
       rel="noopener"
       class="product-social__button product-social__button--facebook"
       aria-label="Share on Facebook">
      <svg width="20" height="20" viewBox="0 0 20 20" fill="currentColor">
        <path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z"/>
      </svg>
    </a>
    
    <a href="https://twitter.com/intent/tweet?text={{ product.title | url_encode }}&url={{ shop.url | append: product.url | url_encode }}"
       target="_blank"
       rel="noopener"
       class="product-social__button product-social__button--twitter"
       aria-label="Share on Twitter">
      <svg width="20" height="20" viewBox="0 0 20 20" fill="currentColor">
        <path d="M6.29 18.251c7.547 0 11.675-6.253 11.675-11.675 0-.178 0-.355-.012-.53A8.348 8.348 0 0020 3.92a8.19 8.19 0 01-2.357.646 4.118 4.118 0 001.804-2.27 8.224 8.224 0 01-2.605.996 4.107 4.107 0 00-6.993 3.743 11.65 11.65 0 01-8.457-4.287 4.106 4.106 0 001.27 5.477A4.073 4.073 0 01.8 7.713v.052a4.105 4.105 0 003.292 4.022 4.095 4.095 0 01-1.853.07 4.108 4.108 0 003.834 2.85A8.233 8.233 0 010 16.407a11.616 11.616 0 006.29 1.84"/>
      </svg>
    </a>
    
    <a href="https://pinterest.com/pin/create/button/?url={{ shop.url | append: product.url | url_encode }}&media={{ product.featured_image | image_url: width: 1200 | url_encode }}&description={{ product.title | url_encode }}"
       target="_blank"
       rel="noopener"
       class="product-social__button product-social__button--pinterest"
       aria-label="Share on Pinterest">
      <svg width="20" height="20" viewBox="0 0 20 20" fill="currentColor">
        <path d="M10 0C4.477 0 0 4.477 0 10c0 4.237 2.636 7.855 6.356 9.312-.088-.791-.167-2.005.035-2.868.181-.78 1.172-4.97 1.172-4.97s-.299-.6-.299-1.486c0-1.39.806-2.428 1.81-2.428.852 0 1.264.64 1.264 1.408 0 .858-.546 2.14-.828 3.33-.236.995.5 1.807 1.48 1.807 1.778 0 3.144-1.874 3.144-4.58 0-2.393-1.72-4.068-4.177-4.068-2.843 0-4.515 2.133-4.515 4.34 0 .859.331 1.781.745 2.281a.3.3 0 01.069.288l-.278 1.133c-.044.183-.145.223-.335.134-1.249-.581-2.03-2.407-2.03-3.874 0-3.154 2.292-6.052 6.608-6.052 3.469 0 6.165 2.473 6.165 5.776 0 3.447-2.173 6.22-5.19 6.22-1.013 0-1.965-.525-2.291-1.148l-.623 2.378c-.226.869-.835 1.958-1.244 2.621.937.29 1.931.446 2.962.446 5.523 0 10-4.477 10-10S15.523 0 10 0z"/>
      </svg>
    </a>
  </div>
</div>

Mobile Optimization

Product pages are fully optimized for mobile devices with:
  • Touch-Friendly Interface: Large buttons and touch targets
  • Swipe Gestures: Swipe through product images
  • Responsive Layout: Optimized for all screen sizes
  • Fast Loading: Optimized images and lazy loading
  • Easy Navigation: Simplified mobile navigation

Mobile CSS

@media (max-width: 768px) {
  .product-layout {
    grid-template-columns: 1fr;
    gap: 1rem;
  }
  
  .product-gallery__main {
    aspect-ratio: 1;
  }
  
  .product-gallery__thumbnails {
    justify-content: center;
  }
  
  .product-variant__options {
    justify-content: center;
  }
  
  .product-form__actions {
    flex-direction: column;
    gap: 1rem;
  }
  
  .product-form__submit {
    width: 100%;
  }
  
  .product-recommendations__grid {
    grid-template-columns: repeat(2, 1fr);
    gap: 1rem;
  }
}

Performance Optimization

Image Optimization

  • WebP Support: Automatic WebP format for supported browsers
  • Responsive Images: Different sizes for different screen sizes
  • Lazy Loading: Images load as needed
  • Critical Images: First product image loads immediately

JavaScript Optimization

  • Minified Code: All JavaScript is minified for production
  • Async Loading: Non-critical scripts load asynchronously
  • Event Delegation: Efficient event handling
  • Debounced Functions: Optimized for performance

Best Practices

Content Strategy

  1. High-Quality Images: Use professional product photography
  2. Detailed Descriptions: Provide comprehensive product information
  3. Clear Pricing: Display prices prominently
  4. Trust Signals: Include reviews, ratings, and guarantees

User Experience

  1. Easy Navigation: Clear product options and variants
  2. Fast Loading: Optimize images and code
  3. Mobile First: Ensure great mobile experience
  4. Accessibility: Follow WCAG guidelines

Conversion Optimization

  1. Clear CTAs: Prominent “Add to Cart” buttons
  2. Social Proof: Customer reviews and ratings
  3. Related Products: Cross-sell opportunities
  4. Trust Elements: Security badges and guarantees

Troubleshooting

Common Issues

  1. Images Not Loading: Check image file sizes and formats
  2. Variants Not Working: Verify variant configuration
  3. Reviews Not Showing: Check review app integration
  4. Mobile Issues: Test on various mobile devices

Performance Issues

  1. Slow Loading: Optimize images and reduce JavaScript
  2. Layout Shift: Set proper image dimensions
  3. Mobile Lag: Reduce animation complexity