Now, let's style our filtering options. These appear just before the markup for our product items. In small, medium, and large viewports, they appear as a left-hand sidebar.
At the moment, they appear like the following screenshot:
For our final design, we want to transform the Clearance Sale link into an attractive extra-large button and arrange the filtering options into two columns with checkboxes rather than bullets, as shown in the following screenshot:
Let's begin by setting up some basic styles to lay a basic groundwork.
We'll start by adjusting fonts, colors, margins, and padding.
Let's add these rules to _prod
ucts-grid.less
:
.grid-options { .panel; .panel-default; padding-top: 12px; padding-bottom: 24px; > h2 { margin-top: 0; font-size: 1.5 * (@font-size-large); line-height: 1.2; color: @gray-dark; } }
The preceding code does the following:
h2
headingNext, we will style the Clearance Sale link.
We want to transform our Clearance Sale link into an extra-large attractive button.
Let's adjust the markup to do the following:
btn-feature
class, which we created in Chapter 4, Bootstrappin' Business, to give the button our special featured color—red.icon-3x
class.For more information about Font Awesome's special sizing classes, see the documentation at http://fontawesome.io/examples/#larger.
The resulting markup is as follows:
<a class="btn btn-feature choose-clearance" href="#"> <span class="icon fa fa-tag fa-3x"></span> <h3>Clearance Sale</h3> <p>View clearance items</p> </a>
This immediately gives us a good start towards our desired result as shown in the following screenshot:
Now to polish it up, perform the following steps:
.center-block()
Bootstrap mixin.white-space:
nowrap
rule for buttons, so that our text can wrap as it should (See Bootstrap's white-space
rule in less/bootstrap/buttons.less
. You can learn more about the white-space
property at http://css-tricks.com/almanac/properties/w/whitespace/ ).We can accomplish these goals by adding the following style rules:
.choose-clearance { .center-block(); width: 92.5%; padding-top: 20px; padding-bottom: 12px; white-space: normal; position: relative; h3 { font-weight: normal; color: #fff; padding-top: 4px; margin: 6px; } p { margin: 6px 20px; line-height: 1.2; } .icon { position: absolute; top: 0; right: 2px; } }
This gives us a pleasing result as is evident from the following screenshot:
As a bonus, these styles work well across viewport sizes. Take a few moments to test it. Then of course, as always, feel free to take what we've begun and beautify it further.
Meanwhile, let's move down to the options for filtering our products.
In this section, we will transform our lists of product filtering options.
If you take a moment to examine the markup of product filtering options in a store such as Amazon (http://www.amazon.com) or Zappos (http://www.zappos.com), you'll find that they are composed lists of links that have been specially styled to appear like checkboxes. We will style our links to look like checkboxes, which will appear as checked once selected, and we'll adjust them to work nicely across devices, such as tablet and phone devices.
On e-commerce websites such as Amazon and Zappos.com, the filter options are connected to a content management system, which dynamically updates the grid of shown products in response to the options selected. Bootstrap is a frontend design framework, and not a content management system. Thus, we will not be dynamically filtering our products as a part of this project. Instead, we will prepare a design that is ready to be used in the context of a complete content management system.
We'll start with the h3
headings for the lists, adjusting their size, line-height, margin, and color:
.grid-options { > h3 { font-size: @font-size-large; line-height: 1.2; margin-top: 12px; color: @gray-dark; } }
Now, let's turn our attention to the unordered lists. These have a special class of options-list
, which we'll use as our selector to ensure we're targeting only these special lists.
First, let's remove bullets and padding:
.grid-options { .. .options-list { list-style-type: none; padding-left: 0; }
Now we'll style the links. Shortly, we'll also style the list items, so we'll include them in the sequence of nested selectors.
... li { a { .btn; .btn-sm; padding-left: 0; padding-right: 0; color: @gray; } &:hover, &:focus, &:active, .active & { color: @link-color; } }
The rules we just set accomplish the following:
.btn
class that includes displaying the inline-block
link and the addition of padding:.btn-sm
class to reduce padding and for the font-size to be a bit smaller than the standard button (for a refresher on Bootstrap button classes, go to http://getbootstrap.com/css/#buttons)@gray
@link-color
valueYou may want to save, compile, and test the results. The following screenshot depicts the result we get:
Our option links have gained improved padding and font size and taken our desired colors.
You may be wondering why I've chosen to pull in button styles by using the .btn
and .btn-sm
classes in our LESS files rather than adding the classes directly in the markup. We could do the latter, but given the number of option links, I think you will agree that it is far more efficient to apply the styles via CSS as we've done. In the section that follows, I will continue this pattern and extend it by bringing in Font Awesome icons via LESS rather than by adding markup.
Now we'll add checkboxes to our option links.
In this section, we'll use Font Awesome icons to add an empty checkbox to the left of each option link. Rather than adding icons in the markup, we will do it here via LESS as it will be far more efficient. Then we'll push a step further, adding styles to pull in an alternate Font Awesome icon—for a checked checkbox — to the hovered, focused, and active option links.
Adding icons via LESS requires drawing Font Awesome styles from three files. First, we will take these fundamental styles from the core.less
file in the font-awesome
folder. In this file, you'll find the following key styles:
.@{fa-css-prefix} { display: inline-block; font-family: FontAwesome; font-style: normal; font-weight: normal; line-height: 1; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; }
These styles establish the fundamental rules for all Font Awesome icons, including the Font Awesome icon for the font family and then refine the details of its presentation.
For our present purposes, we do not need the selector or the braces but only the rules. We will take these and apply them to our links. Primarily, we'll use the :before
pseudo-element as it ensures the best results.
For more information about the CSS2.1 :before
pseudo-element, go to http://coding.smashingmagazine.com/2011/07/13/learning-to-use-the-before-and-after-pseudo-elements-in-css/.
Copy the rules (but not the selector) from core.less
. Then paste these rules in the _products-grid.less
file, nested as follows:
.grid-options { ... li { ... a { ... &:before { // from font-awesome/core.less display: inline-block; font-family: FontAwesome; font-style: normal; font-weight: normal; line-height: 1; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
These rules establish the fundamentals. Next, we need to specify which Font Awesome icon to use. Browsing the options at http://fontawesome.io/icons/, we find the following open checkbox icon:
The LESS rules for this icon are found in the icons.less
file inside the font-awesome
folder. By opening that file and searching for the string }-square-o
(including the closing curly brace before -square-o
to narrow the results), we can find the following relevant line:
.@{fa-css-prefix}-square-o:before { content: @fa-var-square-o; }
From the previous line, we need only content: @fa-var-square-o
, which we need to copy and paste in the _products-grid.less
file directly after the preceding rules are applied to our a:before
selector:
a { ... &:before { ... content: @fa-var-square-o;
Finally, we want to grab Font Awesome styles to give our icons a fixed width and to avoid any shifting when the icon changes to the checked version. These styles are found in the fixed-width.less
file inside the font-awesome
folder. Copy and paste just these two lines while also applying them to our &:before
selector:
width: (18em / 14); text-align: center;
After adding these rules, compile them to CSS and refresh your browser. You should see the checkboxes appear as shown in the following screenshot:
Now, following the same approach, we'll add the following selectors and rules to apply the checked version of the Font Awesome icon to the hovered, focused, and active states of our links:
li { ... a { &:before { ... content: @fa-var-square-o; &:hover:before, &:focus:before, &:active:before, .active &:before { content: @fa-var-check-square-o; }
Save the file, compile to CSS, and refresh your browser. You'll find that the checked version of the square icon appears when you hover on one of the links as shown in the following screenshot:
That's it! We've successfully given our links the appearance of checkboxes to provide desired user feedback.
Next, let's make more efficient use of our space by floating our options side by side.
In the previous section, we've used custom LESS rules to accomplish steps that might have been accomplished by adding markup. Given the number of option links we need to manage, this has proven significantly more efficient. The same dynamic applies when we want to arrange our option links into columns.
We might accomplish our desired result by using Bootstrap row and column classes, adjusting our markup with the following pattern:
<ul class="options-list options-categories row"> <li class="col-xs-6"><a href="#">Option 1</a></li> <li class="col-xs-6"><a href="#">Option 2</a></li> ...
Thanks to the power of Bootstrap's mixins, we can accomplish the same result with a few lines of LESS as shown in the following steps:
.make-row()
mixin to the .options-list
selector, as follows: .options-list {
.make-row();
...
This mixin applies the same styles to our options list that we would have gained by applying the row
class in the markup. In this case, it's simply more efficient to do it here.
li { .make-xs-column(6);
This will apply the same styles to our list items as would be applied if we had added the col-xs-6
class to each of the relevant li
tags.
Not bad!
We need to constrain the width of our options panel so that it does not range too widely in tablet-width devices.
Right now, our Clearance Sale button stretches too wide, and our options list items spread too far apart on viewports between 480 pixels and 768 pixels wide. Thus, they can end up appearing like the following screenshot:
This can be easily fixed by setting a max-width
property with a value of 480 pixels for the entire options panel:
.grid-options { ... max-width: 480px;
Now let's adjust our option list items so that they organize themselves in three columns in small viewports. Using LESS, we can nest a media query within the appropriate selector and add an adjusted .make-xs-column(4)
mixin as shown in the following code snippet:
li { .make-xs-column(6); @media screen and (max-width: @screen-xs-max) { .make-xs-column(4); }
After making these adjustments, save the file, compile to CSS, and test in a narrow viewport. You should see the result as shown in the following screenshot:
Now let's address the next problem facing our single-column layout: we need to hide our options away until they're needed.
At present, our options take up a considerable amount of vertical space. This creates a problem in narrow viewports. The single-column layout winds up pushing our grid of products far down the page.
This is a great deal of vertical space for options that are not needed. The products themselves are priority items. We need to allow users of phones to find the products more quickly while still allowing them to access the filtering options when desired.
We'll use Bootstrap's collapse plugin for this. In the following steps, we'll apply the collapse plugin to the options panel, add a button to expand the panel when desired, and restrict the behavior to narrow viewports only:
products.html
.div
tag to wrap our Clearance Sale button and three options lists. We need to give this new div
a special class of collapse as well as a distinctive ID so that we can target it with our JavaScript plugin. For good measure, we'll give it a matching special class as well:<div id="options-panel" class="options-panel collapse">
<a class="btn btn-feature choose-clearance" href="#">
...
<h3>Categories</h3>
<ul class="options-list options-categories">
<li><a href="#">Option 10</a></li>
...
</ul>
</div><!-- /#options-panel.collapse -->
Bootstrap's collapse JavaScript plugin is what powers the collapsible responsive navbar. It may also be put to other uses, such as the one shown in the Bootstrap's documentation at http://getbootstrap.com/javascript/#collapse.
h2
heading Narrow your selection as shown in the following screenshot:Now we need a toggle button to expand our filter options when clicked.
h2
heading that reads, Narrow your selection, add a button element with the following attribute structure:<h2 class="clearfix">Narrow your selection <button type="button" class="options-panel-toggle btn btn-primary pull-right" data-toggle="collapse" data-target="#options-panel"> <span class="icon fa fa-cog fa-2x"></span> </button> </h2>
The following points explain what the preceding markup will do:
clearfix
class will ensure that the h2
heading will contain the toggle button, which will float to the right (you'll find the clearfix
class in the utilities.less
file inside the bootstrap
folder, the mixin of which it's made is in mixins.less
in the bootstrap
folder)btn
and btn-primary
classes will style our new button
element with the Bootstrap's btn
styles, which includes our background color of @brand-primarypull-right
class will float the button to the rightbutton
element, we've placed a Font Awesome cog icon using the fa-2x
class to double its sizeSave this and refresh to view the following result:
_products-grid.less
:// Responsive adjustments @media (min-width: @screen-sm-min) { .options-panel { display: block; } .options-panel-toggle { display: none; } }
collapse
class, which hides its element by defaultSave and refresh, and you should see our desired results.
In narrow viewports, the options list is collapsed and the toggle button is visible:
In small, medium, and large viewports, the toggle button is hidden, and the options list is visible:
Congratulations! With this, we have accomplished our design.