The Redesign Details — ExpressionEngine

By John Faulds

As you may have noticed, this site has been redesigned recently, and I mentioned in the announcement that I'd talk about some of the work that went into the process. So in this first instalment of what might be a two or three-part series, I'm going to talk about some of what's going on under the hood in (the) ExpressionEngine. In the other parts, I'll cover topics relating to design in general, and aspects of the front-end development. In terms of how sites normally get built, that's a bit backwards, as integrating your design and content into the CMS usually comes last, but most of what I'm going to discuss here relates to Stash, which seems to be a bit of a hot topic at the moment.

Bangers & Stash

Yep, so tasty that you just want to smother it in gravy and eat it up! If you're not familiar with Stash by Mark Croxton yet, you should be because it's awesome in so many ways, some of which are discussed by Adrienne Travis on EE Insider. One of Stash's greatest strengths, its amazing flexibility for use in a variety of situations, I think is also one of its shortcomings when it comes to uptake by developers. Because there's so many different things it can be used for, for people new to it, I think it can be a bit hard to grasp just how it can benefit you in your own work.

I'm very much a learn from examples type of guy, so rather than give a dissertation on why I use it, I'm just going to dive straight into some examples from the build of this site and others I've worked on recently.

Templates

Standard pages

There are actually separate template groups for all the main sections of the site, even though the templates for some like About and Info are essentially the same. That's just so I didn't have to use either the Pages module or something like Structure or Navee to assign the same template to pages that appear under different URLs. But even though I have different template groups for the sections, they all make use of the same code like this:

{exp:channel:entries channel="site" url_title="{segment_2}"
{sn_page}
Standard page template

Just the start of the channel entries tag to set the channel and the entry to display, the rest is contained in the {sn_page} snippet.

limit="1" disable="categories|member_data|pagination|trackbacks"}
 	{ if no_results}{redirect="404"}{ /if}

	{embed="_embeds/index" body_class="{segment_1}" nav_active="{segment_1}"}

		{exp:stash:set_value name="st_page_title" value="{title}"}

		{exp:stash:set name="st_content"}
			{body}
		{/exp:stash:set}

	{/exp:channel:entries}

	{exp:stash:set name="st_side"}

		{!-- Sidebar stuff like: --}
		{sn_testimonials}

		{sn_social-links}

	{/exp:stash:set}
The {sn_page} snippet

The snippet finishes off the channel entries tag (these parameters are common) and then a single embed which pulls in the ‘layout’ template (below). We're setting a value for the page title, the {st_content} variable holds the body of the entry, and then there's another {st_side} variable for sidebar content. All fairly straightforward stuff.

