Thoughts on scalable, maintainable CSS

This post is heavily inspired by the article referenced in the above tweet. If you haven’t already read it, stop what you’re doing and go read it. Every once in a while you come across a post that challenges your assumptions and makes you take a step back and evaluate your process.

I know a little bit about maintaining large CSS code bases. At my current job, we have a 140 site network of Drupal 7 sites for the college. We also have a few WordPress installs and some other sites and static pages in the mix.

Maintainability is something I strive for. There are also some issues with maintaining CSS for large sites that haven’t been addressed until now.

With all the different naming conventions out there, you’d think we’d have nailed it by now. The truth is, CSS is still a mess.

Preprocessors and build tools have brought us a long way, but what if that is the wrong place to focus?

What if you could open up your text editor and build the interface you want without writing a single line of new CSS?

could open up Sublime Text and write some fancy mixins and Sass functions that really are clever and then make some new classes for my components, but why? Chances are I’ve written CSS that does all of those things already.

I’m not very interested in what I can do with css. I’m interested at this point in what I can help groups of people do with css. –mrmrs

This brings me to why I’m so interested in the concept of one class, one function.

When working with a giant network of sites with distributed authorship, you learn real quick that you can almost never come up with a solution that everyone will like. Certain groups want slight variations to components that you built. Things come up.

What if we threw a bunch of lego bricks at them and said “Here’s all the tools you need”?

Consider the following HTML:

<div class="card card--red">
<h2 class="card--headline">Headline</h2>
<p class="intro">Here is some test text</p>
</div>

Without looking at the CSS for this, can you imagine what it would look like? I’m guessing you would know it looks something like a card and maybe it has a red background? Other than that, it would be difficult to tell what is happening here. Are there any clues about fonts, padding, borders, or text styling?

Now, consider this HTML:

<div class="bg-red padding-2rem border-1px">
<h2 class="sentinel italic font-large">Headline</h2>
<p class="whitney drop-cap">Here is some test text</p>;
</div>

You’ll notice a couple differences right off the bat. There are more CSS classes, yes. But you can also get a much better idea of what the HTML will do. It is semantically clear.

Benefits of this approach include rapid interface development without having to write a line of CSS. Once you come up with all your “utility” classes, you’re free to construct your interface using classnames in HTML.

Also, it allows a broader group of people to benefit from your CSS. People who may not be comfortable with CSS can now in plain English, add classes to their markup which does one thing without having to worry about side effects.

Let me be clear: I don’t think this is a substitute for writing some abstract classes. I think there is still a need to write classnames that don’t map directly to a function (ex: .header-top, .footer, etc) but the point is that a majority of the CSS functionality will be easily exposed in the form of plain English utility classes.

I think this has the potential to help large sites with lots of CSS and lots of people who use the CSS. I’m interested in giving this a try at my organization. When I do, I will most certainly report back here with my findings.

Check out the followup to this piece.

Sharing content between Drupal multi-sites with RESTful and Feeds modules

At Oswego, when we decided to go with Drupal multi-site, one of the biggest drawbacks was the ability “out of the box” to share content between sites. But when you think of it, how much of Drupal works just as you’d like right out of the box? We looked at a few options but what we ended up settling on was a combination of modules that is doing the trick nicely.

Problem

We have a branch campus that needs to pull in program information from another site (graduate studies). The branch campus editors should not be able to edit the content being brought in since they are not the content experts on the subject. Graduate studies maintains the “master” content, then needs to be periodically pulled into the branch campus site. Then, using views we can display a list of content that we pulled in.

Solution

Being a semi-Drupal-newbie, this took quite a bit of trial and error before I figured out something that will work. If you know of another solution to this, by all means leave a comment! I’d love to hear it.

First thing I did was set up the RESTful module on the graduate studies site. This module makes it very easy to be able to expose our graduate program data as a read-only REST endpoint. I experimented with exporting it as RSS, or trying to build something to export the graduate programs as CSV or some other form of structured data but ended up going with JSON via the REST module. JSON is so widely supported, readable, and consumable by so many other applications that it seemed like it was the best route to go.

