Theming with Twitter Bootstrap version 3 - Part 2

Mobile FirstIn the first article, I explained some of the basics of creating a Twitter Bootstrap 3 (BS3) based theme for Exponent.  In this article I'll attempt to alleviate some of the myths or quirks associated with BS3 that may be delaying your move to use this versatile framework for your next custom theme.

Myth #1 - BS3 themes are limited to a one page design - NOT TRUE.  While many of the examples found across the internet are limited to one (possibly) long page with a menu of relative links on the page, you can still use the multi-page approach Exponent has used in the past.

Myth #2 - BS3 themes must have the fixed menu (navbar) always displayed at the top of each window - NOT TRUE.  Again, while many examples on the internet follow this approach, our sample BS3 theme (bootstrap3theme) provides the option of 'static top' (stays at the top of the content and will scroll out of view), 'fixed bottom' (always displayed at the bottom of the window), or 'fixed top' (always displayed at the top of the window).

Additionally, you may place a banner above the navbar using one of the techniques found here.  You are not limited to generic sort of layout.  Some example non-Exponent themes can be found at:

Quirk #1 - BS3 navbars are limited to children only (depth of two) and no grandchildren (depth of three or more) - While we support multi-level navbars of any depth, this will NOT work with touch devices (grandchildren are only displayed on 'hover'), nor with the 'collapsed' menu provided on small devices (or small width browser windows)

Quirk #2 - Not everything is 'touch' enabled - Though we're working inside Exponent to alleviate (work-around) this, some elements like the 'carousel' are not 'touch' enabled, in addition to the aforementioned multi-level menus.

Quirk #3 - The site looks slightly different on different sized devices or different browser widths - This is actually a feature, NOT a problem.  With BS3 you won't need to develop a complex stylesheet based on media queries, nor have separate mobile subthemes (a feature of Exponent documented here).  Since BS3 is 'mobile first' it makes it simpler to desing a web site style and layout which works equally well on large (desktop) or small (smartphone) displays.

Hopefully, this has alleviated some of your fears in pressing forward into the Bootstrap era.  I do still plan to write another article/tutorial on converting an open-source/free BS3 theme (from one of the sites listed above) into an Exponent theme, which may be a greater incentive to take the plunge.

Theming with Twitter Bootstrap version 3

Twitter Bootstrap 3 - MObile FirstTwitter Bootstrap version 3 (BS3) is becoming the user interface framework library of choice for Exponent CMS.  Though initially shipped with Exponent v2.3.0, that BS3 implementation was still lacking some refinement, and wasn't fully implemented across the entire user interface.  This has been somewhat remedied by the first three patches to v2.3.0, and will be even more-so in the upcoming patch #4 release.  In this article I'll attempt to share some of the basics of how to create a Twitter Bootstrap 3 custom theme.

First off, this is NOT an introduction to using Twitter Bootstrap 3 or it's grids, nor understanding what 'mobile first' or 'responsive' means.  There are several tutorials on the web including this one.  However, we won't avoid those topics as we focus on Exponent CMS theming specifics as they apply to using BS3.

We ship a BS3 sample theme with Exponent v2.3.0 appropriately named 'bootstrap3theme'.  Since the release of v2.3.0 we have tweaked this theme (as we said we would), therefore the one being included in v2.3.0 patch #4 has some changes from the one included in the initial release.  This article assumes you have access to those sample theme files and can use it as a starting point.  Eventually I may also publish a second part to this article to walk you through converting an existing open source BS3 theme template for use as an Exponent template (with the purpose of it being added to the help/doc site).

When you examine the /themes/bootstrap3theme/index.php default theme template, you'll note several Exponent specific things in the 'head' section with the expTheme::head() parameters: 

  • the 'framework' parameter is set to 'bootstrap3'.  This automatically ensures we are loading the BS3 stylesheets, jQuery script, and 'prefer' the '.bootstrap3' view template variation (which includes any form control or template engine plugin variations) if available.
    • BS3 scripts are never automatically loaded, but must be requested by the expJavascript::pushToFoot() call or the theme template {script} smarty function using the 'bootstrap=' parameter.  This parameter works just like the 'yui3mods' and 'jquery' parameters.
  • there are no 'reset' scripts being loaded.  The new standard css reset script, 'normalize.css' is automatically loaded by BS3.
  • we can optionally load the BS3 'theme' stylesheet which gives a BS2 appearance to BS3 styles, if that setting was saved within the theme configuration.
  • though the 'viewport' parameter is optional since we always set the minimum defaults, it is in this theme template as a point to deviate from.
  • we account for two (2) less stylesheet compiler variables (lessvars) we pull from the theme configuration settings which are mandatory for this theme's .less stylesheets.  Most (but not all) stylesheets used with a BS3 theme are in the .less format to allow custom configuration by the end user.  For example, the bootstrap3theme allows selecting from the entire set of 'BootSwatch' themes.  

