5 Common Pitfalls when Developing a Shopify Theme

I’ve worked with a fair amount of Shopify themes at this point, and there are some trends I’ve noticed over time. Here are 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 an 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 declaring 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 to improve your JavaScript organization.

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.

More reading

Take a look at 8 Development Tips for Building Better Custom Shopify Sites, which is an article I wrote for Shopify.

Find this helpful? You might also like our apps:

  • Customer Fields allows you to build custom registration forms and retrieve valuable data from customers at just the right time.
  • Meteor Mega Menu offers a variety of beautiful dropdown menu templates which you can attach to your exisiting Shopify navigation, meaning your store could have a menu makeover in minutes.

Related articles


How to implement access control on your Shopify store


How to add extra customer data to Shopify orders


2 ways developers build Shopify storefront apps and how they affect your theme