I’m currently working on a post about setting up the RESTful module! Sign up for email updates to get notified.

The feeds module alone doesn’t consume JSON, but luckily there is a really nice module called Feeds Extensible Parsers.

I’m also working on a post about setting up the Feeds Extensible Parsers module to read JSON!

I currently have it set up to update the branch campus’ program content every 3 hours. Using Drupal’s role and permissions, I can configure it so the branch campus editors can only read the program content, keeping it in sync with the “master” copy.

Creating a hero page template in Drupal

Prerequisites

  • Using Panopoly + Panels + Panelizer

Our current sub-pages look like this:

Screen Shot 2015-04-30 at 3.56.24 PM

 

Drupal is really good at having a consistent header throughout the site. But what if you want to have a landing page that looks like this:

Screen Shot 2015-04-30 at 3.58.00 PM

At first this seemed impossible to me, but after reading about theme_hook_suggestions and preprocess functions, I began to see the light.

  1. Create Hero Landing Page content type with appropriate fields
  2. Create image style to ensure the image is always the right size for the hero area
  3. Add theme_preprocess_page function to grab the image from the node
  4. Add a theme_hook_suggestion to load a different page template file
  5. Disable the hero image field in the default panels
  6. Profit

1. Create Hero Landing Page content type with appropriate fields

You don’t technically have to create a separate content type, but you do need a specific field to hold your hero image. I created a separate content type for landing pages because our landing pages will have some differences from basic pages within our system.

First thing I needed to do was create a “Hero Landing Page” content type that would be able to crank these types of pages out. Within this content type, I created a “Hero Image” field that would be used to hold the appropriate image. Keep note of the “field_landingpage_hero_image” field. That’s what we’ll need later to grab our image.

fields2. Create an image style for the hero image

If you don’t create an image style, you’ll be stuck with Drupal’s defaults which probably won’t suit your needs. In our case, we need the hero image to be 1920px x 768px in order to fit nicely within the theme. Navigate to admin/config/media/image-styles and create a new Image Style called “Landing Page Hero Image”. Under “Effect” choose “Scale and crop” and enter in 1920 for the width and 768 for the height. Once we apply this image style to the hero image field, this will take any image the user uploads and wrangle it into those dimensions.

image_style

3 + 4. Pull out the hero image so we can use it within our page template file & and a theme_hook_suggestion

Using Drupal’s hook system, we can override the template_preprocess_page() function to grab the hero image (if it exists) and make it accessible to the page template file. The way template_preprocess_page works is, you substitute your theme’s machine name for the word ‘template’, and pass in a reference to the $variable’s array. Now within the function you can play with the variables that Drupal is about to render on the page.


/**
* Implements template_preprocess_page().
*/
function oswego_preprocess_page(&$variables) {

  // Check to see if a hero image field is set
  if (isset($variables['node']->field_landingpage_hero_image[LANGUAGE_NONE][0])) {

    // Store the image into $img for easy reference
    $img = $variables['node']->field_landingpage_hero_image[LANGUAGE_NONE][0];

    // Build the $hero array to be used in templates/page/page--hero.tpl.php
    $variables['hero']['path'] = image_style_url('landing_page_hero_image', $img['uri']);
    $variables['hero']['alt'] = $img['alt'];
    $variables['hero']['title'] = $img['title'];

    // Add a theme hook suggestion to load templates/page/page--hero.tpl.php
    $variables['theme_hook_suggestions'][] = 'page__hero';
  }
}

Note the function ‘image_style_url’ that is being called. The first parameter takes the machine name of an image style. In our case, we created our image style in step 2, so I’ll use the machine name of that image style. The function will then return the URL of the image using the specified image style.

By making a $variables[‘hero’] array, we can now access items within it on our page template file using $hero. For example, $hero[‘path’] will point to the URL that image_style_url built in our preprocess function. You can see within the code comments above that I make reference to a file called page–hero.tpl.php. By adding ‘page__hero’ to $variables[‘theme_hook_suggestions’], Drupal will now look for a page template file named page–hero.tpl.php.

