tetchi blog

Tetchi's blog about life and stuff

Shopify Theme from Scratch Part 5: product.liquid

Shopify Theme from Scratch Part 5: in this tutorial we’re going to be building the product.liquid template, which is where customers add products to the cart.


The product page is where you see the details of an individual product. This includes the product images, options, descriptions, and more.

This part is a doozie, so grab a Red Bull™ and let’s do it up!

1. Open a product with Multiple Options

Navigate to the “Awesome Sneakers” product, and open it on your storefront.

awesome sneakers

We’re going to be working with this dummy product because I’ve already added some options and variants to it.

2. Add the initial markup

We’ll start off by setting up the “skeleton” of the product template. Delete the contents of product.liquid, and add the code below:

We’re going to lay out the product images in a column on the left-hand side, and the product info on the right-hand side.

3. Output the product images

When you upload a product image, Shopify generates different sizes of that image. You can see a list of all the different sizes here. Here, we’re loading up the ‘grande’ version of the image, and we’re going to wrap it in an anchor tag so that when clicked, it goes to the bigger ‘original’ version.

Let’s do a for loop through the product.images array to output the other product images. I’m going to use the offset filter to skip the first product thumbnail, as that would be redundant.

{% for image in product.images | offset:1 %} {% endfor %}

Let’s add the CSS to style these images nicely. Open style.css, and at the very bottom at the following snippet of code:

/**** product.liquid ****/

