When I was a kid, I was so envious of my best friend, because he had something I’d always wanted: a Stretch Armstrong doll.

If you’re not familiar with Stretch, he’s a toy, originally released by Kenner in 1976, whose professional wrestler-like body is made from an incredibly elastic material. Grab hold of his arms and legs and pull, and he distorts and stretches to incredible lengths.

Ladage_SitecoreCMS_1

My friend and I were intrigued by just how flexible this little rubber guy was…and we found out the hard way, when we tried to stretch him across the length of the living room and ripped his arms clean off.

These days, I’m reminded of the Stretch debacle when I work on a project that uses the Sitecore CMS. Like Stretch, Sitecore is also incredibly flexible, but that flexibility comes with a few caveats — especially when it comes to how you approach UI development within it. Without some careful planning, you can easily stretch it to the point of breaking.

With Great Power Comes…Well, You Know the Rest

I often refer to Sitecore as the infinitely configurable CMS. At its core (pun intended) is a component-based architecture that – by default, at least – allows content editors to build web pages that contain whatever components they choose, often in whatever order or layout they want, as well.

This level of flexibility might seem like the ultimate goal for any CMS-based site, and if it’s set up correctly, it is pretty cool. But there are a couple of counterpoints to this unfettered assemble-your-own-website approach:

  • Paradox of choice. Our clients know their own businesses well, but most of them don’t build websites for a living (nor would they want to). A CMS is supposed to empower non-developers to manage a site, but out of the box, Sitecore is like something out of a “Mad Max” movie: totally lawless. This can be overwhelming to people who don’t spend their days building the web. If you think of a website as a collection of individual building blocks, having to piece together each block just to construct a page can be tedious for some.
  • Modularity is difficult. In theory, dropping any component in any order into any custom-developed layout sounds awesome. In practice – especially if you’re the poor UI schmuck who has to figure out all that CSS and JavaScript – making a component look and function perfectly in an infinitely configurable layout (and the infinite combination of page widths within a responsive design) can be really freaking hard.

The CMS and UI teams at DEG have put a lot of thought into solving these two issues, both in terms of how we build the Sitecore site-management experience to match our clients’ needs and workflows, as well as how we craft and deliver the front-end code that actually makes its way to the browser for these sites.

Creating an Enjoyable Sitecore Experience

We design our Sitecore setups with two types of users in mind: standard users and power users.

  • Standard users are more interested in getting content onto a page quickly than they are in assembling the page piece-by-piece. If they’ve worked with a CMS before, it’s generally been more of a template-based system, such as WordPress.
  • Power users appreciate the additional flexibility that comes with a component-based CMS, such as Sitecore. On occasion, they have development experience, or at the very least have built sites that allow them to arrange and structure a site how they see fit.

In order to accommodate both of these groups, we present everything within the Sitecore editor as one of the following:

  • Elements. An element is the smallest Sitecore building block, and when combined with a column group gives the site editor the maximum amount of layout flexibility. Think of each element as a discrete piece of content or functionality that can be grouped or combined with other discrete pieces of content or functionality, but can’t really be reduced to smaller pieces within itself. This can include, but is not limited to, content pods, text elements (headings, paragraphs, ordered/unordered lists, etc.), promotional pods or panels, event lists, tables, or forms.
  • Columns. A column group is typically a horizontal group of individual columns that is dropped into the page’s empty content area first, and then individual elements are added within each column. Out of the box, our column architecture (which can be customized to suit a project’s unique needs) allows for one-, two-, three- or four-column page layouts, as well as offset columns (wide left, wide center and wide right layouts).More than one column group can be added to a page, and column groups can be nested inside of other column groups, which gives content editors an enormous amount of layout flexibility.

    This strategy is flexible, but as you might imagine, calls for some pretty complex and creative CSS solutions. To solve for this, we’ve coded in a few “opinions” into how this structure behaves at different screen sizes and column/element combinations, which has worked well overall. However, if there are specific situations where these assumed conventions don’t work, we can always override them on a per-situation basis.

  • Element Groups. An element group, which is the default view our site editors see, is our solution to the “standard user vs. power user” problem. When a content editor adds an element group to a page, what they’re actually doing is adding a predefined set of columns and elements that meet some of the site’s most common layout and content needs, with a minimal amount of configuration required. Similar to a template-based CMS such as WordPress, this takes much of the grunt work out of constructing a page, but of course, does limit some of the flexibility Sitecore is known for.

It’s important to note that although element groups are the default view in the CMS, we never restrict the site editor’s ability to build a page using individual elements and columns instead. We’ve found this combination of simplicity by default, with customization available when needed, to be a great solution for our clients.

Writing Self-Aware, Axiomatic CSS

Dividing the CMS building blocks into elements, columns, and element groups helped solve our CMS management issue, but it doesn’t answer another important question: how can we write CSS that actually works well within this framework?