Now a short sidebar on some BS3 basic concepts...there is a hierarchy of three (3) basic components for the BS3 grid system: 1) container, 2) row, and 3) column.  

  • The 'container' class element is mandatory as the highest level element for the grid system.  It may NOT be nested as this will create anomalies with display of the page.  The classname used for a container element is 'container'.
  • The 'row' class element MUST be placed within a 'container' class element, however unlike the container, they may be nested if the nesting occurs within a column.  In a basic sense, the row is a placeholder for up to 12 equal-width columns of data.  The classname used for a row element is 'row'.
  • The 'column' class element MUST be placed within a 'row' class element, and like the container may NOT be nested...except when found within a nested row.  The classname for a column element is more complex and composed of at least three (3) parts:
    • 'col-' to signify that this is a column
    • a designator for the device size the column setting applies to (more or this later).  But in our example we'll use the size for a small device or tablet with a max-width of 768 pixels which is 'sm-'.  Grid column classes are divided into device sized groupings:
      • 'lg' for large devices such as wide-screen monitors (max width 1200 pixels)
      • 'md' for medium sized devices such as desktop monitors (max width 992 pixels)
      • 'sm' for tablet sized devices
      • 'xs' for extra small devices such as phones (max width 640 pixels
      • These can be mixed within the same element to provide for a different layout on different devices.  E.g., a 4 column wide layout on a desktop would become a 2 column layout on a tablet (2 rows high) or a single column layout (4 rows high) on a smartphone.
    • and a digit to set the number of column units of width this column is to fill (from 1 to 12)
    • so the simplest column element would be 'col-sm-12' for a single column the entire width of the row.  A equal-width 2-column layout would be two elements each with a class of 'col-sm-6' (6 + 6 = 12).

<body>
    <div class="container">
        <div class="row">
            <div class="col-sm-12">
               This is a full width column, 12 units wide.
               A row with columns could also be placed within this element.
            </div>
        </div>
    </div>
</body>

Therefore, in Exponent, the template theme/subtheme template MUST hold any 'container' element(s).  There must NEVER be an element with the class of 'container' found within a view template.  A BS3 styled view template can ALWAYS assume it is being loaded within a 'container' and/or a 'column' element.  Therefore, the view template should be wrapped within a 'row' element if it will be subdividing its display using the grid system with 'column' elements.  The only exception to this is the navigation menu (navbar) which in most examples (including the main BS3 site) is simply wrapped within a 'container' element without rows nor columns.

So within the 'body' section of the /themes/bootstrap3theme/index.php default theme template, you'll note:

  • We have two (2) containers: one for the menu and one for the content
  • Within the menu container we have NO rows or columns, so the menu 'template' view can assume it's within a container
  • Within the content container we have two rows: one for the actual page content, and one for the page footer area
  • Within the actual page content row we have two columns: one for the main content, and one for the sidebar

For the Exponent theming system to work correctly with several UI frameworks, we allow for view templates to also have theme framework variations.  These system view templates are denoted by a framework type suffix before the file type.  So a system 'showall.tpl' view template with a BS3 variation would be named 'showall.bootstrap3.tpl'.  In the absence of a BS3 specific view template, the system would fallback and choose a BS2 template with that framework suffix...in this example if the BS3 variation template did not exist but a BS2 variation template existed named 'showall.bootstrap.tpl, it would be used instead of the base 'showall.tpl' file.  Since a custom theme can only use one UI framework, ALL custom template views use the root name without any framework variation.

A note about the /themes/bootstrap3theme/config.php theme configuration settings file.  You MUST include a variable named 'SWATCH' or the .less stylesheet compiler will crash when compiling the BS3 stylesheets. 

There MUST always be a file /theme/customthemename/less/variables.less, even if it's an empty flle. This file is ALWAYS compiled by the bootstrap.less file and overrides any bootstrap 3 and swatch variables as needed.  A failure to include this file (it may be empty) WILL result in a .less compiler crash.  This file should ONLY contain .less 'variables' as it will also always be compiled as a theme stylesheet and any 'styles' included within in it will also create a theme stylesheet named /css/variables.css.

In summary:

  • The theme/subtheme template MUST include the un-nested BS3 'container' element.  The theme/subtheme template is the only place the 'container' element will be found.  It may optionally contain 'row' elements' so long as it also contains 'column' elements within the 'row'.
  • The view template can always assume it's being displayed within a 'container' and/or also a 'column' element.
  • Any 'custom' view templates must only have the '.tpl' file type suffix and can NOT contain the '.bootstrap3.tpl' framework variation suffix.
  • Failure to follow these guidelines will cause horizontal margin anomalies and prevent theme custom views from loading