Copy your existing page.tpl.php and name it page–hero.tpl.php. I won’t go into the specifics of how I used CSS to style it, but now it is possible to add the hero image in the new page–hero.tpl.php file. Example:


<div class="hero-image">
  <img src="<?php print $hero['path']; ?>" alt="<?php print $hero['alt']; ?>" title="<?php print $hero['title']; ?>">
  <?php if ($title): ?>
    <div class="hero-header">

    <div class="row">
      <div class="section-title-container">
        <div class="section-title-inner">
          <?php print $breadcrumb; ?>
        </div>
      </div>
    </div>

    <h1 class="hero-title"><?php print $title; ?></h1>
    </div>
  <?php endif; ?>
</div>

Disable the Hero Image within your panels configuration

This step will differ greatly depending on how you’re using panels/panelizer. For us, we have a default template that the content type goes into. By default I disabled the node:field_landingpage_hero_image pane so that the image wouldn’t display twice and confuse editors.

disable


And that’s all! Quite a different process than I’m used to when I used to make WordPress themes, but still very effective. Drupal’s powerful hook system allows you to tap into the process and modify data, giving a themer and developer a ton of control. Drupal’s ability to separate logic (template.php) from the theme (*.tpl.php) files is pretty nice as well.

A local Oswego counseling practice gets a website

Heather Rice CounselingMy wife, who is currently in grad school studying mental health counseling, is logging practicum hours with a local practitioner. Their old site was in Wix and had terrible SEO value and wouldn’t properly display on mobile phones. To remedy this, I whipped up a WordPress theme using Bootstrap v3, and gave them a fresh new site to build their practice off of. The site features a blog, which will educate the community on topics relating to mental health. Heather Rice, who offers counseling services in Oswego, NY, now has a simple new website built on WordPress that can grow with her business.

 

SUNY Oswego’s 2014 Annual Report

2014 Annual Report

I’m super proud of what our team at work was able to accomplish in the midst of a Drupal build/migration, as well as our day-to-day tasks. The writing is top-notch and dives deep into the happenings of SUNY Oswego over the past year.

The primary designer of the project was Kelli Ariel, who had a large part in deciding how the site looked. I took the lead on the front-end development. Since I was so involved in the front-end code and design, that’s mostly what this post will be about.

What did this project take to build?

It was about a month of throwing around ideas, designing, coding and Slack conversations. Our process usually involved Kelli coming up with a quick mock-up of what certain parts of the site would look like, then she’d pass those mocks to our Slack channel, some brief discussion would ensue with our team and then I’d code it to work on the web. It worked pretty well for us and allowed us to get a lot done in a short period of time.

Design, development, and content were all intertwined throughout the project. This helped quite a bit. The primary writer, Julie Blissert was very flexible to work with. We were able to get a content structure formed in the early part of the process so design and development could go on, even though the content was still in the process of being written. For example, by structuring the content, I mean the blocks that you can hover over on the site were defined as having:

  • A headline
  • Optional subhead
  • ~325 characters of content on hover

hover-blocks

Without designers, developers, and writers working together to define things like that, a project can get unnecessarily messy.

Development tools:

  • Bower to manage libraries
  • Grunt to build, minify, and concat files to cut down on requests and file size
  • Git for version control

Libraries used:

  • jQuery
  • Waypoints
    • Used to lock in the sticky horizontal navigation
    • Used to fire an event when you hit the bottom of the page. This would then slide out the ‘next’ arrow near the footer.
  • CountUp.js
    • Used in the number panels to count up our statistics
  • Chart.js
    • Used on the Facts and Figures page to build the charts
  • Bootstrap’s grid system
  • Modernizr for feature detection

Fun features

Theme Color Cupola Card

Theme Color

