My Drupal Blog - Case Study (Upgrade, Redesign, HTML5, Responsive)

I recently upgraded My Drupal Blog from Drupal 6 to Drupal 7 and implemented a newly designed and HTML5 based responsive theme.

My Drupal Blog home page

This case study details the processes involved.

The two sentence overview

My Drupal Blog is a Drupal theming blog written by Laurence Mercer (that's me!). The blog focuses primarily on theming tutorials and snippets, though also contains occasional opinion pieces.

Upgrading from Drupal 6 to Drupal 7

Upgrading was relatively straightforward (obviously, with many backups throughout):

  • disable/uninstall/remove any unneeded modules
  • update core to the most recent Drupal 6 version
  • update contrib modules to their most recent Drupal 6 version
  • disable the custom theme and switch to a core theme
  • disable contrib modules
  • upgrade core to Drupal 7
  • upgrade contrib modules to Drupal 7 and enable
  • upgrade the theme to Drupal 7 (more on that later) and enable

A couple of good resources here are:

I found the most time consuming part to be determining what to do about modules which had no Drupal 7 version. Thankfully this only affected a couple of modules and in both cases I was able to implement an alternative solution.

Module choices

The core modules used are, arguably, all pretty standard apart from 'PHP filter', which is a text filter that allows PHP code to be added directly to blocks etc.

I wanted to keep contrib modules to a minimum - both for performance and maintainability reasons. In each case I used the most recent recommended release or, failing that, the most recent dev release.

Core

Block, Color, Comment, Database logging, Field, Field SQL storage, Field UI, File, Filter, Help, Image, List, Menu, Node, Number, Options, Path, PHP filter, Search, System, Taxonomy, Text, Toolbar, Update manager, User

Contributed

  • Code Filter
    Allows users to post code verbatim using <code> and <?php ?> tags. Used for codeblocks (in combination with Prettify - more on that later).
  • Comment RSS
    Generates RSS feeds for comments.
  • Chaos tools
    Required by Views.
  • Devel
    A great developer tool.
  • Global Redirect
    Resolves the 'two URLs for one page' issue.
  • Mollom
    Spam protection.
  • Pathauto
    Automatically generates URL/path aliases for various kinds of content.
  • Service links (inc. General Services)
    Adds social links (Twitter, Facebook etc.) to the end of blog posts.
  • Token
    Required by Pathauto.
  • Views (inc. Views UI)
    Used for the 'Categories' block. May just be the greatest module ever :)

Site setup

Being a blog, the majority of the content consists of blog posts and their associated comments (surprising eh!). The remaining content is a mix of blocks (some custom) and a few pages.

Blog posts

Blog posts are the default 'Story' content type, with comments set to 'open'.

Two extra fields have been added to the content type:

  • Topic (a taxonomy term reference field used for adding post tags)
  • Images (an image field used for adding post images)

I've also set posts to be unpublished by default, so as to avoid accidental posting of a draft...

Code blocks

Blog posts use the 'Full HTML' text format, to which I've added the 'Code filter' text filter. This allows the posting of code verbatim - i.e. code will be displayed rather than executed.

My Drupal Blog code block

The Prettify JavaScript plugin is then used to add line numbering and syntax highlighting. There is a Prettify Drupal module available, though for simplicity I instead added Prettify via my theme, initiating it with some jQuery:

// prettify code blocks
Drupal.behaviors.cb = {
  attach: function (context, settings) {
    $('.codeblock:not(.cb-processed)', context).addClass('cb-processed').each(function() {
      $('code', this).addClass("prettyprint linenums");
    });
    if ($(".prettyprint").length > 0) {
      prettyPrint();
    }
  }
};

Social links

The social links (Twitter, Facebook etc.) at the end of blog posts are generated by the Service links module.

My Drupal Blog social links

There are many social link modules available, each with pros and cons. I chose to use the plain image links provided by the Service links module because of their simplicity (from an HTML perspective) and ease of theming.

One thing to note: in order to prevent the service links from appearing in your RSS feed (as I did) you need to modify the 'Page specific visibility settings' (admin/config/services/service-links) - ensure that 'All pages except those listed' is selected and then add '*rss.xml' to the 'Pages or PHP code' textarea.

