welcome to framer.

the faster way to build a theme for shopwired

download now

1.1 What is the framer theme?

The Framer Theme has been specifically designed by ShopWired to make building a theme for a ShopWired website quick and easy.

The purpose of Framer is to provide a complete framework for a fully functional ShopWired theme to be developed. Framer provides a solid code base from which to start coding a theme, skipping all the initial theme setup and diving straight into development.

You don't have to worry about how content is rendered on a page, what the correct Twig code is or how to use it, you just need to style each page.

1.2 Who can use it?

Framer has been built with simplicity in mind.

Theme creators of any skill level or experience will be able to use it to create a theme.

1.3 What you get

  • All the required views for a comprehensive theme
  • Some basic theme settings to guide you
  • Structured data in JSON-LD format
  • A mobile first CSS grid
  • Commented code throughout
  • Full help guidance and documentation

1.4 Downloading Framer

Download Framer version 1.2 by clicking here.

1.5 Theme editing using ShopWired Theme Engine

Theme Engine is a tool that works across platforms for building themes locally. Once you download the tool you'll be able to easily setup themes on your local machine for creation and editing.

Install Theme Engine using the command shown below:

npm install -g https://s3-eu-west-1.amazonaws.com/shopwired-resources/shopwired-theme.tgz

You can run shopwired-theme for a list of commands.

For more information about ShopWired Theme Engine you can go to https://theme-engine.shopwired.co.uk

2.1 Breakpoints

Framer has three core breakpoints:

  • Small: any screen.
  • Medium: any screen 640 pixels or wider.
  • Large: any screen 1024 pixels or wider.

Many components can be modified at different screen sizes using special breakpoint classes. The grid is the most obvious example. In the code below, the left-hand column is six columns wide on small screens, hence .small-6. On medium-sized screens, the class .medium-4 overrides the small style, changing the column to be four wide.

<div class="row">
    <div class="small-6 medium-4 columns"></div>
    <div class="small-6 medium-8 columns"></div>
</div>

Use these media queries to imitate the three core breakpoints:

/* Small only */
@media screen and (max-width: 39.9375em) {}

/* Medium and up */
@media screen and (min-width: 40em) {}

/* Medium only */
@media screen and (min-width: 40em) and (max-width: 63.9375em) {}

/* Large and up */
@media screen and (min-width: 64em) {}

/* Large only */
@media screen and (min-width: 64em) and (max-width: 74.9375em) {}

2.2 The Grid

Create powerful multi-device layouts quickly and easily with the default 12-column, nestable Foundation grid. If you're familiar with grid systems, you'll feel right at home. If not, you'll learn quickly.

Basics

Start by adding an element with a class of .row. This will create a horizontal block to contain vertical columns. Then add elements with a .column class within that row. You can use .column or .columns—the only difference is grammar. Specify the widths of each column with the .small-#, .medium-#, and .large-# classes.

Framer is mobile-first. Code for small screens first, and larger devices will inherit those styles. Customise for larger screens as necessary.
<div class="row">
    <div class="small-2 large-4 columns"></div>
    <div class="small-4 large-4 columns"></div>
    <div class="small-6 large-4 columns"></div>
</div>
<div class="row">
    <div class="large-3 columns"></div>
    <div class="large-6 columns"></div>
    <div class="large-3 columns"></div>
</div>
<div class="row">
    <div class="small-6 large-2 columns"></div>
    <div class="small-6 large-8 columns"></div>
    <div class="small-12 large-2 columns"></div>
</div>
<div class="row">
    <div class="small-3 columns"></div>
    <div class="small-9 columns"></div>
</div>
<div class="row">
    <div class="large-4 columns"></div>
    <div class="large-8 columns"></div>
</div>
<div class="row">
    <div class="small-6 large-5 columns">;</div>
    <div class="small-6 large-7 columns"></div>
</div>
<div class="row">
    <div class="large-6 columns"></div>
    <div class="large-6 columns"></div>
</div>
4
4
4
3
6
3
2
8
2
3
9
4
8
5
7
6
6

Small Grids

Small grids expand to large screens easier than large grids cram into small screens.

