What’s New for Shopify Theme Developers in 2017

As some of you may know from my previous articles Shopify is a theme-based hosted commerce platform which enables you to build online stores. It’s been steadily growing over the last few years and today is the platform behind 400,000+ businesses in approximately 175 countries.

What’s New for Shopify Theme Developers in 2017

The Shopify platform is constantly evolving and over the last few months, a number of key features have been launched, specifically aimed at theme and app developers. In this article, we’ll be looking at a selection of these new features and toolsets including:

  1. Updates to theme image management
  2. Sections
  3. Blocks
  4. ThemeKit and Slate
  5. The Polaris design system

Many of the following examples will discuss Liquid. Liquid is the template language enabling theme developers to use placeholders and logic constructs in their templates that will be replaced with live store data when a page is requested and rendered. It uses a simple syntax which allows output (e.g. a product title) and logic (e.g. a for loop). I won’t go into too many details here but you can watch my 25 minute screencast that goes into a lot more detail on how Liquid works.

And whilst you’re here, you may also be interested in the following inspiration post, for themes available on ThemeKeeper:

  • What’s New for Shopify Theme Developers in 2017

    20 Best Shopify Themes With Beautiful eCommerce Designs

    Building an eCommerce site is a snap when you have the very best Shopify themes to choose from. A quality Shopify theme has the features you need, is sure to…

1. New Theme Image Management

Let’s begin by looking at one of the major theme related changes that happened recently: the img_url Liquid filter. Until recently images were rendered based on a set of predefined named sizes. For example:

{{ product.featured_image | img_url: 'grande' }}

Here we are requesting the featured image for the product in size grande. This would, assuming the original image had one side equal or greater than 600px, render the image with the longer of the two axes being 600px.

These named sizes are now deprecated and whilst they will still work they have been replaced by a new set of parameters including size, crop, scale, and format. This now makes it possible to do a whole host of image related manipulations previously unavailable to Shopify theme developers.

I’ll be using the img_url Liquid filter in these examples but the techniques will also work with the following other image related objects:

  • product_img_url
  • collection_img_url
  • article_img_url
  • asset_img_url

Let’s begin by looking at how we can resize an image. In order to do this, we replace the now deprecated image name with a specific size in pixels. Here’s an example:

{{ product.featured_image | img_url: '450x450' }}

Using the above syntax now puts the control of the image dimensions in your hands: here we have specified both the width and height (in that order).

You can also specify only a width:

{{ product.featured_image | img_url: '450x' }}

or only a height:

{{ product.featured_image | img_url: 'x450'}}

When specifying a single value, Shopify will calculate the remaining dimension based on the original image size, keeping the original image’s aspect ratio intact.

Going back to our original example, you might think that it would result in a 450×450 version of your image being rendered. This, however, isn’t always the case.

This request would result in a perfect square, only if both of the following conditions are met:

  • The original image was 450px or greater on both axes
  • Both sides are of the same length

If both conditions are true then a 450×450 square image would be rendered. If not, Shopify will resize it using the same logic as if you’ve specified only height or width. The longest side wins out in this situation and is scaled accordingly.

In order to create square images, you can make use of the crop parameter to ensure that the resulting image’s dimensions match the requested dimensions. If the entire image won’t fit in your requested dimensions, the crop parameter specifies which part of the image to show. There are three valid options:

  • top
  • center
  • bottom
  • left
  • right

This functionality has been available since late 2016 but in early 2017 an update was released that added even more flexibility. Themes available in the Shopify Theme Store, including the free Empire theme pictured below, all make use of these techniques. Installing a free theme is a great way to learn more about how to implement these ideas.

It’s now possible to directly access the height, width, and aspect ratio properties of an image using Liquid. Theme developers are now able to make use of this information to serve images sized appropriately for the end user. Here’s an example using srcset to outline how you can take advantage of this in your own themes:What’s New for Shopify Theme Developers in 2017

