Hello everyone, and welcome to Front End Center.
Just because it’s the holiday season doesn’t mean there’s any reason to take it slow! In the last episode I went over the bigger picture of Front-end Architecture being my focus to start 2017. I’ve had the opportunity in the week since to begin a head start on the process!
As I assemble the many, many facets of a proper front-end architecture, I want to break them down here on Front End Center. Depending on the pace of my work, that may mean week after week of architecture related episodes. Some of the work, though, may not merit an episode to speak of. There only need to be so many tutorials on how to set up workflow environments.
When I have something of particular interest, I will make record of it here. This week, we’re starting at the base of the architecture and figuring out the rules that will shape the rest of the work.
The ever-present challenge of front-end work means that, for better or worse, many choices at this stage will be somewhat arbitrary. While we have quantifiable goals which we can identify per-project (such as specific load times or accessibility guarantees), there are always multiple right answers to get there.
As such, much of the legwork in creating a front-end architecture has to do with the process of building as much as it does with the end product. A well-executed architecture may have an even longer run-up time than a haphazard project that produces similar end products. The difference emerges the instant you need to easily understand, update, or expand the work done, though.
For that reason, I’ve started with a focus on how the CSS of the architecture will be handled. Last time we discussed CSS, we looked at the concepts of Object Oriented CSS, as well as the Block Element Modifier naming system. Those are coming back into play, but aren’t the only tools on hand.
First, we need to look at existing patterns in CSS, especially as they pertain to large, complex projects that need to be maintained over time.
Inheritance and specificity are baked into Cascading Style Sheets as methods of applying styles to elements. For quite some time, CSS best practices have focused on minimizing repetitious code and avoiding verbose class and ID declarations. On the useful end of the spectrum, this meant selecting all h2 headers that were inside div’s classed “blog-feed”, for example! On the horrifying end of the spectrum, we encounter monsters that style every “a href” link within a div that’s inside another div classed “portfolio-side-bar”, which is inside a table-cell, inside a table, inside a flexbox with the ID of “content”.
Not only is this sort of descendent string terrifying to parse out, but it can also lead to confusing and unpredictable ways for your work to break during updates. If you change one thing in a CSS file or HTML template, you don’t know how that incredibly specific string of selectors may or may not be effected. Once you have tens or hundreds of such selectors, good luck. Updates become a game of web-based roulette.
Instead, there’s a growing trend of using “flat” CSS. If these complex selectors are “deep”, flat selectors are intended to focus your efforts and keep the unintended cascade fallout to a minimum. There are valid arguments that are concerned with the fact that excessive use of these flat classes completely negates the very cascading function of CSS. Like any good tool, though, flat CSS class structure is best used in moderation.
To understand what should be considered moderation, we need to have a better understanding of how the overall CSS is used as a design system. Ideally, a proper system would mean that even after we’ve finished an entire project, it would be easy to expand and alter the existing code base for unexpected needs. Have a new reach-out campaign, or an external team that wants to leverage your design for completely different content? A proper design system makes that possible.
The underlying bones of the design system I’m building can be sorted into two pillars: the layout and the components that fit within. The layout has been an exercise in creative problem solving and defining the line between reliable and not-yet-widely-supported. The amount of code that goes into the layout is small and specific compared to building the rest of the project.
The role of the layout is to organize and control the vertical and horizontal positioning of any components placed within. It’s focused on uniform rules, not exceptions. In other words, you’re not going to have a large number of variations, margin tweaks, and more hiding within the code. Instead, you’ll have a succinct and helpful set of containers to place content within. In many cases, this results in a grid of rows and columns, preferably customized to your specific site, rather than as robust as something like Bootstrap.
To make the most of this specific tool, I’ve been working on a layout that uses flexbox. Rather than a series of floats, display attributes, and extra considerations, flexbox allows for unique control of content position and even placement order. It minimizes the amount of code necessary to be written, while maintaining widely supported functionality. Adding auto-prefixer into the workflow further ensures almost ubiquitous coverage.
Another trend I’ve been testing is the use of HTML5 data-attributes as pseudo-classes. For those unfamiliar, in addition to the usual tags you find on an HTML element, like class, ID, etcetera, you can add custom tags. These are formatted with the word data, a dash, and then whatever string you decide after. Data-theme, data-display, data-potato. You get the idea.
The specific use for these data-attributes in the spec is to hold additional data that may not be user-relevant this moment, but could be used in the near future. A list of color options, or contact methods might be good examples of what you could store in a data-attribute.
With the correct notation, however, these data-attributes can also be used just like classes for CSS purposes! As always, warnings first: this is a slippery slope. Unlike actual CSS classes, HTML data-attributes are not NEARLY as optimized for this purpose. Excessive use, over specificity, or incredibly large pages (like, thousands of DOM elements), will make this lack of optimization readily apparent. When used with precision and care, however, data-attributes’ flexibility becomes a powerful tool.
In some CSS methodologies, the idea of layout styles are denoted with additional information in class names. You may use layout-column-2, or l-column-2 to minimize extra characters. When using flat CSS structure, though, this could result in a number of lengthy class names all on a single element.
Instead, I’ve opted to use specific data-attributes to apply any layout styles. At a glance, a developer can see if there are component styles on an element via a class, or if the element is dedicated to a layout. Anything with, for example, data-layout=”col-2” is always going to have that recognized layout role. No need to worry about ensuring the layout is the second class-name out of six, or alphabetized, or anything else. With minimal impact to the end product’s effectiveness and a much more legible development environment, I count this as a win.
Now, we’re onto our components. The components are small pieces of content that fit within a layout. They’re not particularly opinionated about their specific layouts, and leave their parent element to decide that. These could be content cards, slider images, individual logos, and more. When styled appropriately, they can be dropped into a layout that places them side-by-side in a single row with 6 columns, or a thin, tall container 2 wide by 3 deep. They don’t particularly care, and will fill their layout appropriately without you adding or changing extra code.
Since we now have flexible layouts and un-opinionated components to put within, we’re now well on our way to a modular and reusable CSS architecture. Useful tools like the BEM naming methodology still need to be applied at the component level, but that’s a step deeper into actually applying the architecture than I’ve reached at this point.
With that said, time to dive back in and make some progress towards a more complete architecture solution! I’ll look forward to relaying the progress next week. Until then, thanks for listening! This has been Chris Landtiser and Front End Center.