CSS examples

Breakpoints

Defining values and names in Sass makes it possible to use breakpoints in a variety of situations. These are the default values.

$grid-medium: 750px;
$grid-large: 990px;
$grid-widescreen: 1400px;
$grid-gutter: 30px; // spacing between grid elements

$small: 'small';
$medium: 'medium';
$medium-down: 'medium-down';
$medium-up: 'medium-up';
$large: 'large';
$large-down: 'large-down';
$large-up: 'large-up';
$widescreen: 'widescreen';

Breakpoint values and names are declared in styles/settings/variables.scss.liquid

Media query mixin

Pass a media query name (above) to the media query mixin to generate media queries in your stylesheet with ease.

Example 1

Define an element’s background to pink above our large breakpoint value.

@include media-query($medium-up) {
  .foo {
    background: pink;
  }
}

Output:
@media screen and (min-width: 750px) {
  .foo {
    background: pink;
  }
}

Example 2

Define an element’s background to blue, unless between the medium and large breakpoint values.

.foo {
  background: blue;

  @include media-query($medium) {
    background: pink;
  }
}

Output:
.foo {
  background: blue;
}

@media screen and (min-width: 750px) and (max-width: 989px) {
  .foo {
    background: pink;
  }
}

Grid

A grid as versatile as Slate’s (based on csswizardry-grids) can generate a lot of code, so the flexibility of only adding what is needed is helpful in keeping the file size down. Grid size classes for $small and $medium-up are generated by default.

$breakpoint-has-widths: ($small, $medium-up);

Each column — or .grid__item — should be a direct child of a .grid container. Create the child element sizes with the format breakpoint-name--one-tenth. See the example below or look through styles/global/grid.scss for available sizes. Ideally you should not style the padding or margins of grid or grid__item classes directly or the layout may break.

No grid classes exist in the provided templates, meaning you can swap grid.scss from your own grid in theme.scss without a lot of cleanup necessary.

<div class="grid">
  <div class="grid__item">
    1
  </div>
  <div class="grid__item">
    <div class="grid">
      <div class="grid__item medium-up--one-half">
        2.1
      </div>
      <div class="grid__item medium-up--one-quarter">
        2.2
      </div>
      <div class="grid__item medium-up--one-quarter">
        2.3
      </div>
      <div class="grid__item medium-up--one-third">
        2.4
      </div>
      <div class="grid__item medium-up--one-third small--one-half">
        2.5
      </div>
      <div class="grid__item medium-up--one-third small--one-half">
        2.6
      </div>
    </div>
  </div>
  <div class="grid__item">
    <div class="grid">
      <div class="grid__item medium-up--one-twelfth one-sixth small--one-third">
        3.1
      </div>
      <div class="grid__item medium-up--one-twelfth one-sixth small--one-third">
        3.2
      </div>
      <div class="grid__item medium-up--one-twelfth one-sixth small--one-third">
        3.3
      </div>
      <div class="grid__item medium-up--one-twelfth one-sixth small--one-third">
        3.4
      </div>
      <div class="grid__item medium-up--one-twelfth one-sixth small--one-third">
        3.5
      </div>
      <div class="grid__item medium-up--one-twelfth one-sixth small--one-third">
        3.6
      </div>
      <div class="grid__item medium-up--one-half one-whole">
        3.7
      </div>
    </div>
  </div>
</div>

Grid push classes

Add push classes by adding the breakpoint name to $breakpoint-has-push in variables.scss.liquid. For this example, push classes for $medium-up have been added. By default, no push classes are generated.

$breakpoint-has-push: ($medium-up);
<div class="grid">
  <div class="grid__item medium-up--one-quarter medium-up--push-one-quarter">
    1
  </div>
  <div class="grid__item medium-up--one-quarter medium-up--push-one-half">
    1.1
  </div>
</div>

SVG icons

Slate uses SVG icons for easy maintainability. Place your SVG icons in src/icons, preface the filename with the name icon-. E.g. icon-cart.svg, and the icons will become available for use as snippets in your theme.

Note: your SVG must use the case sensitive viewBox property otherwise it will not be compiled properly

Usage in Liquid:

{% include 'icon-cart' %}

Style it with CSS. All icons will have an .icon class added along with its filename.

.icon-cart {
  fill: blue;
}

Below is a list of all available icons and their respective names.

It is recommended to set descriptive text that also acts as a fallback for icons. See the demo for visually hiding text and icon fallback text.

Update icons manually

If you need to add an icon to a live shop without Slate’s build tools, follow these steps:

  1. Create an SVG icon.
  2. Change the file from an .svg extension to .liquid and place it in snippets/. Make sure the file name starts with icon- for consistency.
  3. Add aria-hidden="true", focusable="false", and role=”presentation” to the svg element
  4. Add class="icon" to the svg element.
  5. Add a class the same name as the file name to the svg. E.g. icon-cart
  6. Remove any unneeded elements like DOCTYPE and <?xml>.
  7. Include your new icon with {% include 'icon-cart' %}.

