# Coding Guidelines
# CSS
=====================================================================
## CSS 1
Avoid using more than 2 levels of nesting
#### Don't
```
.selector {
.level-2 {
.level-3 {
.child-1 {}
.child-2 {}
}
}
}
```
#### Do
```
.selector {
.level-3 .child-1 {}
.level-3 .child-2 {}
}
```
=====================================================================
=====================================================================
## CSS 2
Use nested media queries
#### Don't
```
.selctor1 {}
.selctor2 {}
.selctor3 {}
@media (max-width) {
.selctor1 {}
.selctor2 {}
.selctor3 {}
}
```
#### Do
```
.selctor1 {
@media (max-width) {}
}
.selctor2 {
@media (max-width) {}
}
.selctor3 {
@media (max-width) {}
}
```
=====================================================================
=====================================================================
## CSS 3
Group rules by meaning i.e. fonts, colors, size, position
#### Don't
```
.selector {
position: absolute;
font-size: 14px;
background-color: red;
height: 50%;
top: 50%;
line-height: 1.3;
left: 50%;
color: blue;
width: 50;
}
```
#### Do
```
.selector {
width: 50%;
height: 50%;
position: absolute;
top: 50%;
left: 50%;
font-size: 14px;
line-height: 1.3
color: blue;
background-color: red;
}
```
=====================================================================
=====================================================================
## CSS 4
Use shorthand rules
#### Don't
```
.selector {
padding-top: 10px;
padding-right: 20px;
padding-bottom: 50px;
padding-left: 10px;
}
```
#### Do
```
.selector {
.padding: 10px 20px 50px 10px;
}
```
=====================================================================
=====================================================================
## CSS 5
Use hex instead of rgb
#### Don't
```
.selector {
.color: rgb(255, 255, 255);
}
```
#### Do
```
.selector {
.color: #000
}
```
=====================================================================
=====================================================================
## CSS 6
Comma separated selectors on new lines
#### Don't
```
.selector1, .selecto2, .selector3, .selector4 {}
```
#### Do
```
.selector1,
.selecto2,
.selector3,
.selector4 {}
```
=====================================================================
=====================================================================
## CSS 7
Use global or local variables to avoid repetition
#### Don't
```
.selector1 {
color: #1e1e1e;
}
.selector2 {
color: #1e1e1e;
}
.selector3 {
color: #1e1e1e;
}
```
#### Do
```
$formLabelGray: '#1e1e1e';
.selector1 {
color: formLabelGray;
}
.selector2 {
color: formLabelGray;
}
.selector3 {
color: formLabelGray;
}
```
=====================================================================
=====================================================================
## CSS 8
Use single quotes
#### Don't
```
.selector1 {
background-image: url("path-to-file")
}
```
#### Do
```
.selector1 {
background-image: url('path-to-file')
}
```
=====================================================================
=====================================================================
## CSS 9
Use stateful selectors
#### Don't
```
.active {}
.clicked {}
.hidden {}
```
#### Do
```
.is-active {}
.is-clicked {}
.is-hidden {}
```
=====================================================================
=====================================================================
## CSS 10
Add trailing semicollons
#### Don't
```
.selector {
color: red;
background-color: blue;
display: block
}
```
#### Do
```
.selector {
color: red;
background-color: blue;
display: block;
}
```
=====================================================================
# Liquid
=====================================================================
## Liquid 1
Use {% render %} instead of {% include %}
#### Don't
```
{% include 'icon-misc', icon: 'search', colour: 'red' %}
```
#### Do
```
{% render 'icon-misc' with icon: 'search', colour: 'red' %}
```
=====================================================================
=====================================================================
## Liquid 2
Break to multiple lines when snippets have more than 2 params or the whole snippet goes over 80 characters
#### Don't
```
{% render 'social-sharing' with share_title: product.title, share_permalink: product.url,
share_image: product.featured_image %}
```
#### Do
```
{% render 'social-sharing' with
share_image: product.featured_image,
share_permalink: product.url,
share_title: product.title,
%}
```
=====================================================================
=====================================================================
## Liquid 3
Use {% break %} and {% continue %} to exit out of a loop iteration early and to break out of the loop
```
{% for tag in product.tags %}
{% if tag != 'value' %}
{% continue %}
{% endif %}
{% render 'tag-snippet' %}
{% break %}
{% endfor %}
```
=====================================================================
=====================================================================
## Liquid 4
Add how-to-use comments for liquid snippets at the top of the file
```
{% comment %}
Usage: In your liquid template file, copy the following line
- {% render 'responsive-image' with image: featured_image, image_class: "css-class", wrapp
er_class: "wrapper-css-class", max_width: 700, max_height: 800 %}
{% endcomment %}
```
=====================================================================
=====================================================================
## Liquid 5
- In areas where the client can customize the content, do not assume that they will want to display every part of a section's settings
- Wrap each setting in a {% if %} to hide it if no content is entered
- Use != '' rather than {% if condition %} or != blank as it is more reliable, it is possible for a setting to exist if it previously had a value
- When testing make sure the section does not appear visually broken, the client will expect it to work with missing settings
#### Don't
```
{% for block in section.blocks %}
{% assign _block = block.settings %}
<div class="block">
<img src="{{ _block.image | img_url: '2000x' }}" alt="{{ _block.image.alt }}">
<h2 class="block__title">{{ _block.title }}</h2>
<div class="block__text rte">{{ _block.text }}</div>
<a class="block__button" href="{{ _block.button_url }}">
{{ _block.button_text }}
</a>
</div>
{% endfor %}
```
#### Do
```
{% for block in section.blocks %}
{% assign _block = block.settings %}
<div class="block">
{% if _block.image != '' %}
<img
alt="{{ _block.image.alt }}"
src="{{ _block.image | img_url: '2000x' }}"
>
{% endif %}
{% if _block.title != '' %}
<h2 class="block__title">{{ _block.title }}</h2>
{% endif %}
{% if _block.text != '' %}
<div class="block__text rte">
{{ _block.text }}
</div>
{% endif %}
{% if _block.button url != '' and _block.button_text != '' %}
<a class="block__button" href="{{ _block.button_url }}">
{{ _block.button_text }}
</a>
{% endif %}
</div>
{% endfor %}
```
=====================================================================
=====================================================================
## Liquid 6
Don't use variable names that are already allocated in Shopify
#### Don't
```
{% assign section = section.settings %}
```
#### Do
```
{% assign _section = section.settings %}
```
=====================================================================
=====================================================================
## Liquid 7
Hoist settings variables in _section and _block
#### Don't
```
{% if section.settings.main_image != blank %}
<img src="{{- section.settings.main_image.src -}}" alt="{{- section.settings.main_image.alt -}}">
{% endif %}
```
#### Do
```
{% assign _section = section.settings %}
{% assign main_image = _section.main_image %}
{% assign section_title = _section.title %}
{% if main_image != blank %}
<img src="{{- main_image.src -}}" alt="{{- main_image.alt -}}">
{% endif %}
```
=====================================================================
=====================================================================
## Liquid 8
Don't use multiple inline if statements
#### Don't
```
<div class="row {% if section.settings.width == 'full' or section.settings.display == 'ful
l' %}row--full-width{% endif %} {% if is_hidden %}is-hidden{% endif %}"></div>
```
#### Do
```
{% if section.settings.width == 'full' or section.settings.display == 'full' %}
{% assign row_class = 'row--full-width' %}
{% endif %}
<div
class="
row
{{ row_class }}
{% if is_hidden %}is-hidden{% endif %}
"
>
<!-- Content -->
</div>
```
=====================================================================
=====================================================================
## Liquid 9
Use proper indenting for nested code
#### Don't
```
{% if variable %}
<h1>{{ product.title }}</h1>
{% endif %}
```
#### Do
```
{% if variable %}
<h1>{{ product.title }}</h1>
{% endif %}
```
=====================================================================
=====================================================================
## Liquid 10
Spacing and line character limits
- Add spaces inside each object and tag
- Add spaces around filters
- Separate blocks of Liquid code with a newline
- Opening {% if %} tags should be on separate lines
- {% if %} tags with more than two filters and exceeding 80 characters should be split
onto multiple lines
- {% assign %} tags with more than two filters and exceeding 80 characters should be
broken up over multiple lines and indented
- Once you are writing something over multiple lines, each line should only have one
attribute or value on it
#### Don't
```
{% if template contains 'search' or template contains 'account' or template contains 'cust
omer' or template contains 'cart' %}<meta name="robots" content="noindex, nofollow">{% end
if %}
{% assign sanitized_var = string|downcase|split: '/'|last|remove:'<p>'|remove:'</p>'|money
_with_currency %}
{%if variable%}<h1 class="product__title">{{ product.title }}</h1>
<div class="product__price product__price--large money subtitle-1">{{ product.price | mo
ney }}</div>{% else %}<h2 class="product__title">{{ product.title }}</h2>{%endif%}
```
#### Do
```
{% if
template contains 'search' or
template contains 'account' or
template contains 'customer' or
template contains 'cart'
%}
<meta content="noindex, nofollow" name="robots">
{% endif %}
{% assign sanitized_variable = string |
downcase |
split: '/' |
last |
remove:'<p>' |
remove:'</p>' %} |
money_with_currency
%}
{% if variable %}
<h1 class="product__title">{{ product.title }}</h1>
<div
class="
product__price
product__price--large
money
subtitle-1
"
>
{{ product.price | money }}
</div>
{% else %}
<h2 class="product__title">{{ product.title }}</h2>
{% endif %}
```
=====================================================================
# Javascript
=====================================================================
## JS 1
Write explicit code
#### Don't
```
// implicitly convert to integer
const dataIndex = +item.dataset.index;
```
#### Do
```
// explicitly convert to integer
const dataIndex = parseInt(item.dataset.index);
```
=====================================================================
=====================================================================
## JS 2
Add comments even on simple pieces of code
#### Don't
```
function sumTwoIntegers(a, b) {
return a + b;
}
```
#### Do
```
/**
* Return the sum of two integers
* @param {Integer} a
* @param {Integer} b
* @returns Integer
*/
function sumTwoIntegers(a, b) {
return a + b;
}
```
=====================================================================
=====================================================================
## JS 3
Use full name variables
#### Don't
```
const accPass = '...';
```
#### Do
```
const accountPassword = '...';
```
=====================================================================
=====================================================================
## JS 4
Always null check
#### Don't
```
const item = document.querySelector(selector);
item.classList.add('class');
```
#### Do
```
const item = document.querySelector(selector);
if (item !== null) {
item.classList.add('class');
}
```
=====================================================================
=====================================================================
## JS 5
Hoist variables at the top of a js module
#### Don't
```
const var1 = '';
function useVar1() {
return var1;
}
const var2 = '';
function useVar2() {
return var2;
}
const var3 = '';
function useVar3() {
return var3;
}
```
#### Do
```
const var1 = '';
const var2 = '';
const var3 = '';
function useVar1() {
return var1;
}
function useVar1() {
return var2;
}
function useVar1() {
return var3;
}
```
=====================================================================
=====================================================================
## JS 6
Define long conditions as variables
#### Don't
```
if (window.width > 767 && window.height > 600 && window.scrollY > section.offset.top) {
...
}
```
#### Do
```
const isDevice = window.width > 767 && window.height > 600;
const isSectionInView = window.scrollY > section.offset.top;
if (isDevice && isSectionInView) {
...
}
```
=====================================================================
=====================================================================
## JS 7
Always leave trailing commas
#### Don't
```
const object = {
prop: 'value',
prop2: 'value2',
prop3: 'value3'
}
```
#### Do
```
const object = {
prop: 'value',
prop2: 'value2',
prop3: 'value3',
}
```
=====================================================================
=====================================================================
## JS 8
Use arrow functions whenever it's possible and makes sense to do so
#### Do
```
array.map(item => {
...
})
const sumTwoIntegers = (a, b) => {
return a + b;
}
```
=====================================================================
=====================================================================
## JS 9
Use stateful naming for stateful variables
#### Don't
```
const mobile = window.width < 767;
const children = item.children.length;
```
#### Do
```
const isMobile = window.width < 767;
const hasChildren = item.children.length;
```
=====================================================================
=====================================================================
## JS 10
Brake multiple methods on their own line
#### Don't
```
array.map(item => item.props).sort().reverse();
```
#### Do
```
array
.map(item => item.props)
.sort()
.reverse();
```
=====================================================================