These rules apply to all Liquid, HTML, and Vue <template>
code.
See also Vue's style guide.
- Attributes
- Characters
- Commenting
<div>
or<span>
- Indenting
- Spacing & line character limits
- Self-closing element
- Vue render tags
- The general rule is if the attribute is to do with CSS then you use kebab-case for the value
- If the attribute is for JavaScript then use camelCase in the value
- kebab-case
id
class
for
- camelCase
v-
bind- Vue
@
events data-
js-
selector values
{% # Liquid file %}
<input id="NewsletterModal-Email" class="newsletter-modal__textarea" autocapitalize="off" autocomplete="newsletter-address" autocorrect="off" name="contact[email]" placeholder="{{ 'general.newsletter_form.email_placeholder' | t }}" type="email" value="{{ customer.email }}" aria-labelledby="NewsletterModal-EmailLabel" data-show="true" js-newsletter="email">
{% # Liquid file %}
<input
id="newsletter-modal-email"
class="newsletter-modal__textarea"
autocapitalize="off"
autocomplete="newsletter-address"
autocorrect="off"
name="contact[email]"
placeholder="{{ 'general.newsletter_form.email_placeholder' | t }}"
type="email"
value="{{ customer.email }}"
aria-labelledby="newsletter-modal-email-label"
data-show="true"
js-newsletter="email"
>
- When an element has more than one attribute then each attribute should be on its own line
- Attributes should follow this order:
is
v-for
v-if
/v-else-if
/v-else
v-show
v-cloak
id
ref
key
v-model
class
- { native }
aria-
data-
js-
@event
v-html
/v-text
- { native } covers everything else, items within { native } should be in alphabetical order
- This makes it easier for managing merges in Git
- Make sure you trim trailing spaces after each line
- See also spacing & line character limits
Be sure to follow the formatting; the trailing
>
should be on a newline with the attributes indented in two spaces.
<div class='foo'></div>
<div class="foo"></div>
- Use double quotations
"
in HTML elements, not apostrophes/single quotations'
- Note that you should use single quotations in Liquid tags and filters
<div>
and <span>
are often used interchangeably but there are specific use cases for each:
- If the content is going to be displayed inline, use
<span>
- If you want the element to display block, on its own line, use
<div>
- If you're using CSS to change its
display
property, consider using the other
<p class="body-1">
{{ product.description }}
</p>
<p class="body-1">
{{ product.description }}
</p>
- Indent two spaces inside each opening HTML element
{% # Liquid file %}
<div id="Product" class="product" data-id="{{ product.id }}" js-product="container">
<h1 class="product__title">{{ product.title }}</h1>
<h2 class="product__subtitle">{{ product.type }}</h2>
<button class="product__button product-button"><span class="product-button__icon">{% render 'icon-misc' with icon: 'plus' %}</span><span class="product-button__text">{{ 'products.product.add_to_cart' | t }}</span></button>
<div class="product__content product-content">
<p class="product-content__description">{{ product.description }}</p>
<p class="product-content__shipping">{{ pages['shipping'].content | strip_html }}</p>
</div>
<div class="footer"><div class="footer__inner"><span class="footer__copy">{{ 'footer.copyright' | t }}</span><span class="footer__name">{{ shop.name }}</span><img src="{{ settings.logo | img_url: '300x' }}" alt="{{ settings.logo.alt }}"></div></div>
</div>
{% # Liquid file %}
<div
id="Product"
class="product"
data-id="{{ product.id }}"
js-product="container"
>
<h1 class="product__title">{{ product.title }}</h1>
<h2 class="product__subtitle">{{ product.type }}</h2>
<button class="product__button product-button">
<span class="product-button__icon">
{% render 'icon-misc' with icon: 'plus' %}
</span>
<span class="product-button__text">
{{ 'products.product.add_to_cart' | t }}
</span>
</button>
<div class="product__content product-content">
<p class="product-content__description">
{{ product.description }}
</p>
<div class="product-content__shipping">
{{ pages['shipping'].content }}
</div>
</div>
<div class="footer">
<div class="footer__inner">
<span class="footer__copy">{{ 'footer.copyright' | t }}</span>
<span class="footer__name">{{ shop.name }}</span>
<img
alt="{{ settings.logo.alt }}"
src="{{ settings.logo | img_url: '300x' }}"
>
</div>
</div>
</div>
- Use common sense spacing to improve the readability of your code
- Block-level elements should open onto a new line and indent
- Inline-level elements should be written on a single line
- Single line elements should be grouped together by type
- Multi-line elements should have a newline between them
- This guideline includes empty block-level elements, e.g. the following is correct:
{% # Liquid file %}
<div
class="article__image"
data-bgset="{% render 'responsive-bg-image' with image: article.image %}"
js-article="image"
></div>
- Once you are writing something over multiple lines, each line should only have one attribute or value on it
- If an attribute's value exceeds 80 characters then it too should be split in the following format:
{% # Liquid file %}
<div
class="
class-1
class-2
class-3
class-4
"
data-handle="{{ product.handle }}"
js-product="content"
>
{% # Content %}
</div>
- Short block-level elements like
<h1>
,<li>
or<title>
can be displayed on a single line unless they're greater than 80 characters long - Inline-level elements greater than 80 characters long should follow multi-line rules
{% # Liquid file %}
<component-handle />
<img
alt=""
src="{{ 'image.png' | file_url: '200x' }}"
/>
<input
class="foo"
placeholder="Content"
type="text"
/>
{% # Liquid file %}
<component-handle></component-handle>
<img
alt=""
src="{{ 'image.png' | file_url: '200x' }}"
>
<input
class="foo"
placeholder="Content"
type="text"
>
- Vue custom elements in Liquid files should not use a self-closing tag as this is invalid and causes errors
- The
/
in self-closing tags is obsolete in most HTML elements, do not use it
- Inside a Vue
<template>
tag you should use self-closing tags for elements which don't normally self-close:
<!-- .vue file -->
<h1
class="main-product__title"
v-html="product.title"
/>
<!-- .vue file -->
<h1 class="main-product__title">
{{ product.title }}
</h1>
<!-- .vue file -->
<h1
class="main-product__title"
v-html="product.title"
/>
- Use
v-html
orv-text
to render content in an element instead of using the template render tags