{% for product in collection.products %}
  <a href="{{ product.url | within: collection }}">
    {% assign image = product.featured_image %}
    <img src="{{ image.src | img_url: '480x' }}" alt="{{ image.alt | escape }}"
      srcset="
      {% if image.width > 640 %}{{ image.src | img_url: '640x' }} 640w{% endif %}
      {% if image.width > 720 %},{{ image.src | img_url: '720x' }} 720w{% endif %}
      {% if image.width > 900 %},{{ image.src | img_url: '900x' }} 900w{% endif %} 
      " 
      sizes="(min-width: 960px) 450px, (min-width: 720px) 50vw, 100vw"
    />
  </a>
{% endfor %}

In this example, we are using the assign Liquid function to create a variable called image that is equal to the currently viewed products featured image (which is set in the Shopify admin). We are then able to use Liquid logic to create our srcset declarations using, in this case, the width property:

{% if image.width > 640 %}{{ image.src | img_url: '640x' }} 640w{% endif %}

The good news is that theme developers don’t need to worry about re-uploading all of their images as Shopify has indexed every image on the platform.

Two other parameters worth discussing are scale and format. The scale parameter enables you to specify the pixel density of the image. You can scale up either 2x or 3x depending on your needs:

{{ product.image | img_url: '400x400', scale: 2 }}

The format parameter lets you specify what file format to use for the image. Currently, you can specify either jpg or pjpg (progressive JPEG):

{{ product.image | img_url: '400x400', format: 'pjpg' }}

You can also take advantage of this technique for images residing in your theme’s assets folder. In order to do this, you use the asset_img_url filter. Here’s an example that also makes use of the img_tag filter which will result in a fully formed img element being rendered in the template:

