5 Common Pitfalls when Developing a Shopify Theme

Nov 12, 2015 | Blog
5 Common Pitfalls when Developing a Shopify Theme

I've worked with a fair amount of Shopify themes at this point, and there's some trends I've noticed over time. Here's some tips to avoid while you set out to build a Shopify theme.

1. Not thinking of others.

Remember that you're not the only one working on your theme. Most clients will at least make small changes to your markup, CSS, or even JavaScript. The chances of another developer working on your theme is nearly absolute. As you build your theme, write it in such a way that others can easily jump in and change things.

2. Not making good use of snippets.

I find so often that themes are littered with conditional logic that's hard to follow and takes away from the readability of the markup. Many themes I've worked with don't even consider using this in theme.liquid. Why not break it up a bit:

<!DOCTYPE html> 
    {{ content_for_header }}
    {% include 'head' %}
    {% include 'header' %}
    <main id="main">
      {{ content_for_layout }}
    {% include 'footer' %}

This is a simple example, but there's no reason for this file to be much longer. It's better to have a long list of snippet files than html that is impossible to read and gain little context. Snippets provide a way to organize content logically so that the markup is easy to follow. Context is king. Remember that snippets inherit variables declared from where it was defined.

{% assign color = "blue" %}
{% include 'color-picker' %}


Color is {{ color }}
// "Color is blue"

3. Indenting mayhem.

Indentation is the programmer's punctuation. It gives context and clearly identifies what goes where. With a ton of frequency I run into html that looks like this:

<div><div><p>You're cart has
{{ cart.items.size }} items in it.
  <h2>Shipping Estimate</h2>

  <span class=" blue">  {% if color == "blue" %}
   Thanks for your order! {% endif %}

<div> </div></div>

Most of the time I end up indenting this myself so I can read it and understand what's going on. Child tags should always be indented from their parents. It's best to use soft spaces in your text editor so spacing is consistent across editors.

Formatting this might better look like this:

    <p>You're cart has {{ cart.items.size }} items in it.</p>
    <h2>Shipping Estimate</h2>
    <span class=" blue">
      {% if color == "blue" %}Thanks for your order!{% endif %}

But what about liquid indentation?

You'd probably be tempted to use a html formatter like Dirty Markup, but you'd probably run into some issues because liquid code is embedded inside your code. Sometimes a tool like this is really handy, but make sure you're looking at your code and organizing it for the best readability.

So, how should you indent liquid? What's better?

// Example #1:
  {% if three %}
  {% endif %}

// Example #2:
  {% if three %}
  {% endif %}

The subtle difference between these two is the last list item where the liquid conditional indents its contents. The argument for the first would be that it preserves the html indentation. Although the question must be raised - for whom is the indentation written? For the developer or someone viewing the page source? I would opt for the second since its readability is more clear.

Just remember - someone along the way is going to read your code, help them out by indenting everything (unless you want to make it cryptic).

4. Excessive use of !important CSS flags.

The CSS !important flag is one that should only be used on rare occasions. It's an absolute last resort, not a handy tool for a lazy developer. When you keep in mind that other developers will be building or changing your CSS, you'll reconsider how you structure selectors, but you as the developer will benefit the most gain.

The problem that arises from this is that it becomes very difficult to override properties defined with an !important flag. In fact, the only way to overriding it is to declare it after while also delcaring the flag. CSS really works off the principle of inheritance. I've seen this before in themes:

p {
  font-size: 16px !important;

Hm, so every single paragraph tag is forced to be 16px? Anytime you decide a certain context warrants a different size your only option is throw another important tag over it. This results in a theme with hundreds upon hundreds of !important tags. The snowball effect.

Before using this flag, ask the question -

Could this property ever change past this point?

If the answer is yes, don't use it. It will create unnecessary hardship later down the road.

It's better to use well qualified classes and selectors.

Instead of using the 'one size fits all' approach, it's much better to use selectors that further define what you're after. This puts a whole new meaning to "Cascading Style Sheets". Take a look at this great article from Mozilla. This becomes even more powerful when using Sass. Here's a good example:

<div class="product">
  <span class="price">{{ product.price }}</span>
// Bad
.product-price {
  font-weight: bold !important;

// Good
.product {
  .product-price {
    font-weight: bold;

In this case you're defining the font-weight based on the context, instead of universally declaring .product-price to be bold.


5. Not playing nice with JavaScript.

If you're writing even a single line of JavaScript in a Shopify theme, you should read "Use JavaScript responsibly" from the Shopify docs. The three golden rules they list are essential. Although this article is specifically referring to app development, it directly applies to theme development as well. Consider using a framework like RequireJS to build your modules. I wrote a bit about this concept in this article.

Why this is important

Building great Shopify themes and websites in general means staying organized and writing quality code. Even though the end user never sees a line of CSS or HTML, the developers who come after you will. It's like a house that's well put together on the outside but is a total wreck when you step inside. Remember that writing code that is readable is just as important as writing code that work efficiently to viewers.

Recent Articles

Introducing Relatable

Keeping things organized within a Shopify store can be hard, so we built Relatable to help with that.

Why we use Cloud66 to launch Ruby on Rails apps

We use Cloud66 for deploy Ruby on Rails apps, and we love it.

5 Common Pitfalls when Developing a Shopify Theme

Learn some tips on developing Shopify themes and some pitfalls to avoid. Build Shopify themes that perform and are easy to update and edit.

How to create a Shopify email link from your theme navigation

Add an email link to your Shopify website from within your theme using your current link list in navigation.

How to flag Shopify products as "new" by date

Here's a quick way to mark a product as being new by the date it was added to your Shopify store.