<div class="row">
    <div class="small-2 columns">2 <span class="hide-for-small-only">columns</span></div>
    <div class="small-10 columns">10 columns</div>
</div>
<div class="row">
    <div class="small-3 columns">3 columns</div>
    <div class="small-9 columns">9 columns</div>
</div>
2 columns
10 columns
3 columns
9 columns

Medium Grid

Medium sized screens will inherit styles from small, unless you specify a different layout using the medium grid classes.

<div class="row">
    <div class="medium-2 columns">2 columns</div>
    <div class="medium-10 columns">10 columns</div>
</div>
<div class="row">
    <div class="medium-3 columns">3 columns</div>
    <div class="medium-9 columns">9 columns</div>
</div>
2 columns
10 columns
3 columns
9 columns

Fluid Row

Normally, a row is always 1200 pixels wide. Make a row completely fluid by adding the .expanded class.

<div class="expanded row">
</div>

Nesting

You can nest the grids indefinitely, though at a certain point it will get absurd.

<div class="row">
    <div class="small-8 columns">8
        <div class="row">
            <div class="small-8 columns">8 Nested
                <div class="row">
                    <div class="small-8 columns">8 Nested Again</div>
                    <div class="small-4 columns">4</div>
                </div>
            </div>
            <div class="small-4 columns">4</div>
        </div>
    </div>
    <div class="small-4 columns">4</div>
</div>
8
8 Nested
8 Nested Again
4
4
4

2.4 Helper Classes

Visibility Classes

Visibility classes let you show or hide elements based on screen size or device orientation. You can also use visibility classes to control which elements users see depending on their browsing environment.

Small
any screen
Medium
640 pixels or wider
Large
1024 pixels or wider
.show-for-medium Visible Visible
.show-for-large Visible
.show-for-small-only Visible
.show-for-medium-only Visible
.show-for-large-only Visible
.hide-for-medium Hidden Hidden
.hide-for-large Hidden
.hide-for-small-only Hidden
.hide-for-medium-only Hidden
.hide-for-large-only Hidden

And if you really just need something hidden no matter what, there are classes for that as well. The .hide and .invisible classes respectively set display: none and visibility: hidden on an element. Note that both of these classes hide content from screen readers.

Orientation Detection

This straightforward example shows how two strings of text determine whether or not an element is visible in different orientations. This will change on mobile devices when you rotate the device. On desktop, the orientation is almost always reported as landscape.

<p class="show-for-landscape">You are in landscape orientation.</p>
<p class="show-for-portrait">You are in portrait orientation.</p>

You are in landscape orientation.

You are in portrait orientation.

Accessibility

Adding display: none to an element will prevent screen readers from reading it. However, there are techniques to hide content while still making it readable by screen readers.

Show for Screen Readers Only

To visually hide content, while still allowing assistive technology to read it, add the class show-for-sr.

<p class="show-for-sr">This text can only be read by a screen reader.</p>
<p>There's a line of text above this one, you just can't see it.</p>

This text can only be read by a screen reader.

There's a line of text above this one, you just can't see it.

Hide for Screen Readers Only

To hide text from assistive technology, while still keeping it visible, add the attribute aria-hidden="true". This doesn't affect how the element looks, but screen readers will skip over it.

Basic text alignment

You can change the text alignment of an element by adding: .text-left, .text-right, .text-center or .text-justify to an element.

Adding a breakpoint to the front of a text alignment class will cause it to only be applied on that size screen or larger. For example, .medium-text-center will keep text left-aligned on the smallest screens, but switch to center-aligned on medium screens and larger.

3.1 Basic Structure

Framer adopts the following file structure...

   |-assets
   |---css
   |---fonts
   |---images
   |-----samples
   |---js
   |-views
   |---macros
   |---partials
   |---templates

Views

Views represent the pages within your theme. A product page and a contact page are both examples of views.

Macros

Macros are modular, reusable blocks of code which accept arguments. They are useful to put often used HTML idioms into reusable elements.

Partials

Partials allow you to reuse chunks of code instead of having repeated code throughout your files. A header is an example of a partial.

Templates

Templates define the anatomy of your view. Templates can also inherit other templates.

3.2 settings.json