With support for theme-color in the newest versions of Android, it allows web developers to customize their site’s appearance within the Android OS. For example, I was able to change Chrome’s title bar to be in line with our brand colors. I was also able to add our signature cupola icon to the ‘card’ when the user looks at all open apps.

It’s little things like this that are invisible to most users, but adds to the experience.

Sticky Header

On every page, whether you are on a mobile device or a desktop computer, the navigation will ‘stick’ to the top of the view port, allowing users easy navigation to other sections of the site. It seems particularly useful on mobile devices since it can be cumbersome to scroll all the way back to the top of a long page in order to reach the navigation again.

Scrolling Meter

Our web technical lead, Rick Buck pushed for the addition of the scrolling meter, which gives the user a subtle sense of orientation while reading the page. While scrolling down the page, a small green bar will appear under the navigation that shows how far down the page you are. When the bar reaches the end of the screen, you’re at the bottom. This can give users the ability to know where they are on the page with a quick glance.

scrollingmeter

 

 

Migrating to Drupal

At work, we’re migrating a 10,000+ page site with 300+ editors to a single Drupal installation. At first, the task is extremely daunting, but if you learn to embrace the confusion, stick with it, and plan accordingly, a task as massive as this is absolutely doable and even rewarding!

I started a “Drupal Migration” category on my blog to document our journey to the promise land in hopes that it will help others in the same situation. I’m going to be talking in ideals here, but know that it’s basically impossible to stick to these absolutely. If you make an honest effort, gains will be had, even if you don’t execute perfectly. I’m going to go over where we’re currently at in this journey.

Work hard. Don’t be an asshole. Share what you know.
Brad Frost

Define the problem

Moving to a new CMS for no reason is a great recipe for pain. You need to have clear goals if the project is going to be a success. Some people on your team will be behind the goals more than others, and that’s absolutely fine — that’s life. As long as you know what you’re working towards, you can control the parts of the project that’s within your grasp.

In our case, our main goals for migrating are to have:

  • Reusable, structured content
  • A better editing experience (we’re migrating from Ingeniux)
  • Improved content quality
  • An updated look and feel

I’ve read articles on how people + process + technology is the magical equation for a successful IT related project. It’s naive to try to solve all three on your own. Establishing who is in charge of each of these areas will make the project go much smoother. Plenty of teams complete projects without balancing these three criteria, but I bet they have a few more grey hairs afterwards. The focus of most of these posts will be on technology and process, although I’d be willing to bet I touch on people as well.

Plan it out

Let’s clear something up right away. Drupal is not like WordPress. It’s not a CMS that you can slap a theme on and instantly have a site. It’s not like Webydoo, Wix, Weebly, or any other drag and drop website builder. It’s so much more than that. It can handle anything you throw at it, but you have to have a plan and understand how it works. This takes time. If you’re 2 weeks away from a deadline and you want to jump into Drupal and whip up a complex site, you’re going to have a bad time.

Since that’s out of the way, let’s talk about planning. When you’re migrating to Drupal, you’re not just shoveling content over from your previous CMS. If that’s your plan, you’re doing it wrong! I’d assume you want to move to Drupal in order to take advantage of how Drupal handles structured content. What you’re really doing is building a data layer for your entire organization. It’s so much more than a CMS.

Drupal and content strategy go hand in hand. Being able to think abstractly about your content will ensure you get the most out of Drupal. For example, in the context of a University website, what is a department page? What does that piece of content consist of? If you want to pull information in from other areas of your site, mapping out the structure of your content is absolutely vital. Nail it down, have meetings, have arguments, just figure it out. In our base case, we decided departments consist of:

  • A featured image
  • Positioning statement
  • List of degree programs
  • List of faculty
  • Student opportunities
  • Outcomes
  • List of events
  • List of announcements
  • Contact information

Items listed in bold refer to separate pieces of content which all consist of their own pieces. For example, abstractly, a faculty member might consist of:

  • Photo head shot
  • Full name
  • Title
  • Research interests
  • Department
  • Office hours

