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.
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.
Download Framer version 1.2 by clicking here.
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
Framer has three core breakpoints:
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) {}
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.
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.
<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>
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>
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>
Normally, a row is always 1200 pixels wide. Make a row completely fluid by adding the .expanded
class.
<div class="expanded row"> </div>
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>
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.
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.
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.
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.
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.
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.
Framer adopts the following file structure...
|-assets |---css |---fonts |---images |-----samples |---js |-views |---macros |---partials |---templates
Views represent the pages within your theme. A product page and a contact page are both examples of views.
Macros are modular, reusable blocks of code which accept arguments. They are useful to put often used HTML idioms into reusable elements.
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 define the anatomy of your view. Templates can also inherit other templates.
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:
Define a colour variable named color_1
with a default value #ff0000
.
... { "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 }}; }
Define a text variable named text_copyright
with a default value "Copyright © 2016. All Rights Reserved."
... { "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>
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>
Create an image gallery named sample_gallery
and display as a
carousel on your theme's homepage.
... { "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 %}
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 %}
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>
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" ... }
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 %}
Abide is a form validation library that extends the HTML5 validation API with custom validators.
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>
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 elementformvalid.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 });
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})$/
$(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>
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.
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.
Un-bulleted .no-bullet
|
|
Inline .menu
|
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>
The <textarea>
element creates a multi-line text input.
<label> What books did you read over summer break? <textarea placeholder="None"></textarea> </label>
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>
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>
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>
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.
.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>
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>
Framer offers a primary and secondary button to be used or customised as you need.
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>
Use notes as helpers on forms, or brief messages to your customers.
<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>
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>
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 |
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 |
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 |
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.
<span class="icon-bag"></span>