Settings provide flexibility and eliminate hardcoded values in templates. settings.json is located in the root of the theme.

This file declares theme variables; the variables can be adjusted to fine-tune the appearance and behaviour of the theme after installation.

Theme variables can be referenced in .twig and .twig.css files.

Example usage:

Colour

Define a colour variable named color_1 with a default value #ff0000.

settings.json
...
    {
        "label": "Color 1",
        "note": "Short Help Note",
        "name": "color_1",
        "type": "color",
        "defaultValue": "#ff0000",
        "group": "Color Group 1"
    },
...
default.twig.css
header .search-form {     
    background-color: {{ settings.color_1 }}; 
}

Text Snippet

Define a text variable named text_copyright with a default value "Copyright © 2016. All Rights Reserved."

settings.json
...
    {
        "title": "Text Snippets",
        "description": "Customise the text snippets used throughout the theme",
        "resettable": true,
        "settings": [
            {
                "label": "Copyright",
                "note": "appears in the footer",
                "name": "text_copyright",
                "type": "text",
                "defaultValue": "Copyright © 2016. All Rights Reserved."
            }
        ]
    },
...
footer.twig
<footer>
    <div class="copyright"> {{ theme.text_snippet('copyright') }} </div>
</footer>

Links List

Define an unordered list containing links.

settings.json
... {
        "title": "Link Lists",
        "description": "Customise the link lists used throughout the theme",
        "settings": [
            {
                "label": "Footer",
                "name": "list_footer",
                "type": "link_list",
                "links": [
                    {
                        "url": "/terms-conditions",
                        "text": "Terms & Conditions"
                    },
                    {
                        "url": "/privacy-policy",
                        "text": "Privacy Policy"
                    },
                    {
                        "url": "/delivery",
                        "text": "Delivery Information"
                    },
                    {
                        "url": "/refund-policy",
                        "text": "Refunds & Returns"
                    }
                ]
            }
        ]
... }
footer.twig
<div class="row column footer-links">
    {{ theme.link_list('footer') }}
</div>

Gallery

Create an image gallery named sample_gallery and display as a carousel on your theme's homepage.