I could go on, but I hope you see my point. If you can think abstractly about the different pieces of content on your site, Drupal can help you weave this information together into something useful. I’d highly recommend reading Palantir’s Plan or Perish blog post. They do a fantastic job of explaining the importance of planning.

Helpful resources

Dare to fail

Unless you are a Drupal expert, it is very likely that your first try will be less than ideal. Drupal is a powerful, yet complex system. Give yourself time to learn the platform. Make mistakes. Break shit. Learn what doesn’t work. Acquia has a free development tool that allows you to mess around with Drupal on your local machine before committing to a live site. It’s much better to break stuff in a development environment than in production. The more times you fail, if you learn from it, the closer you are to succeeding.

Reach out for help

Drupal has a robust community of professionals that, in my experience, have been super helpful. To avoid a RTFM response, I’d recommend playing around locally and learning the ropes before reaching out to the community. Not because they won’t try to help you, but because there’s certain concepts that you learn about Drupal only after experiencing it first hand. Drupal.org is kind of a mess, but there’s lots of very useful information there. Take the time to learn.

Once you have a decent understanding of how some popular modules work, reach out to the community for clarification of how to reach your goals. I’d recommend having a good grasp of how the following modules function before you can really benefit from the community’s help:

  • Ctools
  • Views
  • Panels
  • Context
  • Organic Groups
  • Page manager
  • Am I missing any?

As I said earlier, Drupal is complex, but learning basics about the system will reap major benefits when you go to implement your site. Also become familiar with the following Drupal concepts:

  • Entities
  • Nodes
  • Contextual arguments (within Views)
  • Relationships (within Views)
  • View modes
  • Theme layer basics

Helpful resources

I’ve recently re-discovered the treasure trove that is IRC. IRC is where a lot of community members hang out, talk about Drupal, and help people with questions. I’ve had some great success in asking questions in #drupal, #panopoly, and #drupal-support channels. I’d highly recommend downloading an IRC client for your computer — or use KiwiIRC if you want to try it out — and logging into Freenode.

Wrapping up

That’s currently where we are in the process. We’ve hammered out most of the project requirements, got our hands dirty in a Drupal development environment, thought abstractly about our content, and gotten involved in the community. You may be thinking that’s a lot of work for still not having a live production site.

I’d agree that it’s a lot of work, but I’d rather measure twice and cut once.

Using automation tools to deal with rem support in older versions of IE

We all know the wonders and joys of working with older versions of IE, namely < IE9. While I see a lot of sites are kind of throwing their hands up in the air when it comes to legacy IE support, I think its necessary to at least make sure your content is accessible. It’s a little irresponsible to throw up a message saying “Sorry, your browser is old. Download Google Chrome”. At the very least, you could serve them a print style sheet so they could read the content. While IE8 is dying a slow death, it still has a good amount of users.

I’ve been using rems in conjunction with ems now to give myself a consistent spacing unit when coding a website. As with all handy CSS properties, IE8 doesn’t support it so we have to look elsewhere. You could either a) Write pixel fallbacks before each time you use a rem.

h1 {
  font-size: 48px; /* for < IE8 */
  font-size: 3rem; /* for newer browsers */
}

IE will ignore the rem part but will pick up on the

font-size: 48px;

If this works for you that’s fine, but I’d rather have a script automate this process. That’s where grunt and rem_to_px comes in handy. My current grunt task is set up like so:

rem_to_px: {
  options: {
    baseFontSize: 16,
    removeFontFace: true,
  },
  dist: {
    src: ['source/css/style.css'],
    dest: 'public/css/ie/'
  }
},

The task will create a stylesheet where I told it do in

dest

that is the same filename as what is declared in

src

. This stylesheet will only contain rem to pixel substitutions. Then, in my HTML it’s simple to drop in a conditional statement to check if the browser is less than IE8. If so, I’ll include the stylesheet created by the grunt plugin.

<!-- link to the normal style sheet -->
<link rel="stylesheet" href="public/css/style.css">

<!--[if lte IE 8]>
<link rel="stylesheet" href="public/css/ie/style.css">
<!--[endif]>