Comments

Comments are the default core comments.

My Drupal Blog comment

Comments use the 'Filtered HTML' text format, with the main modification being that I have added the 'Code filter' text filter to this text format, enabling commenters to post code verbatim.

Spam protection is provided by Mollom.

Search

Search is handled by the core search module. The search module generates a search form block, which I've added to a custom region near the top of the page.

My Drupal Blog search block

Profile links

A default custom block containing a list of links to my profiles on other sites.

My Drupal Blog profile links

Categories

A Views block containing a list of taxonomy term links, with each list item displaying the term name and a count of how many posts have that term.

My Drupal Blog categories block

Footer message

A default custom block containing blog subscription links and other general footer bits.

My Drupal Blog footer

FeedBurner

I use FeedBurner for both my main RSS site feed and my main RSS comments feed. Unfortunately, FeedBurner was one of the modules which had no Drupal 7 release at the time of upgrade.

Fortunately, though, I use a standard FeedBurner implementation (with no fancy stuff like ads in the feed etc.) and found a neat alternative - editing the root '.htaccess' file. It's also worth checking out Google's explanation of how to do this.

Theming

The theme is newly designed, custom built (as opposed to using a base theme), HTML5 based, and responsive.

Design

Designing initially took place in Photoshop, though with the implementation of responsiveness and the advantages of CSS3 I found myself doing increasingly more experimentation directly in the browser.

As with the previous version of the site, I wanted the blog to look as if it was from the same family as the main site but maintain its own style.

My Drupal Blog and Lhmdesign(click to enlarge)

CSS3 FTW!

Rounded corners (border radius), box shadows, linear gradients, alpha channels, text shadows, and transitions are all used in the new theme. Credit to Divya Manian for the CSS gradient transition hack, which I modified for use on my buttons:

My Drupal Blog button states

Converting the theme to HTML5

In essence, converting a theme to HTML5 is very easy - just give it a DOCTYPE of <!DOCTYPE html> and you're done. There is, however, a whole load more stuff you can do...

Both the HTML5 version of Zen and AdaptiveTheme proved to be handy HTML5 theme references, as were the discussions in their respective issue queues regarding HTML5 implementation.

Other useful resources included:

My HTML5 approach

I chose to stick pretty closely to the HTML5 boilerplate.

Primarily, this meant editing:

  • template.php (strip redundant 'type' and 'media="all"' attributes from style, script, and link tags)
  • html.tpl.php (see below for the code)
  • page.tpl.php (add HTML5 elements, e.g. <header> and <nav>)
  • mydrupalblog.css

It also meant removing 'ie8.css' and 'ie7.css', which were no longer necessary as the theme now uses conditional classes (see 'In defense of CSS hacks — introducing "safe CSS hacks"' as well) as opposed to the previous conditional stylesheets. This means that IE CSS corrections are now added directly to the main stylesheet using the relevant class, for example:

.ie8 .page {
  some: thing;
}

As a result of the changes, my 'html.tpl.php' file now looks like this:

<!DOCTYPE html>
<!--[if IE 7]><html class="ie7" lang="en" dir="ltr"><![endif]-->
<!--[if IE 8]><html class="ie8" lang="en" dir="ltr"><![endif]-->
<!--[if gt IE 8]><!--><html lang="en" dir="ltr"><!--<![endif]-->

<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
  <title><?php print $head_title; ?></title>
  <meta name="viewport" content="width=device-width,initial-scale=1">
  <?php print $head; ?>
  <?php print $styles; ?>
  <?php print $scripts; ?>
  <!--[if lt IE 9]>
  <script src="<?php print url(path_to_theme() . '/js/html5-respond.js', array('absolute' => TRUE)); ?>"></script>
  <![endif]-->
  <script>var _gaq = _gaq || []; _gaq.push(['_setAccount', 'UA-XXXXXXX-X']); _gaq.push(['_trackPageview']); (function() { var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); })();</script>