{!-- Setting proper 404 headers --}
{ if segment_2=="404"}{exp:http_header status="404"}{ /if}<!doctype html>
<html>
<head>
	<meta charset="utf-8">
	{!-- Using SEO Lite for page titles --}
	{exp:seo_lite use_last_segment="yes"
		title_postfix="{embed:postfix}"
		default_title="{embed:page_title}"
		default_keywords="{embed:keywords}"
		default_description="{embed:meta_desc}"
	}
	{!-- Using Minimee for asset minification and combination --}
	{exp:minimee:css}<link rel="stylesheet" href="/assets/css/master.css">{/exp:minimee:css}
	<script src="/assets/js/LAB.min.js"></script>
	{!-- Using our own EE #RWD add-on for setting a screensize variable --}
	{exp:ress:cookie}
	{!-- Can inject code into the header from individual posts in the blog --}
	{exp:stash:get name="st_code"}
</head>
<body class="{embed:body_class}">
	<div class="header" id="header">
		…
	</div>
	<div id="content">
		{ if {exp:stash:not_empty name="st_page_title"}}<h1><span class="wrap">{exp:stash:get name="st_page_title"}</span></h1>
		{ /if}
		<div class="wrap row">
			<div role="main" class="main">
				{exp:stash:get name="st_content"}
			</div>
			{ if {exp:stash:not_empty name="st_side"}}<div role="complementary" class="aside">
				{exp:stash:get name="st_side"}
			</div>
			{ /if}
		</div>
	</div>
	<footer role="contentinfo">
		…
	</footer>
	{exp:minimee:js}{ if embed:js_off!="true"}<script src="/assets/js/site.js"></script>{ /if}
	{/exp:minimee:js}
	{!-- Can inject code here too --}
	{exp:stash:get name="st_code_ft"}
</body>
</html>
The embedded ‘layout’ template

This is the template that forms the framework for the whole site, containing the global elements — header and footer, with conditionals in some places to include different things on different pages. There's comments included in the code above to describe some of what's going on.

Portfolio

The carousel displaying recent projects appears on the home page and also at the top of every portfolio detail page. To keep the templates DRY and also improve performance by cacheing the output, I'm saving a Stash as a file, in this case carousel.html which contains:

{exp:channel:entries channel="portfolio" search:p_detail="=y" disable="member_data|pagination|trackbacks" dynamic="no"}
<li class="touchcarousel-item">
	<a class="item-block" href="{url_title_path=portfolio/view}/">
		{exp:ce_img:single src="{p_thumbnail}" width="150" attributes='alt=""'}
		{title}
	</a>
</li>
{/exp:channel:entries}
	
The contents of carousel.html

And it's then pulled into the different templates with:

{exp:stash:get
	name="carousel"
	scope="site"
	file="yes"
	save="yes"
	refresh="60"
	replace="no"
	output="yes"
	parse_tags="yes"
}
	
The tag that calls carousel.html from the Stashes folder

I should fess up and admit that performance-wise, in terms of the number of queries and the time taken to load the page, using the above method works out pretty much the same as if I'd used a snippet and added cache="yes" refresh="60" to the channel entries tag, but I'll be looking at this method in the future and comparing it against embeds and snippets to see if it performs better in different situations.

Another thing that Stash is very handy for is inserting blocks of content from one channel in between blocks of content from other channels. For instance on the portfolio detail pages, I list the details of the project followed by a related testimonial, and then the images associated with the project. Without Stash, I'd either need to use an embed or two separate channel entries tags. With Stash I can do this:

{exp:channel:entries channel="testimonials" url_title="{segment_3}" dynamic="no" disable="categories|member_data|pagination|trackbacks"}

	{exp:stash:set name="st_testimonial"}

		<blockquote>
			{quote}
		</blockquote>

	{/exp:stash:set}

{/exp:channel:entries}

{exp:channel:entries channel="portfolio" limit="1" require_entry="yes" disable="member_data|pagination|trackbacks"}

	{exp:stash:set name="st_content"}

		<h1>{title}</h1>

		Project details…

		{exp:stash:get name="st_testimonial"}

		Project images…

	{/exp:stash:set}

{/exp:channel:entries}
	
The portfolio view template

One other thing not related to Stash going on in this template worth pointing out is how I'm dealing with the issue of responsive images. I'm using an add-on I developed, RESS-ee which creates a variable based on your screensize which you can then use with conditionals in your templates to serve up different sized images or even blocks of content.

{ if ress>768}
	{exp:ce_img:pair src="{image}" max_width="800"}
	<img src="{made}" alt="{title} website screenshot" width="{width}" height="{height}">
	{/exp:ce_img:pair}
{ /if}
{ if ress<=768}
	{exp:ce_img:pair src="{image}" max_width="{ress}"}
	<img src="{made}" alt="{title} website screenshot" width="{width}" height="{height}">
	{/exp:ce_img:pair}
{ /if}
	
Serving up different sized images using RESS-ee

So if your screen is wider than 768 pixels, you get an image whose width is limited to 800 pixels, and if it's under that, the image is sized to whatever size your screen is, i.e. the value of the {ress} variable. The image will be displayed a bit smaller than that due to padding, but I don't think the difference is enough to worry about adding more processing overhead and adding another plugin to do mathmetical calculations on the {ress} variable.

So that's some Stash goodies being used on this site. I'm going to follow up with another post about some I've been using on other projects recently, but feel free to share some of yours in the comments.