Salvattore touts itself as a jQuery Masonry alternative
with one important difference: it uses CSS configuration instead of
JavaScript. These kinds of grids can be seen all over the web, probably
most famously on Pinterest.
Today, we will use Salvattore in combination with Twitter Bootstrap 3 to make a responsively awesome flowing grid structure.
Once this is complete, you're ready to get started with configuring Salvattore!
Next, you'll need either an external stylesheet or a
Note: you must include
You'll notice in the above markup the pattern of
For Salvattore to work properly, our grid container needs a
Next, we will go to our stylesheet and add the following labels via pseudo-elements:
The breakpoints we've chosen map directly to Bootstrap's media queries. Salvattore uses the
Salvattore takes things a step further by offering appending functionality. With these functions and a connection to an API (we're using Google's Book API to pull in books by Ernest Hemingway), we can build a dynamic grid. Here's the JavaScript we'll use:
Note: jQuery Required
First we create an
For this to work properly, we'll want to remove all of the contents in the grid holder.
Salvattore will fill in the columns for us.
Our final markup looks like this:
Today, we will use Salvattore in combination with Twitter Bootstrap 3 to make a responsively awesome flowing grid structure.
Getting started: What You'll Need
First, you'll need to grab the Salvattore JavaScript library (minified or source). Next, you'll want to link up Twitter Bootstrap's CSS. Instead of downloading and hosting our own copy, we'll borrow this directly from NetDNA's BootstrapCDN.
01
02
03
04
05
06
07
08
09
10
11
12
13
| < html > < head > < link rel = "stylesheet" src = "//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" > < title >Salvattore + Bootstrap</ title > </ head > < body > <!-- This is where the magic happens! --> < script src = "salvattore.js" ></ script > </ body > </ html > |
Next, you'll need either an external stylesheet or a
<style type='text/css'>
tag in your header. Most of our work will be done in the stylesheet.Note: you must include
type
and rel
attributes for Salvattore to work properly.A Quick Bootstrap Grid Primer
Twitter Bootstrap provides a powerful, flexible grid structure which focuses on bottom-up media queries. Let's take a look at a common row of columns.
1
2
3
4
5
6
7
8
| < div class = "row" > < div class = "col-xs-12 col-md-4" ></ div > < div class = "col-xs-6 col-sm-3 col-md-4" ></ div > < div class = "col-xs-6 col-sm-3 col-md-4" ></ div > < div class = "col-xs-12 col-sm-3 col-md-4" ></ div > < div class = "col-xs-6 col-md-4" ></ div > < div class = "col-xs-6 col-md-4" ></ div > </ div > |
col-[size]-[column number]
. With available sizes of xs
, sm
,md
, and lg
, we are able to set different column sizes for different breakpoints without writing specific media queries. Take a look at this example which shows how the columns shift at different screen widths.Bootstrap Panels
We will be creating a flowing grid using Bootstrap's panel component. The markup to create the panel is built like this:
1
2
3
4
| < div class = "panel panel-primary" > < div class = "panel-heading" >Panel heading without title</ div > < div class = "panel-body" >Panel content</ div > </ div > |
Putting it Together with Salvattore Magic
Now that we have the Bootstrap pieces we need, we're going to put it all together with Salvattore. For now, we'll start with six empty panels; later, we will make it all dynamic to give each panel some content.For Salvattore to work properly, our grid container needs a
data-columns
attribute. Here is what our markup currently looks like:
1
2
3
4
5
6
7
8
9
| < div id = "grid" data-columns> < div class = "panel panel-primary" > < div class = "panel-heading" >Panel heading without title</ div > < div class = "panel-body" > Panel content </ div > </ div > <!-- repeat the panel as many times as you'd like --> </ div > |
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
| @media screen and ( min-width : 1px ) and ( max-width : 767px ){ #columns[data-columns]::before { content : '2 .col-xs-6' ; } } @media screen and ( min-width : 768px ) and ( max-width : 991px ){ #columns[data-columns]::before { content : '3 .col-sm-4' ; } } @media screen and ( min-width : 992px ) and ( max-width : 9999px ){ #columns[data-columns]::before { content : '4 .col-md-3' ; } } |
::before
pseudo-element and content
attribute to define the classes of the columns created, and then attempts to split the elements evenly into those columns.Making it Dynamic
We've kept thing strictly within CSS so far, but if you'd like to go the extra mile, JavaScript can offer a few goodies.Salvattore takes things a step further by offering appending functionality. With these functions and a connection to an API (we're using Google's Book API to pull in books by Ernest Hemingway), we can build a dynamic grid. Here's the JavaScript we'll use:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
| function append(title, content) { // build/select our elements var grid = $( '#columns' )[0]; var item = document.createElement( 'div' ); // build the html var h = '<div class="panel panel-primary">' ; h += '<div class="panel-heading">' ; h += title; h += '</div>' ; h += '<div class="panel-body">' ; h += content; h += '</div>' ; h += '</div>' ; salvattore[ 'append_elements' ](grid, [item]) item.outerHTML = h; } $.getJSON( "https://www.googleapis.com/books/v1/volumes?q=inauthor:Ernest+Hemingway&callback=?" , function (data) { $(data.items).each( function (i, book) { append(book.volumeInfo.title, book.volumeInfo.description); }); }); |
First we create an
append
function which takes our title and content, and wraps them in our panel markup. We then use the salvattore['append_elements'](grid, [item])
function to add the item to our grid. Finally, we run the AJAX call to pull in the dynamic data.For this to work properly, we'll want to remove all of the contents in the grid holder.
1
| < div id = "grid" data-columns></ div > |
Our final markup looks like this:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
| <! DOCTYPE html> < html > < head > < link href = "//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel = "stylesheet" > < style type = "text/css" > @media screen and min-width 1px and max-width 767px { #columns[data-columns]::before { content: '2 .col-xs-6'; } } @media screen and min-width768px and max-width 991px { #columns[data-columns]::before { content: '3 .col-sm-4'; } } @media screen and min-width992px and max-width 9999px { #columns[data-columns]::before { content: '4 .col-md-3'; } } </ style > < title ></ title > </ head > < body > < div class = "container" > < h1 class = "col-xs-12" >Books by Ernest Hemingway</ h1 > < div data-columns = "" id = "columns" > < div ></ div > < div ></ div > < div ></ div > </ div > </ div > < script src = "salvattore.js" ></ script > < script > function append(title, content) { var grid = document.querySelector('#columns'); var item = document.createElement('div'); var h = '< div class = "panel panel-primary" >'; h += '< div class = "panel-heading" >'; h += title; h += '</ div >'; h += '< div class = "panel-body" >'; h += content; h += '</ div >'; h += '</ div >'; salvattore['append_elements'](grid, [item]) item.outerHTML = h; } $.getJSON("https://www.googleapis.com/books/v1/volumes?q=inauthor:Ernest+Hemingway&callback=?", function (data) { $(data.items).each(function (i, book) { append(book.volumeInfo.title, book.volumeInfo.description); }); }); </ script > </ body > </ html > |