{{ logo.jpg' | asset_img_url: '300x' | img_tag }}

These new image manipulation filters and image properties finally make it possible to be as flexible as you need to be when it comes to dealing with images, art direction, and being friendly to the end users data plans.

2. Sections

In late 2016 Shopify introduced “Sections”. This new feature allows theme developers to create a custom admin interface which allows store owners to easily add, reorder, and remove content sections such as products, slideshows, videos, or product collections. These are common use cases but you can literally use this functionality to allow store owners to add and edit any type of content. All changes in the admin can be viewed in real-time and once saved will be live in the store.

What’s New for Shopify Theme Developers in 2017

Sections can be included statically in a theme’s templates (like the header and footer), or they can be dynamically added and removed, via the admin interface, on a theme’s homepage. In the above example, which we’ll go into shortly, you can see how we are able to edit a static section which will appear in the footer of the store. You’ll also notice the “Add Section” button which enables us to add dynamic sections, more on those later, to the homepage.

Section templates reside in the new sections folder and can be referenced in a similar way to snippets. If our file was located at sections/promotion.liquid we would reference it as follows:

{% section “promotion” %}

Note: you don’t need the .liquid extension as is common with snippets in Shopify themes. Let’s have a look at an example to help clarify the power of sections. The following is the contents of sections/footer.liquid:

<h1> {{ section.settings.title }} </h1>
<p> {{ section.settings.description }} </p>
 
{% schema %}
  {
    "name": "Footer Promotion",
    "settings": [
      {
        "id": "title",
        "type": "text",
        "label": "Promotion Title",
        "default": "Title"
      },
      {
        "id": "description",
        "type": "richtext",
        "label": "Add your description below",
        "default": "<p>Add your description here</p>"
      }
    ]
  }
{% endschema %}

{% stylesheet %}
{% endstylesheet %}

{% javascript %}
{% endjavascript %}

If you are familiar with Shopify theme settings some of this may look quite familiar. It comprises a mixture of HTML, Liquid placeholders and JSON similar to that found in settings_schema.json. Incidentally, the functionality of settings_schema.json still remains: sections just add an extra layer of functionality.

At the top of the template is the HTML output that I would like to be generated when the template encounters the section at render time. Inside each of the h1 and p elements are Liquid placeholders using the new {{ section.settings.[x] }} output syntax. In our examples, our section template is going to look for data corresponding to {{ section.settings.title }} and {{ section.settings.description }}.

So far nice and easy but how does Shopify know what to populate these placeholders with? This all comes down to the JSON I mentioned earlier nestled between the opening and closing {% schema %} tags.

 {
    "name": "Footer Promotion",
    "settings": [
      {
        "id": "title",
        "type": "text",
        "label": "Promotion Title",
        "default": "Title"
      },
      {
        "id": "description",
        "type": "richtext",
        "label": "Add your description below",
        "default": "<p>Add your description here</p>"
      }
    ]
  }

In order for our section to appear in the “Customise Theme” area of the store’s admin we need to give it an identifier: we do this by defining the “name” value at the top level of the JSON.

Next, we have the settings node which has, in this example, two sub-nodes. Both contain properties of id, type, label, and default. Each of these, depending on their value, will govern how the admin interface is rendered. Let’s have a look at each in turn:

id

A text string which will be used internally. It’s worth noting that whilst the IDs must be unique across a section file they do not have to be unique across all section files. As such it’s perfectly OK to have an id of title in multiple section files. Section settings also won’t conflict with settings in settings_schema.json.

type

This represents the control that will be rendered within the admin. The most commonly used options are as follows:

  • text: Single-line text fields
  • textarea: Multi-line text areas
  • richtext: A rich text editor
  • image_picker: Image uploads
  • radio: Radio buttons
  • select: Selection drop-downs
  • checkbox: Checkboxes

Some of these require additional JSON to work. For example, the select control requires options to populate it. More information on how these work, as well as other controls that you might want to consider, are available in the Shopify docs.

label

This represents the HTML label that will be generated in the admin above your control.

default

This setting allows you to add in placeholder values to the control. It’s worth noting that these are the values that will be used until the section has been updated by the store owner.

My example is pretty simple and will create two controls. The first is a single line text field that will be rendered in the h1 element in the template, the second is a rich text box which gives the options of bold, italic, and URL.

There are many other options that you can use to pimp out your store’s admin including adding bespoke controls for URLs, collection and product listings, as well as custom HTML. We won’t look at all of them in this article but I encourage you to delve into the possibilities.

You’ll also notice that you can add custom CSS and JavaScript to section files using the following Liquid tags:

{% stylesheet %}

{% endstylesheet %}
{% javascript %}

{% endjavascript %}

You might be thinking that this could add a lot of potentially bloated inline CSS and JavaScript to your theme. The good news is that Shopify concatenates all CSS and JS into a single file which is injected via the Liquid content_for_header placeholder. The platform ensures that only a single instance is ever included, even if that section is used multiple times on a page. More information about how scripts are executed is available in the Shopify docs.

Once you have set up your controls and names in the JSON file you are able to include the section in any relevant template. Sections can be added to a layout file (the outer skin of a page) or an individual template file. The Shopify admin will display the controls contextually: i.e. only when viewing the relevant template in the “customize theme” editor. Changing values will result in a real-time update in the admin: this is a great way to see how amends will affect the layout before updating and pushing live.

If you have a look at the rendered HTML you’ll notice that sections are wrapped in a div element:

<div id="shopify-section-footer" class="shopify-section">

The id of the div takes the format of shopify-section-[id] , where id is a unique id for that element for the page, and without specifying adds a class of shopify-section. You can add your own class to the div element too by specifying a class value in your settings. Here’s how it would look for our example above:

 {
    "id": "title",
    "type": "text",
    "Class": "title",
    "label": "Promotion Title",
    "default": "Title"
}

This addition would result in the following:

<div id="shopify-section-footer" class="shopify-section title">

Sections are a great addition to Shopify themes as they allow theme developers to enable contextual settings across a whole store. However, they really come into their own when working in tandem with the new blocks functionality.

3. Blocks

Blocks build on top of the sections concept and allow store owners to add multiple sections to a store’s home page. Let’s have a look at how we can make use of blocks to add the ability to add a number of promotional boxes to the home page. Here’s the example file we’ll be working with:

{% for block in section.blocks %}  
{% if block.type == "promo-box" %}
<h3>{{ block.settings.title }}</h3>
<p>{{ block.settings.description }}</p>
{% elsif block.type == "image-picker" %}
<img src="{{ block.settings.promo-image | img_url: '800x' }}" />
{% endif %}
{% endfor %}

{% schema %}
{
    "name": "Promotional Blocks",
	"max_blocks": 5,
	"presets": [
	{
		"name": "Promotional Blocks",
		"category": "Custom Homepage Content"
	}
	],
	"blocks": [
	{
		"type": "promo-box",
		"name": "Promotional Box",
		"limit": 1,
		"settings": [
		{
			"id": "title",
			"type": "text",
			"label": "Title",
			"default": "your title here"
		},
		{
			"id": "description",
			"type": "textarea",
			"label": "Description",
			"default": "your description here"
		}
		]
	},
	{
		
 		"type": "image-picker",
		"name": "Promo Image",

		"settings": [
		{
			"id": "promo-image",
			"type": "image_picker",
			"label": "Promo Image"
		
		}
		]
	}
	]
}
{% endschema %}

{% stylesheet %}
{% endstylesheet %}

{% javascript %}
{% endjavascript %}

I’ll be honest, it took me a more than a little while to get my head around how blocks work. However, once you understand how the pieces fit together it will open up a whole new set of possibilities for your theme development.

Essentially the home page can be made up of multiple sections with each section capable of containing multiple blocks. The store owner can then re-order these blocks to create a layout that best suits their needs. Let’s have a look at how this differs from the previous example to help clarify some concepts.

Firstly you’ll notice that there is a Liquid for loop at the top of the template:

{% for block in section.blocks %}  
{% if block.type == "promo-box" %}
<h3>{{ block.settings.title }}</h3>
<p>{{ block.settings.description }}</p>
{% elsif block.type == "promo-image" %}
<img src="{{ block.settings.promo-image | img_url: '800x' }}" />
{% endif %}
{% endfor %}

As these multiple elements are at the mercy of the store owner we, as theme developers, have no way of knowing what we need to output. We, therefore, need to use a Liquid loop structure, in this case a for loop, which allows us to iterate over all of the blocks present within a particular section in turn and output the relevant data.

In the snippet above you will see I am using a simple if/elsif  statement which checks for the current blocks type. We can set the type in the schema ourselves as we’ll see shortly. In this example, we use elsif to be doubly sure of the type we are checking for. If you only had two distinct block types, as we do in this example, you could just else as you know it’s the only other alternative: that said it doesn’t hurt to be more defensive.

Depending on our type a different section of HTML will be output. To output the value associated with the block we use the following syntax:

{{ block.settings.[id] }}

[id] represents the id given to that particular element in our schema which we’ll cover next.

Moving to the schema you’ll notice some familiar, and some unfamiliar, elements. Let’s begin by looking at the opening part:

"name": "Promotional Blocks",
"max_blocks": 5,
"presets": [
{
    "name": "Promotional Blocks",
    "category": "Custom Homepage Content"
}
]

Let’s have a look at each part in turn:

  • "name": "Promotional Blocks": The name that will appear for this group of controls in the Shopify admin
  • "max_blocks": 5: The total number of blocks that can appear in this section. This works in unison with each block’s limit setting which we’ll cover later. Once the maximum number of blocks has been reached you won’t be able to add any more in the admin.
  • "presets": An array of default settings for the dynamic section. In the example above we want our dynamic element to appear under the title of “Promotional Blocks” and in the category of “Custom Homepage Content”. The category value allows us to group different sections into a group in the admin.

Once we have defined the name, max_blocks, and preset values we can turn our attention to the controls we would like to appear in the admin. These are defined in the blocks section of the schema:

"blocks": [
{
    "type": "promo-box",
    "name": "Promotional Box",
    "limit": 1,
    "settings": [
    {
        "id": "title",
        "type": "text",
        "label": "Title",
        "default": "your title here"
    },
    {
        "id": "description",
        "type": "textarea",
        "label": "Description",
        "default": "your description here"
    }
    ]
},
{

    "type": "promo-image",
    "name": "Promo Image",
    "settings": [
    {
        "id": "promo-image",
        "type": "image_picker",
        "label": "Promo Image"
    }
    ]
}
]

Each block has a number of predefined values:

  • "type": A name given to this particular group of controls. This can be anything you want but ideally something self-explanatory.
  • "name": The name of this particular group of controls that you would like to appear in the admin
  • "limit": The number of times you would like this particular group of controls, i.e. this block, to appear in the section. We’ll look at this further shortly.

Once you have defined these presets you can move onto define the controls you would like to appear in the admin. These are defined in settings:

"settings": [
{
    "id": "title",
    "type": "text",
    "label": "Title",
    "default": "your title here"
},
{
    "id": "description",
    "type": "textarea",
    "label": "Description",
    "default": "your description here"
}
]

In our example, we have two potential block types that we can add to this section. The first is the block type promo-box and the second is the block type promo-image: both of which we defined ourselves.

Each block can also define its own set of settings which can consist of one or more controls. In the above example, the block of type promo-box has two controls that will appear when added to the section. The first is a text field and the second is a textarea. For some reason blocks can’t use the richtext editor we used in our previous example but a textarea will allow you to add HTML in as required. As with static sections, we must also define and id, type, label, and description.

There are a number of types available including:

  • text: Single-line text fields
  • textarea: Multi-line text areas
  • image_picker: Image uploads
  • radio: Radio buttons
  • select: Selection drop-downs
  • checkbox: Checkboxes
  • range: Range sliders

In the above example, we have also defined an image control using the image_picker value. This will allow the store owner to upload an image or pick one that has already been uploaded to the store. As this has its own type, name, and settings the image picker will appear as another option that the store owner can add to this dynamic section.

I mentioned earlier that the promo-box block has a limit value of 1. You’ll hopefully also remember that we defined the maximum number of blocks in this section to be 5. Therefore in this scenario, it’s possible to have a section consisting of:

  • 1 “promo-box” and 4 “promo-images”
  • 5 “promo-images”

Once either combination has been reached you will not be able to add additional blocks to the section unless you delete an existing block.

Once you have your template and schema ready, and any additional CSS and JavaScript, you’ll need to add one final piece of code to your theme’s index.liquid template in order to activate the block’s functionality. By adding content_for_index to index.liquid Shopify knows to include any section that has one or more presets defined. Each preset then becomes a dynamic section a merchant can then add to their theme homepage.

In the image below you will see the end result. After clicking into the admin we are able to add either our Links or Promotional Blocks to the dynamic section. In this instance I chose Promotional Blocks and am subsequently able to add additional blocks — but only Promo images as we specified a limit of 1 in our schema for the “Promotional Box” type.

What’s New for Shopify Theme Developers in 2017

It’s worth noting that not only can you reorder dynamic blocks within a section but you can also reorder the parent sections on the homepage as you see fit. One thing to remember is that there is a hard limit of 25 sections that can be added to the homepage.

Static and dynamic sections, and their subsequent blocks are a very powerful tool. It took me a while to really understand the concepts but once it clicked you start to really appreciate the potential they offer.

4. Theme Kit and Slate

One question I often get asked by first time Shopify theme developers is how best to set up a development environment to work with the platform: today there are two great options that will get you up and running.

Last year the Shopify themes team released Shopify Theme Kit. Theme Kit is a single binary command line tool (works on Windows, Linux, and macOS) which, once installed, will enable you to:

  • Upload themes to multiple environments
  • Upload and download theme assets
  • Watch for local changes and upload automatically to the Shopify platform

Theme Kit enables theme developers to work with their familiar tools (text editor, preprocessors etc) and have changes synchronized in the background to a Shopify development store. If you haven’t looked at Shopify from a theme building perspective before then you might not be aware of development stores.

Essentially they are fully featured Shopify stores with one difference: you are unable to take real payments. However, in order that you are able to demonstrate the full checkout flow to a client, you can add a “dummy payment gateway”. You can create as many development stores as you need via a free partner account. Once ready to launch you can simply upgrade the store to a paid plan, or deploy the theme to another store.

Theme Kit offers a number of useful commands that allow you to interact with themes while working in a local development environment. Once setup you can use the watch command which will start a process to monitor your directory for changes and upload them to Shopify.

What’s New for Shopify Theme Developers in 2017

Shopify can’t be truly “local” (hence the quotes) as you’ll need an internet connection to work with a development store, but the integration of Theme Kit into your workflow makes it feel “local”. Used in conjunction with tools like Prepros you can also take advantage of live reloading your development store as well as file minification and concatenation.

In 2017 Shopify also launched Slate: an open source theme scaffold and command line tool for developing Shopify themes. It is designed to assist your development workflow and speed up the process of developing, testing, and deploying themes to Shopify stores.

Whereas ThemeKit helps you in one area Slate goes much further. In addition to providing the theme sync capabilities of ThemeKit (ThemeKit is actually part of Slate) it also allows you to deploy to multiple environments at the same time, create skeleton templates for a new theme, and organize stylesheets and scripts in a flexible way.

Slate’s scaffolded templates are “intentionally blank” (home page pictured below): standard Liquid tags and logic likely to be used on each template have been included with little to no markup, classes, or other code that you will need to strip out. It’s intended as a fully functioning starting point: all you need to do is fill in the blanks and you are up and running.

What’s New for Shopify Theme Developers in 2017

Finally, there are a bunch of JavaScript and Sass helpers that you can use, or not if you need to include:

JavaScript

  • Trap focus
  • Responsive tables and videos
  • Format currency
  • Image helpers
  • Product variants
  • Cart helpers
  • Section events

CSS

  • Breakpoints and media queries
  • Grid
  • SVG icons
  • Responsive tables
  • Blank states
  • Sass mixins

5. Polaris

In May 2017 Shopify updated the look and feel of all of its applications: both on the desktop and mobile. In order to be able to achieve this ambitious goal the UX team at Shopify developed a new design system called Polaris. It’s a fully featured system that is not only intended for use internally at Shopify but also for Shopify Partners who are building interfaces for apps that integrate via the Shopify API. Its aim is to give anyone the building blocks to create interfaces that appear seamless with the core Shopify admin.

What’s New for Shopify Theme Developers in 2017

One of the main features of Polaris is the extensive component library. Each component features explanations as to the problem it’s solving, best practice recommendations, usage guidelines and example code for both HTML and React. All components are also available as a Sketch file.

The library includes components for:

  • Actions: Buttons, actions, and toggles
  • Images and icons: Badges, avatars, icons, and thumbnails
  • Feedback indicators: Banners
  • Structure: Callout cards, page layout, and empty states
  • Titles and text: Captions, display text, heading, and subheadings
  • Forms: Checkboxes, colour and date pickers, form layouts, and choice lists
  • Behaviour: Collapsible and scrollable elements
  • Lists: Description and resource lists
  • Navigation: Links, pagination, and tabs
  • Overlays: Popovers and tooltips
  • Embedded: Alerts, modals, and resource pickers

In addition to the component library, there’s extensive documentation covering the design guidelines and principles that have informed the creation on the elements. The associated style-guide also goes into detail about how the Shopify UX team think about typography, colour, and UX. There are also very useful sections dedicated to illustration and data visualisation including detailed descriptions outlining when to use default avatars and icons to how to label graphs appropriately.

Along with the component library, you and your team can use the style guide to learn about the design guidelines and principles that have guided the creation of these elements. This gives you a first-hand view of how Shopify’s user experience team thinks about design and interface development.

Polaris is intended to not only make creating interfaces for Shopify apps uicker and easier for frontend developers but to also allow you to create familiar experiences for store owners installing your app. Language is a huge element of any interface and the content guidelines include advice on how to plan the way you communicate. There are also examples that highlight how you can change your voice and tone depending on the store owner’s needs and emotions.

Polaris is an open source project and is available on GitHub. The team at Shopify are actively supporting the project and are you are able to create an issue or make a feature request.

Conclusion

We’ve covered a lot of ground in this article but hopefully, it’s given you some insights into some recent developments to the Shopify platform that will help you build better themes and apps for you and your clients.