Responsive tables

For proper accessibility, tabular data should be built as a table. Tables are notoriously difficult to build responsively, and while there are a lot of ways to do it, Slate includes a basic approach of adding the column labels as data attributes. Test the demo below in mobile mode to see it in action.

Responsive tables are built into cart.liquid, customers/order.liquid, and customers/account.liquid templates.

<table class="responsive-table">
  <thead class="small--hide">
    <tr>
      <th colspan="2">Product</th>
      <th>Price</th>
      <th>Quantity</th>
      <th>Total</th>
    </tr>
  </thead>
  <tbody>
    <tr class="responsive-table-row">
      <td data-label="Product">
        <a href="#">
          Product image
        </a>
      </td>
      <td>
        <a href="#">Product title</a>
        <a href="#">
          <small>Remove</small>
        </a>
      </td>
      <td data-label="Price">
        $25.99
      </td>
      <td data-label="Quantity">
        <input type="number"
               name="updates[]"
               id="updates_key"
               value="1"
               min="0"
               aria-label="Quantity">
      </td>
      <td data-label="Total">
        $25.99
      </td>
    </tr>
    <tr class="responsive-table-row">
      <td data-label="Product">
        <a href="#">
          Product image
        </a>
      </td>
      <td>
        <a href="#">Product title</a>

        <a href="#">
          <small>Remove</small>
        </a>
      </td>
      <td data-label="Price">
        $19.99
      </td>
      <td data-label="Quantity">
        <input type="number"
               name="updates[]"
               id="updates_key"
               value="2"
               min="0"
               aria-label="Quantity">
      </td>
      <td data-label="Total">
        $39.98
      </td>
    </tr>
  </tbody>
</table>

Blank states

It is important to show off some of your theme’s layouts and features on a fresh install, but you don’t always have shop information available to use as defaults (yet… stay tuned on that one). Global SVGs have been made available to use as dummy content until the merchant is ready to customize the layouts.

There are 6 product, 6 collection, 2 lifestyle, 1 logo, and 1 generic image available to be used. These are their filenames — replace the x with a number:

- image.svg
- logo.svg
- collection-x.svg
- product-x.svg
- lifestyle-x.svg

styles/global/blank-states.scss uses your theme colors to style the SVGs with your theme.

// Show dummy products
{% for i in (1..3) %}
  <a href="#">
    {% capture current %}{% cycle 1, 2, 3, 4, 5, 6 %}{% endcapture %}
    {{ 'product-' | append: current | placeholder_svg_tag: 'placeholder-svg' }}
    Example product title
  </a>
{% endfor %}

// Show a lifestyle image if the image setting is not set
{% if section.settings.image == blank %}
  {{ 'lifestyle-1' placeholder_svg_tag: 'placeholder-svg' }}
{% else %}
  {{ section.settings.image | img_tag }}
{% endif %}

Sass mixins

Prefix

Based on Bourbon, generate specific prefixes as needed.

* {
  @include prefix(box-sizing, border-box, webkit moz spec);
}

Output:
* {
  -moz-box-sizing: border-box;
  -webkit-box-sizing: border-box;
  box-sizing: border-box;
}

Text alignment per breakpoint

Change the text alignment based on breakpoint. Only breakpoints that have a width enabled will generate text alignment classes.

<div class="medium-up--text-right small--text-center">
  Lorem ipsum dolor sit amet, consectetur adipiscing elit. In erat mauris, faucibus quis pharetra sit amet, pretium ac libero. Etiam vehicula eleifend bibendum. Morbi gravida metus ut sapien condimentum sodales.
</div>

Visibility per breakpoint

Quickly show or hide content based on enabled breakpoints with the class breakpoint-name--hide or breakpoint-name--show. Only breakpoints that have a width enabled will generate show and hide classes.

<div class="medium-up--hide">This red div is only visible below the medium breakpoint</div>
<div class="small--hide">This green div is not visible on the small breakpoint</div>
<div class="medium-up--show" style="display: none;">Even with display none set, this blue div will appear above the large breakpoint.</div>

Visually hide

Sometimes it is necessary to visually hide content while keeping it accessible in the DOM. This is useful for hiding descriptive text for icons or form labels that you do not want shown. Screen readers, for example, do not read placeholder text on inputs as their label so the label element is required.

// Visually hidden text
<label for="test" class="visually-hidden">Email</label>
<input type="email" name="test" id="test" placeholder="Email">

// Visually hidden icon fallback text
{% include 'icon-cart' %}
<span class="icon-fallback-text">Cart icon</span>