settings.json
... {
        "label": "Sample Gallery",
        "note": "Short Help Note",
        "name": "sample_gallery",
        "type": "gallery",
        "images": [
            {
                "file": "images/samples/banner.png",
                "text": "Optional Text",
                "url": "optional-url"
            }
        ]
... },
home.twig
{# Render carousel #}
{% set images = global.theme.settings.sample_gallery %}
{% if images %}
    <div class="row column">
        <div id="home-carousel" class="carousel">
            {% for image in images %}
                <div class="slide">
                    {% if image.target_url %}
                        <a href="{{ image.target_url }}">
                            <img src="{{ image.url('large') }}" alt="{{ image.name }}">
                        </a>
                    {% else %}
                        <img src="{{ image.url('large') }}" alt="{{ image.name }}">
                    {% endif %}
                    {% if image.name %}
                        <div class="overlay">
                            {{ image.name }}
                        </div>
                    {% endif %}
                </div>
            {% endfor %}
        </div>
    </div>
{% endif %}

Check Box

Create a custom setting controlled with a check box.

settings.json
... {
        "label": "Sample Check Box",
        "note": "Short Help Note",
        "name": "sample_checkbox",
        "type": "checkbox",
        "defaultValue": true,
        "group": "Sample Group"
... },
foo.twig
{% if global.theme.settings.sample_checkbox %}
    <p>This message will be visible when the checkbox is ticked.</p>
{% endif %}

Drop Down List

Create a custom setting controlled with a drop down list.

settings.json
... {
        "label": "Sample Drop Down",
        "note": "Short Help Note",
        "name": "sample_drop_down",
        "type": "drop_down",
        "defaultValue": "2",
        "values": {
            "1": "One",
            "2": "Two",
            "3": "Three"
        }
... },
foo.twig
<p>You selected {{ global.theme.settings.sample_drop_down }} from the dropdown list.</p>

Colour Group & Colour

Categorise colour variables into named groups.

settings.json
... {
        "label": "Color 1",
        "note": "Short Help Note",
        "name": "color_1",
        "type": "color",
        "defaultValue": "#ff0000",
        "group": "Color Group 1"
    },
    {
        "label": "Color 2",
        "note": "Short Help Note",
        "name": "color_2",
        "type": "color",
        "defaultValue": "#00ff00",
        "group": "Color Group 1"
    },
    {
        "label": "Color 3",
        "note": "Short Help Note",
        "name": "color_3",
        "type": "color",
        "defaultValue": "#0000ff",
        "group": "Color Group 2"
... }

Mailchimp

Enable mailchimp newsletter signup when a Mailchimp signup URL is entered.

settings.json
... {
        "title": "Add-Ons",
        "description": "Choose add-ons to add features to your website.",
        "advanced": true,
        "settings": [
            {
                "label": "MailChimp",
                "name": "mailchimp_action",
                "type": "text"
            },
        ...
foo.twig
{% if global.theme.settings.mailchimp_action %}
    <form action="{{ global.theme.settings.mailchimp_action }}" method="post" id="mc-embedded-subscribe-form" name="mc-embedded-subscribe-form" target="_blank" novalidate="novalidate" class="footer-form search-form">
        <div class="input-group">
            <input type="text" class="form-control" placeholder="Enter your email..." name="EMAIL">
            <div class="input-group-btn">
                <button class="btn btn-default" type="submit">
                    <span class="icon-arrow2-right"></span>
                </button>
            </div>
        </div>
    </form>
{% else %}
    <form action="/newsletter-subscribe" method="post" class="footer-form search-form">
        <div class="input-group">
            <input type="text" class="form-control" placeholder="Enter your email..." name="email">
            <div class="input-group-btn">
                <button class="btn btn-default" type="submit">
                    <span class="icon-arrow2-right"></span>
                </button>
                {{ shopwired.honeypot() }}
            </div>
        </div>
    </form>
{% endif %}

4.1 Abide

Abide is a form validation library that extends the HTML5 validation API with custom validators.

Abide Demo

These input types create a text field: text, date, datetime, datetime-local, email, month, number, password, search, tel, time, url, and week.

<form data-abide novalidate>
    <div data-abide-error class="alert callout" style="display: none;">
        <p><i class="fi-alert"></i> There are some errors in your form.</p>
    </div>
    <div class="row">
        <div class="small-12 columns">
            <label>Number Required
                <input type="text" placeholder="1234" aria-describedby="exampleHelpText" required pattern="number">
                <span class="form-error">
                    Yo, you had better fill this out, it's required.
                </span>
            </label>
            <p class="help-text" id="exampleHelpText">Here's how you use this input field!</p>
        </div>
        <div class="small-12 columns">
            <label>Nothing Required!
                <input type="text" placeholder="Use me, or don't" aria-describedby="exampleHelpTex" data-abide-ignore>
            </label>
            <p class="help-text" id="exampleHelpTex">This input is ignored by Abide using `data-abide-ignore`</p>
        </div>
        <div class="small-12 columns">
            <label>Password Required
                <input type="password" id="password" placeholder="yeti4preZ" aria-describedby="exampleHelpText" required >
                <span class="form-error">
                    I'm required!
                </span>
            </label>
            <p class="help-text" id="exampleHelpText">Enter a password please.</p>
        </div>
        <div class="small-12 columns">
            <label>Re-enter Password
                <input type="password" placeholder="yeti4preZ" aria-describedby="exampleHelpText2" required pattern="alpha_numeric" data-equalto="password">
                <span class="form-error">
                    Hey, passwords are supposed to match!
                </span>
            </label>
            <p class="help-text" id="exampleHelpText2">This field is using the `data-equalto="password"` attribute, causing it to match the password field above.</p>
        </div>
    </div>
    <div class="row">
        <div class="medium-6 columns">
            <label>URL Pattern, not required, but throws error if it doesn't match the Regular Expression for a valid URL.
                <input type="text" placeholder="http://foundation.zurb.com" pattern="url">
            </label>
        </div>
        <div class="medium-6 columns">
            <label>European Cars, Choose One, it can't be the blank option.
                <select id="select" required>
                    <option value=""></option>
                    <option value="volvo">Volvo</option>
                    <option value="saab">Saab</option>
                    <option value="mercedes">Mercedes</option>
                    <option value="audi">Audi</option>
                </select>
            </label>
        </div>
    </div>
    <div class="row">
        <fieldset class="large-6 columns">
            <legend>Choose Your Favorite, and this is required, so you have to pick one.</legend>
            <input type="radio" name="pokemon" value="Red" id="pokemonRed"><label for="pokemonRed">Red</label>
            <input type="radio" name="pokemon" value="Blue" id="pokemonBlue" required><label for="pokemonBlue">Blue</label>
            <input type="radio" name="pokemon" value="Yellow" id="pokemonYellow"><label for="pokemonYellow">Yellow</label>
        </fieldset>
        <fieldset class="large-6 columns">
            <legend>Choose Your Favorite - not required, you can leave this one blank.</legend>
            <input type="radio" name="pockets" value="Red" id="pocketsRed"><label for="pocketsRed">Red</label>
            <input type="radio" name="pockets" value="Blue" id="pocketsBlue"><label for="pocketsBlue">Blue</label>
            <input type="radio" name="pockets" value="Yellow" id="pocketsYellow"><label for="pocketsYellow">Yellow</label>
        </fieldset>
        <fieldset class="large-6 columns">
            <legend>Check these out</legend>
            <input id="checkbox1" type="checkbox"><label for="checkbox1">Checkbox 1</label>
            <input id="checkbox2" type="checkbox" required><label for="checkbox2">Checkbox 2</label>
            <input id="checkbox3" type="checkbox"><label for="checkbox3">Checkbox 3</label>
        </fieldset>
    </div>
    <div class="row">
        <fieldset class="large-6 columns">
            <button class="button" type="submit" value="Submit">Submit</button>
        </fieldset>
        <fieldset class="large-6 columns">
            <button class="button" type="reset" value="Reset">Reset</button>
        </fieldset>
    </div>
</form>

Here's how you use this input field!

This input is ignored by Abide using `data-abide-ignore`

Enter a password please.

This field is using the `data-equalto="password"` attribute, causing it to match the password field above.

Choose Your Favorite, and this is required, so you have to pick one.
Choose Your Favorite - not required, you can leave this one blank.
Check these out

Event Listener

Setup event listener after foundation is initialised (especially for formvalid/forminvalid). Easier to chain via document selector.

  • valid.zf.abide and invalid.zf.abide are field level events, triggered in validateInput function
    • ev.target is the DOM field element,
    • elem is jQuery selector for field element
  • formvalid.zf.abide and forminvalid.zf.abide are form events, triggered in validateForm function
    • ev.target is the DOM form element,
    • frm is jQuery selector for form element
$(document)
  // field element is invalid
  .on("invalid.zf.abide", function(ev,elem) {
    console.log("Field id "+ev.target.id+" is invalid");
  })
  // field element is valid
  .on("valid.zf.abide", function(ev,elem) {
    console.log("Field name "+elem.attr('name')+" is valid");
  })
  // form validation failed
  .on("forminvalid.zf.abide", function(ev,frm) {
    console.log("Form id "+ev.target.id+" is invalid");
  })
  // form validation passed, form will submit if submit event not returned false
  .on("formvalid.zf.abide", function(ev,frm) {
    console.log("Form id "+frm.attr('id')+" is valid");
    // ajax post form 
  })
  // to prevent form from submitting upon successful validation
  .on("submit", function(ev) {
    ev.preventDefault();
    console.log("Submit for form id "+ev.target.id+" intercepted");
  });
// You can bind field or form event selectively
$("#foo").on("invalid.zf.abide", function(ev,el) {
  alert("Input field foo is invalid");
});
$("#bar").on("formvalid.zf.abide", function(ev,frm) {
  alert("Form is valid, finally!");
  // do something perhaps
});

Builtin Patterns and Validators

The following patterns and validators are already built in:

alpha, alpha_numeric, card, color, cvv, date, dateISO, datetime, day_month_year, domain, email, integer, month_day_year, number, time, url

They are defined by regular expressions as you can see below. Note, that the patterns that relate to text such as alpha and alpha_numeric do not consider special characters from other languages. You need to add these special characters yourself to the regular expressions. For instance, for the German language you need to add:

alpha : /^[a-zäöüßA-ZÄÖÜ]+$/,
alpha_numeric : /^[a-zäöüßA-ZÄÖÜ0-9]+$/,

Then you need to customise the builtin patterns as explained in the next section. Otherwise Abide will produce an error if a special character is input in your text field which is validated with pattern="alpha" or pattern="alpha_numeric".

Here are the definitions of the builtin patterns:

alpha : /^[a-zA-Z]+$/,
alpha_numeric : /^[a-zA-Z0-9]+$/,
integer : /^[-+]?\d+$/,
number : /^[-+]?\d*(?:[\.\,]\d+)?$/,

// amex, visa, diners
card : /^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|6(?:011|5[0-9][0-9])[0-9]{12}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|(?:2131|1800|35\d{3})\d{11})$/,
cvv : /^([0-9]){3,4}$/,

// http://www.whatwg.org/specs/web-apps/current-work/multipage/states-of-the-type-attribute.html#valid-e-mail-address
email : /^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+$/,

url : /^(https?|ftp|file|ssh):\/\/(((([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-zA-Z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-zA-Z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-zA-Z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-zA-Z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-zA-Z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-zA-Z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/,
// abc.de
domain : /^([a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,8}$/,

datetime : /^([0-2][0-9]{3})\-([0-1][0-9])\-([0-3][0-9])T([0-5][0-9])\:([0-5][0-9])\:([0-5][0-9])(Z|([\-\+]([0-1][0-9])\:00))$/,
// YYYY-MM-DD
date : /(?:19|20)[0-9]{2}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1[0-9]|2[0-9])|(?:(?!02)(?:0[1-9]|1[0-2])-(?:30))|(?:(?:0[13578]|1[02])-31))$/,
// HH:MM:SS
time : /^(0[0-9]|1[0-9]|2[0-3])(:[0-5][0-9]){2}$/,
dateISO : /^\d{4}[\/\-]\d{1,2}[\/\-]\d{1,2}$/,
// MM/DD/YYYY
month_day_year : /^(0[1-9]|1[012])[- \/.](0[1-9]|[12][0-9]|3[01])[- \/.]\d{4}$/,
// DD/MM/YYYY
day_month_year : /^(0[1-9]|[12][0-9]|3[01])[- \/.](0[1-9]|1[012])[- \/.]\d{4}$/,

// #FFF or #FFFFFF
color : /^#?([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$/
				

Adding Custom Pattern and Validator

  • Override builtin patterns and validators before foundation is initialised
  • Add new patterns and validators before or after foundation is initialised
$(document).foundation();
Foundation.Abide.defaults.patterns['dashes_only'] = /^[0-9-]*$/;
Foundation.Abide.defaults.validators['greater_than'] =
function($el,required,parent) {
  // parameter 1 is jQuery selector
  if (!required) return true;
  var from = $('#'+$el.attr('data-greater-than')).val(),
      to = $el.val();
  return (parseInt(to) > parseInt(from));
};
<input id="phone" type="text" pattern="dashes_only" required >
<input id="min" type="number" required >
<input id="max" type="number" data-validator="greater_than" data-greater-than="min" required>

5.1 Typography

Headers and body text

Heading One

Heading Two

Heading Three

Heading Four

Heading Five
Heading Six

Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.

Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi.

Blockquotes

Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Typi non habent claritatem insitam; est usus legentis in iis qui facit eorum claritatem.

List types

Un-bulleted ul

.no-bullet
  • One
  • Two
  • Three
  • Four

Inline ul

.menu

5.2 Forms & Buttons

Text inputs

These input types create a text field: text, date, datetime, datetime-local, email, month, number, password, search, tel, time, url, and week.

<form>
  <div class="row">
    <div class="medium-6 columns">
      <label>Input Label
        <input type="text" placeholder=".medium-6.columns">
      </label>
    </div>
    <div class="medium-6 columns">
      <label>Input Label
        <input type="text" placeholder=".medium-6.columns">
      </label>
    </div>
  </div>
</form>

Text Areas

The <textarea> element creates a multi-line text input.

<label>
  What books did you read over summer break?
  <textarea placeholder="None"></textarea>
</label>      

Select Menus

Use select menus to combine many choices into one menu.

<label>Select Menu
  <select>
    <option value="husker">Husker</option>
    <option value="starbuck">Starbuck</option>
    <option value="hotdog">Hot Dog</option>
    <option value="apollo">Apollo</option>
  </select>
</label>

Add the multiple attribute to allow more than one option to be selected. Hold down the Ctrl (windows) / Command (Mac) button to select multiple options.

<label>Multiple Select Menu
  <select multiple>
    <option value="showboat">Showboat</option>
    <option value="redwing">Redwing</option>
    <option value="narcho">Narcho</option>
    <option value="hardball">Hardball</option>
  </select>
</label>

Checkboxes and Radio Buttons

Wrap a group of checkboxes or radio buttons in a <fieldset> element, and give them a common label using the <legend> element. Each individual control should also have its own label, created using a typical <label>.

<div class="row">
  <fieldset class="large-6 columns">
    <legend>Choose Your Favorite</legend>
    <input type="radio" name="pokemon" value="Red" id="pokemonRed" required><label for="pokemonRed">Red</label>
    <input type="radio" name="pokemon" value="Blue" id="pokemonBlue"><label for="pokemonBlue">Blue</label>
    <input type="radio" name="pokemon" value="Yellow" id="pokemonYellow"><label for="pokemonYellow">Yellow</label>
  </fieldset>
  <fieldset class="large-6 columns">
    <legend>Check these out</legend>
    <input id="checkbox1" type="checkbox"><label for="checkbox1">Checkbox 1</label>
    <input id="checkbox2" type="checkbox"><label for="checkbox2">Checkbox 2</label>
    <input id="checkbox3" type="checkbox"><label for="checkbox3">Checkbox 3</label>
  </fieldset>
</div>
Choose Your Favorite
Check these out

Fieldset Styles

To encourage their use as an accessibility tool, the <fieldset> element is no longer styled by default. Those styles are now contained in the .fieldset class.

<fieldset class="fieldset">
    <legend>Check these out</legend>
    <input id="checkbox12" type="checkbox"><label for="checkbox12">Checkbox 1</label>
    <input id="checkbox22" type="checkbox"><label for="checkbox22">Checkbox 2</label>
    <input id="checkbox32" type="checkbox"><label for="checkbox32">Checkbox 3</label>
</fieldset>
Check these out

Label Positioning

Sometimes you want a form with labels to the left of your inputs. You can put the label inside a different column to the left of the input. Then use the class .text-right or .float-right (or add text-align: right yourself) to realign the label.

In a right-to-left environment, use .float-left instead.

Add the .middle class to vertically align the label with its input.

<form>
    <div class="row">
        <div class="small-3 columns">
            <label for="middle-label" class="text-right middle">Label</label>
        </div>
        <div class="small-9 columns">
            <input type="text" id="middle-label" placeholder="Right- and middle-aligned text input">
        </div>
    </div>
</form>

Inline Labels and Buttons

To attach extra text or controls to the left or right of an input field, wrap the elements in an .input-group container, then add these classes to the elements inside:

  • .input-group-field on the text field.
  • .input-group-label on a text label.
  • .input-group-button on a button. Place the button inside this wrapper.
<div class="input-group">
    <span class="input-group-label">$</span>
    <input class="input-group-field" type="text">
    <div class="input-group-button">
        <input type="submit" class="button" value="Submit">
    </div>
</div>
$

Buttons

Framer offers a primary and secondary button to be used or customised as you need.

Primary Button Small Primary Button
Secondary Button Small Secondary Button
Disabled Button Small Disabled Button
Expand Button Small Expanded Expand
<!-- Primary -->
<a class="button primary" href="#">Primary Button</a>
<a class="button primary small" href="#">Small Primary Button</a>

<!-- Secondary -->
<a class="button secondary" href="#">Secondary Button</a>
<a class="button secondary small" href="#">Small Secondary Button</a>

<!-- Disabled -->
<a class="button disabled" href="#" aria-disabled>Disabled Button</a>
<a class="button disabled small" href="#" aria-disabled>Small Disabled Button</a>

<!-- Sized -->
<a class="button expanded" href="#">Expand Button</a>
<a class="button small expanded" href="#">Small Expanded Expand</a>

5.3 Messages

Use notes as helpers on forms, or brief messages to your customers.

This is a standard note
This is a success message
This is a warning message.
This is an error message.
<div class="note">
    This is a standard note
</div>

<div class="note success">
    This is a success message
</div>

<div class="note warn">
    This is a warning message.
</div>

<div class="note error">
    This is an error message.
</div>

5.4 Tables

Basics

No bells or whistles here, just a straight up table for all of your basic table needs

Table Header Table Header Table Header Table Header
Content Goes Here This is longer content Donec id elit non mi porta gravida at eget metus. Content Goes Here Content Goes Here
Content Goes Here This is longer Content Goes Here Donec id elit non mi porta gravida at eget metus. Content Goes Here Content Goes Here
Content Goes Here This is longer Content Goes Here Donec id elit non mi porta gravida at eget metus. Content Goes Here Content Goes Here
<table>
    <thead>
    <tr>
        <th width="200">Table Header</th>
        <th>Table Header</th>
        <th width="150">Table Header</th>
        <th width="150">Table Header</th>
    </tr>
    </thead>
    <tbody>
    <tr>
        <td>Content Goes Here</td>
        <td>This is longer content Donec id elit non mi porta gravida at eget metus.</td>
        <td>Content Goes Here</td>
        <td>Content Goes Here</td>
    </tr>
    <tr>
        <td>Content Goes Here</td>
        <td>This is longer Content Goes Here Donec id elit non mi porta gravida at eget metus.</td>
        <td>Content Goes Here</td>
        <td>Content Goes Here</td>
    </tr>
    <tr>
        <td>Content Goes Here</td>
        <td>This is longer Content Goes Here Donec id elit non mi porta gravida at eget metus.</td>
        <td>Content Goes Here</td>
        <td>Content Goes Here</td>
    </tr>
    </tbody>
</table>

Stripes

By default, table rows are striped. There's an unstriped. class to remove the stripes.

<table class="unstriped">
</table>
Table Header Table Header Table Header Table Header
Content Goes Here This is longer content Donec id elit non mi porta gravida at eget metus. Content Goes Here Content Goes Here
Content Goes Here This is longer Content Goes Here Donec id elit non mi porta gravida at eget metus. Content Goes Here Content Goes Here
Content Goes Here This is longer Content Goes Here Donec id elit non mi porta gravida at eget metus. Content Goes Here Content Goes Here

Stacked Tables

To stack a table on small screens, add the class .stack.

<table class="stack">
</table>
Table Header Table Header Table Header Table Header
Content Goes Here This is longer content Donec id elit non mi porta gravida at eget metus. Content Goes Here Content Goes Here
Content Goes Here This is longer Content Goes Here Donec id elit non mi porta gravida at eget metus. Content Goes Here Content Goes Here
Content Goes Here This is longer Content Goes Here Donec id elit non mi porta gravida at eget metus. Content Goes Here Content Goes Here

Scrolling Tables

Got a lot of tabular data? Add a wrapper element with the class .table-scroll around your table to enable horizontal scrolling.

<div class="table-scroll">
  <table></table>
</div>
This is the description! One Two Three Four Five Six Seven Eight Nine Ten Eleven Twelve
These are all the words that people use to describe Foundation Framer! Cool Swag Chill Killer Rad Baller OMG Sweet Awesome Beast Dope Tubular
These are some words that people use to describe other web frameworks. Whatevs Ugh. LOL K Aight Eh. Grrr... Meh. TTYL Bleh. Really? Why?
Here are some great super heros. Batman Superman Spiderman Wonder Woman Hulk Nicolas Cage Antman Aquaman Captain America Wolverine Thor Iron Man
Here's a footer, just in case

5.5 Icons

Framer offers a basic icon font for social and payment icons. Import assets/fonts/icons.json into Fontello to make any changes to the set.

Payment Icons

Social Icons

General Icons

Usage

<span class="icon-bag"></span>