Build a Dynamic Grid with Salvattore and Bootstrap in 10 Minutes
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.
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.
1 |
<html>
|
2 |
<head>
|
3 |
<link rel="stylesheet" src="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css"> |
4 |
<title>Salvattore + Bootstrap</title> |
5 |
</head>
|
6 |
<body>
|
7 |
|
8 |
<!-- This is where the magic happens! -->
|
9 |
|
10 |
<script src="salvattore.js"></script> |
11 |
|
12 |
</body>
|
13 |
</html>
|
Once this is complete, you're ready to get started with configuring Salvattore!
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 |
<div class="row"> |
2 |
<div class="col-xs-12 col-md-4"></div> |
3 |
<div class="col-xs-6 col-sm-3 col-md-4"></div> |
4 |
<div class="col-xs-6 col-sm-3 col-md-4"></div> |
5 |
<div class="col-xs-12 col-sm-3 col-md-4"></div> |
6 |
<div class="col-xs-6 col-md-4"></div> |
7 |
<div class="col-xs-6 col-md-4"></div> |
8 |
</div>
|
You'll notice in the above markup the pattern of 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 |
<div class="panel panel-primary"> |
2 |
<div class="panel-heading">Panel heading without title</div> |
3 |
<div class="panel-body">Panel content</div> |
4 |
</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 |
<div id="grid" data-columns> |
2 |
<div class="panel panel-primary"> |
3 |
<div class="panel-heading">Panel heading without title</div> |
4 |
<div class="panel-body"> Panel content </div> |
5 |
</div>
|
6 |
|
7 |
<!-- repeat the panel as many times as you'd like -->
|
8 |
|
9 |
</div>
|
Next, we will go to our stylesheet and add the following labels via pseudo-elements:
1 |
@media screen and (min-width: 1px) and (max-width: 767px){ |
2 |
#columns[data-columns]::before { |
3 |
content: '2 .col-xs-6'; |
4 |
}
|
5 |
}
|
6 |
@media screen and (min-width:768px) and (max-width: 991px){ |
7 |
#columns[data-columns]::before { |
8 |
content: '3 .col-sm-4'; |
9 |
}
|
10 |
}
|
11 |
@media screen and (min-width:992px) and (max-width: 9999px){ |
12 |
#columns[data-columns]::before { |
13 |
content: '4 .col-md-3'; |
14 |
}
|
15 |
}
|
The breakpoints we've chosen map directly to Bootstrap's media queries. Salvattore uses the::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:
1 |
function append(title, content) { |
2 |
// build/select our elements
|
3 |
var grid = $('#columns')[0]; |
4 |
var item = document.createElement('div'); |
5 |
// build the html
|
6 |
var h = '<div class="panel panel-primary">'; |
7 |
h += '<div class="panel-heading">'; |
8 |
h += title; |
9 |
h += '</div>'; |
10 |
h += '<div class="panel-body">'; |
11 |
h += content; |
12 |
h += '</div>'; |
13 |
h += '</div>'; |
14 |
salvattore['append_elements'](grid, [item]) |
15 |
item.outerHTML = h; |
16 |
}
|
17 |
$.getJSON("https://www.googleapis.com/books/v1/volumes?q=inauthor:Ernest+Hemingway&callback=?", function (data) { |
18 |
$(data.items).each(function (i, book) { |
19 |
append(book.volumeInfo.title, book.volumeInfo.description); |
20 |
});
|
21 |
});
|
Note: jQuery Required
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> |
Salvattore will fill in the columns for us.
Our final markup looks like this:
1 |
<!DOCTYPE html>
|
2 |
|
3 |
<html>
|
4 |
<head>
|
5 |
<link href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet"> |
6 |
<style type="text/css"> |
7 |
@media screen and min-width 1px and max-width 767px { |
8 |
#columns[data-columns]::before { |
9 |
content: '2 .col-xs-6'; |
10 |
}
|
11 |
|
12 |
}
|
13 |
|
14 |
@media screen and min-width768px and max-width 991px { |
15 |
#columns[data-columns]::before { |
16 |
content: '3 .col-sm-4'; |
17 |
}
|
18 |
|
19 |
}
|
20 |
|
21 |
@media screen and min-width992px and max-width 9999px { |
22 |
#columns[data-columns]::before { |
23 |
content: '4 .col-md-3'; |
24 |
}
|
25 |
|
26 |
}
|
27 |
</style>
|
28 |
|
29 |
<title></title>
|
30 |
</head>
|
31 |
|
32 |
<body>
|
33 |
<div class="container"> |
34 |
<h1 class="col-xs-12">Books by Ernest Hemingway</h1> |
35 |
|
36 |
<div data-columns="" id="columns"> |
37 |
<div></div>
|
38 |
<div></div>
|
39 |
<div></div>
|
40 |
</div>
|
41 |
</div>
|
42 |
|
43 |
<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script> |
44 |
<script src="salvattore.js"></script> |
45 |
<script>
|
46 |
function append(title, content) { |
47 |
var grid = document.querySelector('#columns'); |
48 |
var item = document.createElement('div'); |
49 |
var h = '<div class="panel panel-primary">'; |
50 |
h += '<div class="panel-heading">'; |
51 |
h += title; |
52 |
h += '</div>'; |
53 |
h += '<div class="panel-body">'; |
54 |
h += content; |
55 |
h += '</div>'; |
56 |
h += '</div>'; |
57 |
salvattore['append_elements'](grid, [item]) item.outerHTML = h; |
58 |
}
|
59 |
$.getJSON("https://www.googleapis.com/books/v1/volumes?q=inauthor:Ernest+Hemingway&callback=?", function (data) { |
60 |
$(data.items).each(function (i, book) { |
61 |
append(book.volumeInfo.title, book.volumeInfo.description); |
62 |
});
|
63 |
});
|
64 |
</script>
|
65 |
</body>
|
66 |
</html>
|
Conclusion
Salvattore makes creating dynamic Masonry-style grids very easy for someone who doesn't know a lot of JavaScript. Saying that, with a small amount of JavaScript, creating dynamic grids coupled with dynamic content is a breeze. Lastly, Bootstrap provides flexible class naming structure to easily construct grids for any breakpoint.