From Styleguide to Final Product
In the first article in our series we talked about how styleguide-driven development (SDD) and decoupling both serve many of the same goals, and SDD can do so in a way that avoids the many challenges of decoupling. Now we’ll get deeper into the details of SDD and how we use it to build a website.
This post will walk you through the process from planning to prototyping to developing, theming, and QAing the final product.
First, plan the work
During a project’s discovery (planning) phase, we break the project down into bite-sized pieces; pieces small enough to build. Part of that includes isolating components. I’m not sure if components is yet a standard word, but it’s a logically and functionally independent piece of the page. One or more components will be placed into a region of the page. A component can be a menu, a “block”, a “module”, a list, a field, etc.. Below is an example from a full-page comp, showing a single component that we called Image — with rollover.
This is a bit more complicated than it first appears because there’s a complex hover effect.
We’ll start by breaking this down into three user stories:
1. Admins see Image — with rollover components after creating them (prototype)Acceptance CriteriaHTML/CSS prototype of component described in the development ticket should appear as comped (across multiple breakpoints). If I hover over the component with my mouse (or tap on a touch device) If I then hover over the arrow If the viewport width is less than 768px If the viewport width is less than 480px Technical notesSee .PSD for hover elements |
2. Admins see Image — with rollover components after creating them (develop)Acceptance CriteriaGiven that I’m an admin on any customizable page
If I view a page with this component Technical NotesThis should be a Fieldable Panels Pane |
3. Admins see Image — with rollover components after creating them (theme)Acceptance CriteriaIf I visit a page that contains this component |
Why three user stories for one component?
This is ultimately part of how we’re able to resource our projects well in advance and keep things consistent through the life of the project. By splitting tickets this way, we can determine and plan for how many hours we need for each, e.g. Project X will run from Aug 1 – Oct 31. It’s estimated at 600 hours back-end work and 400 hours front-end work. We then go even deeper: Gertrude is working 15 hrs per week on project X and 10 hrs per week on project Y.
There’s a second benefit where this split allows us to do the prototype in an earlier iteration than the dev and theming. This means that right from the start of the project, while back-end developers are working on the foundation, front-end devs (we call them The FEDs) can be working on the first set of prototypes.
Prototype
After looking at the series of design comps (maybe some are “mobile” and some are “desktop”), there are generally three things we’re trying to accomplish when we get into the process of responsive prototyping within our living style guide. The goal here is to provide the cleanest model of how the component should be structured, and it will be used as a guide during actual development.
First, we try to determine how to build it with the absolute least markup possible. This means first looking at the component at the smallest possible width. We then add required markup only as necessary to fulfill the needs of the component’s layout as things change visually for increased browser widths. The same approach applies when writing Javascript for the prototype.
Second, we try to anticipate and prevent bloated CSS by using our own brand of DRY methodology (Don’t Repeat Yourself) in assigning class attributes to our markup. The idea is to create reusable classes that describe the component as a whole on its container markup, as well as grouping and identifying the inner parts of the component. We try to adhere to the naming conventions used in BEM methodology (Block, Element, Modifier) for writing scalable and modular styles, as demonstrated in the “flower” example by John Albin Wilkins. By doing this, we can really reduce the amount of long, overly specific CSS selectors (perhaps via Sass code nesting), which leads to faster compile times and leaner final CSS. Here’s an example of ideal rollover component prototype source code, as seen within this case study’s living styleguide:
<div class="component image-rollover"> <img class="image-rollover__image" src="https://placeimg.com/654/476/animals" /> <div class="image-rollover__overlay"> <h2 class="image-rollover__title">Living on campus<a class="arrow" href="#"></a></h2> <p class="image-rollover__content intro">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent posuere tincidunt nisl et eleifend.</p> </div> </div>
Lastly, sometimes we’ll fake things with CSS in the prototypes that will eventually be provided via backend functionality. For example, “responsive” images used in banner/hero image type components. In the prototype it’s usually good enough to use an image and stretch it fluidly, as big or small as it needs to be, using “width: 100%” and/or the common “max-width: 100%” approach. At some point that will be done using a proper solution, like Drupal’s image styles and the Picture or Client-side Adaptive Image modules.
Develop
The back-end developer’s job is to build the prototyped component in Drupal and hook it up to an admin interface for managing its content. Depending on the project and the context, it could be a fieldable panels pane (FPP), a CTools plugin, a BEAN, a block, a theme function, a field formatter, a View… there are all sorts of ways to accomplish the same thing, and picking the right one could be a blog post itself!
In our example, though, we’re working with an FPP, as specified in the technical notes of the ticket. Looking at the prototype, we determine which pieces need to be editable, and we build fields for those pieces. Here, we were able to use the Fields UI for this (but sometimes we’ll need a custom form).
More often than not, we write some hook_form_alter functions to make the admin experience as smooth as possible – things like conditional fields, or programmatic default values. This one is simple enough already, though. Thanks Drupal!
Now, we can input the data required for an instance of this component, and we can make a few samples to work with. Next, we need to override the default markup and get it close to the lean markup provided in the prototype. Since our FPP will be rendered in a panel pane, we implement hook_panels_pane_content_alter, hook_theme and a custom theme function:
/** * Themes an image with rollover FPP. */ function theme_edusa_media_image_rollover($variables) { $output[] = '<div class="image-rollover">'; $output[] = render($variables['image']); $output[] = '<div class="image-rollover__overlay">'; $output[] = '<h2 class="image-rollover__title">'; $output[] = $variables['title'] . l('', $variables['url'], array('attributes' => array('class' => array('arrow')))); $output[] = '</h2>'; $output[] = '<p class="image-rollover__content intro">'; $output[] = $variables['summary']; $output[] = '</p>'; $output[] = '</div>'; $output[] = '</div>'; return implode(PHP_EOL, $output); }
Theme
It’s possible there’s not much left to do during the theming phase if the prototype markup could be faithfully reproduced during development without any snags. However, sometimes it’s easier to make a quick change to the prototype to accommodate something that would have otherwise taken a while to do on the back end. The theming phase serves as a moment for us to tie up any loose ends on the front end, including using the Fences module to set proper wrapper HTML elements (or removing them altogether) for any field content used in the component to match what was used in the initial prototype.
This is where we work in-browser with the fully developed version of the component, and fix any issues on the front-end due to how it appears when real-world variables come into play: the size of the viewport, the existence and length of content, or other edge case scenarios. Occasionally, we’ll need to go back to the style guide and adjust the prototype’s markup, CSS, or JS to keep it in sync with the completed, functional, and responsive version of the component. This is the frustrating part of the process, when the styleguide breaks for seemingly random reasons. We’ve got some ideas for how to fix this problem. We’ll explore these ideas in part 3 of this series.
At this point, we’ll do a little mini-QA session to check things against the current versions of our target browsers and a few popular mobile devices. This allows us to catch the majority of browser or device-based issues early while the component is still fresh, before a more thorough QA process at end of the iteration.
The Final Product
And here’s the component in action:
https://educationusa.state.gov/experience-studying-usa/experience-studying-usa
The Only Thing You Can Count On Is Change
Regardless of whether you’re doing decoupled Drupal, or styleguide-driven development, you need to have interdependence between the front-end and back-end team. If there’s one thing that we can count on, it’s that partway through the project priorities will change. Maybe now that we see the site in action we realize that it needs to be reworked a bit; maybe someone forgot about feature X that is going to end up taking 25% of the project budget; maybe the client organization needs to pivot. Whatever the reason, we need to have a process that can account for change. And keeping the front-end and back-end teams in sync, neither getting too far ahead of the other, is crucial. If we have to start dropping features, our options become limited if we have many things half-built.
Conclusion
Style-guide driven development is not without its challenges (what is?), but we hope you have a good idea of what you’ll need to make it happen. In part three of this series we’ll explore how we might deal with the problems of styleguides getting out-of-sync with reality and styleguides that randomly break.
This article was a team collaboration by Amanda, Andy, Dave, Jack, Kim, Oliver, & Sarah.