The challenge here is that a UI engineer usually knows how a page will look when he/she is authoring CSS, and how elements will be laid out in relation to one another. In Sitecore, this isn’t possible; components can be added, removed, and rearranged in practically any way, so the CSS needs to be written in such a way that it can properly respond to these infinite combinations at runtime.

One of the first tricks our UI team figured out was that the CSS at the element level needs to be self-aware. In other words, we can’t easily rely on the presence of any sort of wrapping element or class to define how we apply styles such as borders, top and bottom margin, and padding. For example, something as simple as a button needs to control its own bottom margin, because there’s no guarantee that it will be placed inside of another markup structure that contains a bottom margin or padding.

That thinking only solved part of the issue; we still had to deal with the complexity of styling elements based on where in a column structure they were added. Fortunately, we soon realized that what we thought was the challenge — our configurable element/column structure within the CMS — was actually the solution. When a site editor creates a page from elements and columns, he/she will always:

  1. Insert columns into the empty content area of the page.
  2. Insert elements directly inside of each individual column.

Ladage_SitecoreCMS_3

This paradigm – that an element is always the immediate child of a column – means we can use child selectors and wildcards to write very general CSS rules to control element layout, regardless of what type of element is there. This is particularly useful for styles such as left/right margin and padding, and how an element looks based on the number of columns. For example:

.column > * {

padding-left: 1rem;

padding-right: 1rem;

}

Ladage_SitecoreCMS_4

In order to allow the column CSS to do its job, an element’s width almost always has to be fluid, and respond to the widths established by its containing column. However, because background colors and images will display within padding, this doesn’t always solve for every situation — you can end up with full-bleed elements butted up against each other. So we’ve also come up with a style that allows us to use full-width elements with margins, thanks to the oh-so-helpful (and surprisingly well-supported) CSS calc function:

.column > * {

margin-left: 1rem;

margin-right: 1rem;

width: calc(100% – 2rem);

Ladage_SitecoreCMS_5

This style of CSS writing, which targets paradigms and patterns within your markup, as opposed to specific classes or elements, is known as Axiomatic CSS. When used correctly, axiomatic code can be very powerful and take a lot of bloat out of your codebase.

Modular JavaScript for the Win

For as long as there’s been JavaScript on the web, people have been complaining about it. Some of those complaints are warranted and some are dubious, but one of the legitimate issues has always been the lack of a built-in, module-loading system for writing and loading discrete pieces of JS functionality.

This is a problem in Sitecore. Because we don’t know what a page is going to contain until runtime, there’s no easy way for us to bundle up and deliver only the JS files that are needed. One option would be to load all scripts on all pages regardless of what’s actually required, but this is not a great strategy, and can negatively impact site performance.

The good news is that this problem is (almost) not a problem anymore.

To be fair, it’s been possible to load module-based JS for years through loaders such as Require.js, but the ratification of the new EcmaScript 2015 standard (not to mention the gradual move to the HTTP/2 transfer protocol) means we’ll soon be able to import and export small, single-purpose JavaScript modules at will without compromising performance. Until these technologies become supported in all browsers, however, our UI team depends on System.js, a fantastic JavaScript loader that follows the new ES2015 module syntax

A module-based approach to writing and delivering our JavaScript assets has been the perfect solution on our Sitecore projects. Our basic strategy is as follows:

  1. System.js is loaded globally on all pages. It also automatically detects missing browser support for next-gen features (such as Module Loading and Promises) and polyfills as needed.
  2. All “common” JavaScript functionality for the site, such as navigation, basic DOM, and object helpers, utility libraries, etc., is bundled together during development, and lazy loaded via System.js on all pages at runtime.
  3. Within our common bundle is a homegrown on-demand module loader, which allows us to load the JS for individual components asynchronously.For example, if a site editor adds a location finder to a page within Sitecore, the markup for that component may look like this:<div class=”location-finder” data-module=”components/locationFinder”>

    </div>Our module loader scans the page for “data-module” attributes and automatically loads those resources, and takes care of any dependencies that module may have along the way.

What I don’t love about this approach is that we’re making an additional HTTP request for every component added. However, considering the current limitations of the HTTP protocol, the fact that these requests are asynchronous and minimal code-wise, and the unpredictable nature of what’s been placed on the page, these are compromises I’m willing to make.

Assembling the Pieces

When I started writing this post, I wanted to compare Sitecore to a jigsaw puzzle, but a puzzle can really only be assembled in one way. In reality, Sitecore is more like playing with Lego bricks: there’s no correct answer, and no limit to your creativity.

Ladage_SitecoreCMS_2

But even Lego sets come with instructions and suggestions, and Sitecore should be no different. We feel like our approaches to structuring the site-management process, crafting intelligent CSS, and loading modular JavaScript give our clients an awesome, flexible final product, without letting them stretch it to the point of breaking.

Oh…and rest in peace, Mr. Armstrong. You fought the good fight.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Comments