</head>
<body class="<?php print $classes; ?>" <?php print $attributes;?>>
  <a href="#main-content" id="skip-link" class="element-invisible element-focusable"><?php print t('Skip to main content'); ?></a>
  <?php print $page_top; ?>
  <?php print $page; ?>
  <?php print $page_bottom; ?>
</body>
</html>

One thing to note: I haven't used Modernizr (which the HTML5 boilerplate does use). On balance I didn't find it necessary for this project, though it's certainly something I anticipate utilising on future projects.

More to do

Going forward, other areas to explore include:

  • Using '.htaccess' to set the X-UA-Compatible header, which would have the added bonus of the HTML then validating
  • Implementing responsive images
  • HTML5 Tools, Fences, and other HTML5 useful/related modules
  • Further form and markup changes (lots of interesting Drupal 8 HTML5 stuff happening here)

Making the theme responsive

Alongside a new design and an HTML5 base, I also wanted the theme to be responsive.

Whilst the concepts of responsive web design are straightforward, I found the challenge to be implementing an elegant solution. Simply squashing everything to fit in 320px doesn't work so well...

Using a combination of (well written!) media queries and jQuery I was able to create a theme which fluidly responds to different resolutions:

My Drupal Blog responsive design(click to enlarge)

HTML5 and responsiveness in IE 8 and IE 7

By default, IE 8 and earlier IE versions (though I was only concerned with IE 8 and IE 7) do not support either media queries or HTML5 elements. As such, they initially made a minor mess of the new theme.

There are a number of possible solutions - everything from "who cares, it's IE" to "pass IE a completely different set of theme files".
There's no single correct answer. The number of users actually accessing a site with IE 8 or IE7 will likely be an important factor, as will implementation time/cost. Ultimately, I chose to go with the solution which Zen currently uses - 'html5-respond.js'.

'html5-respond.js' is a JavaScript file which contains both the HTML5 Shiv and Respond.js.

As might be guessed from their names, HTML5 Shiv enables the "...use of HTML5 sectioning elements in legacy Internet Explorer, as well as default HTML5 styling in Internet Explorer 6 - 9, Safari 4.x (and iPhone 3.x), and Firefox 3.x", whilst Respond.js is "a fast & lightweight polyfill for min/max-width CSS3 Media Queries (for IE 6-8, and more)".

In short, loading this script for IE 6-8 should ensure that they handle HTML5 elements and min/max-width CSS3 media queries correctly.

To implement the script, I first copied 'html5-respond.js' to my theme's 'js' folder and then added the following to my theme's 'html.tpl.php' file (near the closing </head> tag - check out the 'html.tpl.php' code above for the exact position):

<!--[if lt IE 9]>
<script src="<?php print url(path_to_theme() . '/js/html5-respond.js', array('absolute' => TRUE)); ?>"></script>
<![endif]-->

This means the script will only get loaded by IE and only for versions which are less than IE 9.

One important thing to note is that Respond.js only works on CSS files which are added to the <head> via a <link> tag. By default, Drupal adds its CSS files using @import. An easy solution is to enable CSS aggregation (admin/config/development/performance -> 'Aggregate and compress CSS files'). Drupal adds the compressed aggregated CSS files via <link> tags, and less CSS files overall also means the added performance bonus of reducing HTTP requests.

Mobile icons

Lastly, it's worth mentioning touch icons and retina display images.

Touch icons

As 'Everything you always wanted to know about touch icons' succinctly puts it "'Touch icons' are the favicons of mobile devices and tablets."

Basically, adding touch icons to a site allows you to do this:

My Drupal Blog iPhone touch icons

A recent Lullabot article covers the process of adding touch icons to a Drupal site using the Touch icons module.

An alternative approach is to just add the touch icons directly to your site's root folder. No module or HTML required. This works great on iOS (which automatically scans a site's root for touch icons) but not on some versions of Android etc. - so, pros and cons.

Retina display images

iPhone 4+, iPad 3, and newer Android etc. phones use a retina (high PPI) display, fitting more pixels into the same physical space as non-retina phones. In the case of iPhone 4+ the PPI have been doubled. Whilst this produces a super sharp display, it also means there are now two pixels per point, the result of which is that web images are scaled up to adapt to the new resolution and this, in turn, results in blurring.

