Search code examples
shopifyliquid

How can I make this Shopify code fragment less verbose?


I am learning Shopify development. I wonder how can I make this code fragment less verbose, to follow DRY rule. I render product list with a featured image and check if a product has a second image. If so, then I also render second image and use it for a hover functionality. This is my code:

<ul class="homepage-products">
 {% for product in collections.homepage.products %}
  {% liquid
    assign featuredImage = product.featured_image
    assign hoverImage = product.images[1]
  %}
 <li class="homepage-products-li">
  <h2 class="homepage-products-title">{{ product.title }}</h2>
  <a class="homepage-products-a" href="{{ product.url }}">
   <img
    class="homepage-products-image"
    srcset="
     {{ featuredImage | image_url: width: 300 }} 300w,
     {{ featuredImage | image_url: width: 500 }} 500w,
     {{ featuredImage | image_url: width: 700 }} 700w,
     {{ featuredImage | image_url: width: 900 }} 900w,
     {{ featuredImage | image_url: width: 1000 }} 1000w,
     {{ featuredImage | image_url: width: 1445 }} 1445w,
     {{ featuredImage | image_url: width: 1680 }} 1680w,
     {{ featuredImage | image_url: width: 2048 }} 2048w,
     {{ featuredImage | image_url: width: 2200 }} 2200w,
     {{ featuredImage | image_url: width: 2890 }} 2890w,
     {{ featuredImage | image_url: width: 4096 }} 4096w,"
    src="{{ featuredImage | image_url }}"
    alt="{{product.title}}"
    width="{{featuredImage.width}}"
    height="{{featuredImage.height}}" />
    {% if hoverImage != null %}
     <img
      class="homepage-products-hover-image"
      srcset="
       {{ hoverImage | image_url: width: 300 }} 300w,
       {{ hoverImage | image_url: width: 500 }} 500w,
       {{ hoverImage | image_url: width: 700 }} 700w,
       {{ hoverImage | image_url: width: 900 }} 900w,
       {{ hoverImage | image_url: width: 1000 }} 1000w,
       {{ hoverImage | image_url: width: 1445 }} 1445w,
       {{ hoverImage | image_url: width: 1680 }} 1680w,
       {{ hoverImage | image_url: width: 2048 }} 2048w,
       {{ hoverImage | image_url: width: 2200 }} 2200w,
       {{ hoverImage | image_url: width: 2890 }} 2890w,
       {{ hoverImage | image_url: width: 4096 }} 4096w,"
      src="{{ hoverImage | image_url }}"
      alt="{{product.title}}"
      width="{{hoverImage.width}}"
      height="{{hoverImage.height}}" />
    {% else %}
     <img
      class="homepage-products-hover-image"
      srcset="
       {{ featuredImage | image_url: width: 300 }} 300w,
       {{ featuredImage | image_url: width: 500 }} 500w,
       {{ featuredImage | image_url: width: 700 }} 700w,
       {{ featuredImage | image_url: width: 900 }} 900w,
       {{ featuredImage | image_url: width: 1000 }} 1000w,
       {{ featuredImage | image_url: width: 1445 }} 1445w,
       {{ featuredImage | image_url: width: 1680 }} 1680w,
       {{ featuredImage | image_url: width: 2048 }} 2048w,
       {{ featuredImage | image_url: width: 2200 }} 2200w,
       {{ featuredImage | image_url: width: 2890 }} 2890w,
       {{ featuredImage | image_url: width: 4096 }} 4096w,"
      src="{{ featuredImage | image_url }}"
      alt="{{product.title}}"
      width="{{featuredImage.width}}"
      height="{{featuredImage.height}}" />
     {% endif %}
     </a>
    </li>
   {% endfor %}
  </ul>

I was thinking about using a snippet or making conditional rendering more simple like "? :" kind of conditional rendering, that JS has, but I don't know how to make it work in Liquid.


Solution

  • This is completely untested, so you might find a typo or two, but this gives you a general idea about how to effectively make Liquid a little bit less verbose. It will always be pretty long and ugly though.

    {% assign sizes = '500,700,900,1000,1445,1680,2048,2200,2890,4096' | split: ',' %}
    {% capture feature_sizes %}
        {% for size in sizes %}
            ,{{ featuredImage | image_url: width: size }} {{ size }}w
        {% endfor %}
    {% endcapture %}
    {% capture feature_img %}
        <img class="homepage-products-image" srcset="{{ feature_sizes | remove_first: ',' }}" src="{{ featuredImage | image_url }}" alt="{{ product.title }}" width="{{ featuredImage.width }}" height="{{ featuredImage.height }}" />
    {% endcapture %}
    
    {% if hoverImage %}
        {% capture hover_sizes %}
            {% for size in sizes %}
                ,{{ hoverImage | image_url: width: size }} {{ size }}w
            {% endfor %}
        {% endcapture %}
        {% capture hover_img %}
            <img class="homepage-products-hover-image" srcset="{{ hover_sizes | remove_first: ',' }}" src="{{ hoverImage | image_url }}" alt="{{ product.title }}" width="{{ hoverImage.width }}" height="{{ hoverImage.height }}" />
        {% endcapture %}
    {% endif %}
    
    <li class="homepage-products-li">
      <h2 class="homepage-products-title">{{ product.title }}</h2>
      <a class="homepage-products-a" href="{{ product.url }}">
        {{ feature_img }}
        {% if hoverImage %}
            {{ hover_img }}
        {% else %}
            {{ feature_img | replace: 'homepage-products-image', 'homepage-products-hover-image' }}
        {% endif %}
        ...