.product-images img{max-width: 100%; height: auto;}
.product-featured-image{border: 1px solid #ccc; padding:10px; margin-bottom:20px;}
.product-img{border: 1px solid #ccc; text-align:center; padding:10px; margin: 0 20px 20px 0; width:100px;}

Here’s a screenshot of the product page so far:


Figure 5.1: The product images are now output on the left-hand side.

4. Output product details

Next, we’re going to fill up the right side of the product page with product details, including: product title, price, variants & options, and description.

Open product.liquid, and insert the code in red below.


{{ product.title }}

{{ product.description}}

You should now see the product details being output, but we need to add some CSS to make it align properly on the page.

Open style.css, and insert the following CSS to the bottom:

.product-details{width: 524px;}
.product-desc, .price-field, .product-form{margin-bottom:30px;}
.product-form{text-align: right;} 
.selector-wrapper{padding:10px 0; border-bottom:1px solid #ccc;}
.selector-wrapper label, .selector-wrapper select{display: inline-block;}
.selector-wrapper label{float:left;}
.selector-wrapper select{float:right;}

Still inside style.css, scroll up to the global CSS section, and insert the code in red below:

/**** global css ****/

.left{float: left;}
.right{float: right;}
.last{margin-right:0px !important;}
.btn{background: #2c2b2b; border: none !important; display:inline-block; color:#fff; padding:9px 13px; text-transform: uppercase;font-size:0.8em; font-weight: bold;   border-radius: 8px;}
.btn:hover{background:#585656; color:#fff;}

Here I’m introducing a new class called .btn, that will be applied to all buttons in the theme. Your product page should now look like this:

product page details

Figure 5.2: The product details are now output on the right-hand side.

5. Plug in selectCallback

Open product.liquid, and insert the following script at the bottom:

What is this selectCallback function?

selectCallback is a very important Javascript function that is used on the product template. Its main purpose is to split up a product’s options into multiple dropdowns, based on how many Options a product has. What’s important to know about selectCallback is that it triggers every time a user selects a different variant using the dropdowns. This means that it can be used to output information of the currently-selected variant such as price, compare at price, SKU, inventory quantity, etc. (for a full list of what can be output, see http://wiki.shopify.com/Variant).

Notice how the price and availability of the variant now update as you select different variants from the dropdowns. That’s selectCallback at work baby!


Figure 5.3: selectCallback splits up the options into multiple dropdowns

6. Add links to navigate within a collection

The last thing we’re going to do is have links for navigating to the next and previous products in a collection.

The {% if collection %} statement makes it so that the links are only output if a customer arrived at the product page via a collection.

Open product.liquid, and paste in the code in red below.


{{ product.title }}

{{ product.description}}
{% if collection %}
{% if collection.previous_product %}
{{ '← Previous Product' | link_to: collection.previous_product }}
{% endif %} {% if collection.next_product %}
{{ 'Next Product →' | link_to: collection.next_product }}
{% endif %}
{% endif %}

If you go to a product through a collection, you should now see a next/previous link under the product description (Figure 5.4).

navigating within a collection

Figure 5.4: These links take you to the next/previous products in the same collection as the product you’re viewing.

That is all for now!

← Back to table of contents


  • Amandeep Singh
    Amandeep Singh on May 8th, 2013

    Nice work man!! Really Helpful. I just have a question, Is there any way by which we can show List of Best Selling Products. This shouldnt be a category but should be generated dynamically.

    Amandeep Singh

  • tetchi
    tetchi on May 8th, 2013

    @Amandeep Unfortunately not – there is no way to check for how many time a product/variant has sold via Liquid. It’s not part of product.js either :(

  • Rodolfo
    Rodolfo on May 10th, 2013

    Hey Tetchi, quick question, I’ve been trying to create two columns in the description for a product (achieved through a hasty table scaffold), but I would like the two columns to have different styles (they’re two different languages). I tried using table style, but looks like that only works within the product description on the admin side, not on the web side. Any ideas?

  • Amandeep Singh
    Amandeep Singh on May 12th, 2013

    Thanks for the reply Tetchi. I am working on a shopify project (Online Book Store) and as you know we do not really have so many fields by which we can show Author, ISBN Number etc. So Is there way by which I can add custom fields (like we can add in WordPress). I’ve read about MetaFields but how can I use them in my store? May be you can write a blog post/tutorial on this :)


  • Amandeep Singh
    Amandeep Singh on May 12th, 2013


    Can you post the link/url?

  • Rodolfo
    Rodolfo on May 12th, 2013

    Hi Amandeep! The example is here: http://www.revvapor.com/products/caramelcappuccino

    The idea was to have the English translation in a lighter color – let’s say a lighter grey.

    I can probably also do some funky crafting with tabs and but I’d rather avoid that option since the description is shared with Vend. But if tabs and <!– split is the only way to divide it out, then that might have to be the option.

  • tetchi
    tetchi on May 13th, 2013

    @Amandeep I’m not too familiar with metafields, but I can certainly work on a tutorial after I’m done with this series :)

  • Amandeep Singh
    Amandeep Singh on May 14th, 2013


    May be this will help : http://jsfiddle.net/vQq8v/

  • Rodolfo
    Rodolfo on May 14th, 2013


    Thanks, I’ll try it out. Looks similar to what I was trying out with straight up, old fashioned HTML tables (yeah, I really need to get a good handle on CSS).


    It seemed to me, even though none of the CSS related to the product.description was stripping out the HTML, it just wasn’t passing the color through the call (even though it worked marvelously in the admin panel).


  • Ben
    Ben on June 4th, 2013

    One super minor thing, but as per the product .csv uploaded way back when, this product is only showing 1 product image besides the featured image (just the Beatles cover, not the other three sneakers)

  • Ben
    Ben on June 29th, 2013

    Also, according to http://wiki.shopify.com/Product_img_url, it seems like using product_img_url: ‘original’ is depreciated. What’s the right way to get the original image size?

  • tetchi
    tetchi on July 7th, 2013

    Thanks for catching those Ben, I’ll make those amendments when I get a chance!

  • Kyle
    Kyle on July 22nd, 2013

    Great tutorials man. I’m just having one issue right now.
    When attempting step 5: “Plug in selectCallback”, it doesn’t split up the variants in the desired way. It seems like selectCallback isn’t being called in the mark up.

  • tetchi
    tetchi on July 22nd, 2013

    @Kyle That’s strange… would you happen to have the URL of your shop handy?

  • Kyle
    Kyle on July 22nd, 2013
  • tetchi
    tetchi on July 22nd, 2013

    @Kyle you’re loading jQuery after the script for selectCallback. The script tag that loads jQuery needs to go in the <head> section, not at the bottom of the theme. See Step 2 of Part 1.

  • Kyle
    Kyle on July 22nd, 2013

    My goodness! What was I on when I did that?
    Thanks for the help tetchi, I appreciate it.

  • tetchi
    tetchi on July 22nd, 2013

    No worries Kyle :) Cheers!

  • Kas
    Kas on August 22nd, 2013

    Quick question. I copied and pasted the JavaScript code as it was, without changing anything, and I think there is something wrong with it. It shows different variants as you can see on the screenshot you included in the post, but when I want to check what Size variants or Title variants are available, it just shows me “test”, not the actual variants (I hope this explanation makes sense ;) ). Any ideas why it is happening? Again – I just copied and pasted the script, as I don’t know JavaScript, and didn’t change a thing.

  • tetchi
    tetchi on August 22nd, 2013

    Hey Kas, what’s the URL of the shop you’re working on?

  • Kas
  • tetchi
    tetchi on August 22nd, 2013

    I took a look at your product template (ex: http://cassia-test-shop.myshopify.com/collections/frontpage/products/awesome-sneakers) and it appears to be working fine. Selecting the different options changes the price and availability properly.

  • Kas
  • tetchi
    tetchi on August 23rd, 2013

    That looks correct to me Kas – have a look at the variants of that product: http://take.ms/P7gQQv. The options in the dropdowns look like they match with what’s shown in the admin page for that product. Let me know if you still need a hand.

  • Kas
    Kas on August 23rd, 2013

    Oh yes, sorry. I don’t know why but I assumed straight away that it only shows the test PAGE, not a variant. Thank you! And sorry again

  • tetchi
    tetchi on August 23rd, 2013

    hey no worries Kas! Let me know if you run into something again.

  • Kas
    Kas on August 23rd, 2013

    Thanks, i’ve just finished the whole tutorial and so far so good ;). Just waiting for the last part now!

  • tetchi
    tetchi on August 23rd, 2013

    Awesome! I’ve been a little caught up with stuff and haven’t had time to finish the last one, I’m going to get it done ASAP! Cheers Kas.

  • Rory
    Rory on November 27th, 2013

    Hi Tetchi

    Thanks so much for this tutorial, is a huge help! I was wondering (and maybe this is out of your remit!) but if I wanted to only have the product variants appear if I add one how would that work or dose there always have to be one variant present?

    Thanks again man!


  • Ricky
    Ricky on January 31st, 2014

    The http://wiki.shopify.com/Product_img_url link is going to a 404 error page.
    But I think the info can be found here http://docs.shopify.com/themes/filters/product-img-url

  • Steve
    Steve on October 22nd, 2014

    Hey, just out of curiosity, how would you hide unavailable options from a dropdown? For example, I have mens and womens shirts with 6 mens sizes and 4 womens sizes but all six sizes show when I have “Womens” selected from the first dropdown when it should only show 4.

    It displays an “out of stock” on the button implying that these products exist when they do not and are just out of stock. Seems like if those options don’t exist, they shouldn’t show at all.

  • Mike
    Mike on October 29th, 2015

    I was a bit confused by the JavaScript until I found the documentation for Shopify.OptionSelectors here: https://docs.shopify.com/support/your-website/themes/can-i-make-my-theme-use-products-with-multiple-options#instantiate-shopify-optionselector

    To avoid listing unavailable product combinations, Shopify has provided another useful snippet: https://docs.shopify.com/manual/configuration/store-customization/advanced-navigation/linked-product-options

    Thanks again for the tutorial Tetchi!

  • Atif
    Atif on January 16th, 2016

    my desc area is not flowing to the right of page, stuck in step 4 , plz help

  • Greg
    Greg on February 23rd, 2016

    @Atif send a link. I can take a look at it

Post a comment