(image: iPhone 4S displaying non-retina optimised images vs. retina optimised images)My Drupal Blog retina display images

Fortunately, as the screenshot above shows, there is a solution! Alternative images can be passed to these high PPI displays using CSS3 media queries.

For example, the Twitter icon:

@media screen and (-webkit-min-device-pixel-ratio: 2) {
  #twitter a {
    background-image: url(../images/twitter-footer-2x.png);
    background-size: 24px 24px;
  }
}

See: this, this, and this for further reference.

Questions, comments, suggestions?

Leave a comment and I'll be happy to answer!
Thanks,
Laurence.

16 comments

Alex Weber March 14th, 2012 @ 1:52pm

Nice writeup, thanks! :)

One question, what made you decide to build your own theme from scratch as opposed to using one of the available contributed HTML5 responsive base themes?

ericduran March 14th, 2012 @ 2:39pm

Nice write up.

Since you mention maybe using html5_tools in the future and also moving the X-UA-Compatible header to .htaccess I wanted to let you know that if you use the html5_tools module it would actually add the header on to request for you. So you don't really need to do much. Also it should handler most of the forms stuff for you. :)

Laurence March 14th, 2012 @ 2:43pm

@Alex

Thanks!

I'd say the custom theme choice was due to a combination of:
- wanting to structure and code theme files however I liked
- wanting as lean a theme as possible

Also, coding from scratch kinda forces you to think and learn :)

Laurence March 14th, 2012 @ 2:49pm

@ericduran

Very cool, thanks. I'll be interested to check that module out in more detail!

Greg Anderson March 14th, 2012 @ 3:22pm

Great overview; very thorough. On the topic of the upgrade step, the new version of Drush site upgrade (http://drupal.org/project/drush_sup) will help take the tedium out of the manual process of stepping through the iterative process of replacing a module and running updatedb. I should be publishing the first release shortly; the adventurous can try the master branch today.

Laurence March 14th, 2012 @ 4:07pm

@Greg

Nice! Yes, that is not the most fun process to do manually ;)

Alex Weber March 14th, 2012 @ 4:21pm

@Laurence

Awesome! :)

Adrian March 17th, 2012 @ 3:59am

Did you use any html5 drupal based theme as starter ?

Laurence March 17th, 2012 @ 12:23pm

@Adrian

No, the theme is custom.

However, I did find the HTML5 Boilerplate, the HTML5 branch of Zen, and AdaptiveTheme to be useful references (you can find links to these in the post).

Drupal Entwickler March 18th, 2012 @ 4:45pm

Thx for your great post! I'm also migrating to D7. Especially your HTML5 approach is very interesting :)

Shawn April 8th, 2012 @ 10:49pm

Great writeup Laurence.

Laurence April 10th, 2012 @ 11:23am

Thanks Shawn :)

Pat April 19th, 2012 @ 8:09pm

This is great work. I like the responsive design.

One thing:
The transitions don't seem to be working in Opera. I think it's just a matter of syntax.

Laurence April 20th, 2012 @ 12:05pm

@Pat

Thanks - glad you like the responsive stuff.

Yes, Opera's a tricky one. I generally do include Opera's -o- vendor prefix where relevant. However, Opera currently accounts for less than 1% of my traffic, so it's not a browser I explicitly support.

Drupal Dallas June 4th, 2012 @ 12:36am

Loving the layout! Simple, clean and user friendly. The trick with responsive design is to make everything that stacks still look good. Sometimes designs that look great in the browser, get cluttered when you view them on mobile / iPad, and vice versa. The perfect balance is when it is seamless and maintains brand integrity across all devices, and you have achieved this with your new design. Congrats on the new look!

I despise IE6, 7 & 8, that browser has consistently stolen pieces of my soul for almost a decade.

Your documentation for this post is on point. Thanks for the share!

tyler June 7th, 2012 @ 6:04pm

This is great-thanks!

Comments are closed

If you want to ask a question or have something to add please contact me.