DEV Community

Ash
Ash

Posted on • Originally published at sidigital.co

Bringing new CSS techniques to production

Hi Dev.to community. I've been lurking here for a while, but haven't posted anything yet 🙂. I've wanted to find a community like this ever since the Forrst days! A month or so ago, I was able to write an article about new CSS techniques for the Si digital blog. This is a cross post of that article.


If you're anything like me, the first time you realised that CSS Grid and Custom Properties were real features that browser makers were really working on implementing, you were giddy with excitement. If you're not familiar with frontend development, those words probably don't instil much joy in you at all. Perhaps they even prompted a yawn. Let me explain...

We—people making websites—have been designing and building responsive websites for the best part of ten years. Responsive websites are designed to be accessible at any display size we can reasonably anticipate being used to browse the web. That could be anything from the smallest mobile phone, or even a watch, to a large desktop display. Part of the mindset we must adopt is that we don't really know what devices our visitors will use. Today, you'd be hard-pressed to find a website that isn't responsive. Indeed, responsive websites are so ubiquitous that you may not have even noticed that some websites aren't responsive.

With responsive web design, the processes behind making a website became more complicated. Where once we might have cheated, building a website in its exact manifestation at a single display size, we started to discard our assumptions about how websites are accessed. Our focus moved from precision and pixel perfection to fluidity (layout naturally stretching to fill the available space) and adaptivity (layout changing at specific sizes, or breakpoints, to make the most of the available space). Building single viewport websites was never a good idea—the web is naturally flexible, after all—but it became widely practiced, even necessary in some cases to achieve increasingly ambitious visual designs.

Adapting to both display size and browser capabilities

Rapidly, web designers and developers came to accept responsive web design as the way. Despite the sound theory behind it, the challenges of implementing responsive websites have not always been easy to contend with. The battle between web developers and patchy or inconsistent browser capabilities is a story as old as time itself—or, at least, as old as my career in this field. When building for the web, we don't only have to consider the multitude of device form factors and sizes in use, but also the wide spectrum of browser capabilities.

Just as we must acknowledge the web is edgeless—that there is no single display size for us to target—we must also accept that we have no control whatsoever over how a website will be accessed. It's a fundamental characteristic of the medium we are building for.

In terms of CSS support, the most widely used mobile browsers have typically1 been more complete than Internet Explorer (IE), and have adopted new features faster. It's sometimes left me feeling that I have to pick between two options for how I'm going to hamstring projects I work on:

  1. Should I deliver an excellent, future-proof, responsive experience for mobile devices and modern web browsers, or
  2. Should I deliver an enhanced experience for IE that will be acceptable for mobile devices and modern browsers, but is frozen in time.

The answer usually lies somewhere between these two options. We create a solid baseline experience for all web browsers, which we can layer enhancements on for more advanced browsers. This technique, known as progressive enhancement, is fairly elegant thanks to the way CSS works, and is a key tenet of frontend web development. Just as we must acknowledge the web is edgeless—that there is no single display size for us to target—we must also accept that we have no control whatsoever over how a website will be accessed. It's a fundamental characteristic of the medium we are building for. Browser capabilities, device CPU power, and network conditions are all out of our control.

Technically, progressive enhancement in CSS is fairly straightforward. Web browsers ignore declarations they do not recognise, so as long as we specify a fallback declaration wherever we make use of a property or value that isn't supported everywhere, we can provide a progressively enhanced experience.

Here is an example showing how we can progressively use Custom Properties, while still providing a functional experience for less capable web browsers:

:root {
  --spacing: 1rem;
}

.jumbotron {
  padding: 1rem;
  padding: var(--spacing);
}
Enter fullscreen mode Exit fullscreen mode

Web browsers that support Custom Properties will use the dynamic --spacing variable, which is incredibly useful because we can change it at run time (for example, in a media query that responds to the current viewport size). Less capable browsers will fall back to the constant value of 1rem.

CSS also provides feature queries, which are a bit like media queries, but allow us to test browser capabilities, rather than visual properties such as viewport size. Feature queries are useful when we have more complex groups of styles to apply. For example, if we are composing a layout with CSS Grid:

@supports (display: grid) {
  .product-group {
    display: grid;
    margin: 1rem;
    grid-gap: 1rem;
    grid-template-columns: repeat(3, 1fr);
  }
}
Enter fullscreen mode Exit fullscreen mode

An example of how we might apply a collection of styles only for web browsers that support CSS Grid.

Managing fallback styles

Despite progressive enhancement being fairly simple to achieve technically, we still have to think carefully about how to apply it. I aim for a baseline experience that is as simple as possible; for example, layouts might occupy only a single column. Content will be rendered linearly, based on the order it appears in HTML, and some visual flourishes may not appear. Websites should be perfectly accessible in this form. If all else fails, and CSS and JS do not work, visitors should still be able to make use of the semantic HTML that forms the skeleton of the frontend. Assistive technologies that aid visitors rely on the presence of semantic HTML, so it's extremely important.

As is the case for so many questions that face us during the development process, we must consider who will be using our website before settling on which techniques and fallbacks to use. In many cases, it's acceptable to make use of modern techniques coupled with simple fallbacks. In others, a significant segment of our audience might be using less capable web browsers. In such a scenario, it may be preferable to focus on providing an enhanced experience using older techniques. Consult your site statistics to determine where your time is best invested.

In either case, it's important to be cautious of creating many complicated forks in your CSS. Each fallback has a maintenance cost. Sometimes it might be tempting to fork an entire layout, so that we can deliver some estimation of the intended layout in all web browsers. I think it's important to avoid this wherever possible; the maintenance cost alone of this approach can be great. There's an entire mosaic of different devices and browsers that will be used to visit a website, naturally there might be some differences in the way a site appears.

The new frontend baseline

Browser vendors are releasing updates faster than ever. IE usage is steadily diminishing, and Microsoft's next web browser will be evergreen: updating continually and automatically. We are perhaps only a few short years away from being able to deliver websites targeted squarely at modern web browsers. For some projects, this is even a reality today. As browsers improve, we can slowly strip away fallbacks from our arsenal. Of course, there will always be new techniques with varying support, but we are close to establishing a new baseline collection of techniques that will be available in most web browsers. These techniques (such as Grid, Custom Properties, Flexbox, and Calc) present a marked change in the way we build websites. They empower web developers to create more robust and visually ambitious websites that scale smoothly between display sizes, with less code than ever before.

In this post I’d like to call special attention to two new CSS features: Grid and Custom Properties. These features are very exciting because they finally provide answers to really big challenges that have existed for as long as we've been making responsive websites.

For newcomers, Grid, Flexbox, et al present a significantly simpler entry point into web development. The decade or more of Web Platform trivia many developers have accumulated is difficult to explain. We have slowly acquired a vast amount of knowledge in dealing with quirks from Stack Overflow answers and frustrating IE testing sessions. I find much of this trivia difficult to rationalise even to myself. Being able to dive directly into new techniques really does make frontend development more approachable.

Grid

When I started making websites in the mid 2000's, the concept of CSS Grid was pretty much unimaginable to me. We had only a few techniques available for composing content horizontally: namely, Floats. By the late 2000's, Table display was widely available, which presented some interesting techniques for layout, yet didn't feel quite right for the web. In a world of responsive web design, it felt like our hands were tied by the limited features available.

Implementing a responsive layout? Choose a breakpoint, add some Floats. What about a grid with varying column counts, gutters, and vertical alignment of items? It's possible using inline-block or Table display combined with negative margins, but a little touch and go.

If you've ever had to clear a Float, type display: table, or make use of faux columns, you probably agree that CSS Grid feels like magic. We have been given incredible power to control almost every aspect of layout in CSS. Between breakpoints, we can reorder and rechoreograph components as necessary.

In 2011, Trent Walton wrote about content choreography, and how we might interdigitate content at various display sizes. But at the time, there was no clear technical path for cleanly achieving this. If you've read Scott Jehl's Responsible Responsive Design, or are familiar with Filament Group's work, you may know of the ‌AppendAround pattern. This pattern, combined with a small JavaScript utility, gave developers the ability to shift content around the page at given breakpoints.

I can't speak to whether AppendAround was widely adopted, but I personally found it fiddly to use. Additionally, it delegated layout responsibilities to JavaScript, which has generally been accepted as a bad idea. But what it achieved was necessary for many websites: the ability to interdigitate components, something that at the time required HTML markup be physically shifted about the page2.

CSS Grid gives us incredible control over layout. Compare Trent's article with Thoughbot's 2018 article ‌Concise Media Queries with CSS Grid to see how much the Web Platform has advanced. CSS Grid makes an entire class of supremely flexible layouts easy to achieve on the web. Now we can reorder components using CSS alone; we actually have a good way to implement seemingly trivial layout changes. Not only can we implement more ambitious visual designs, we find our layouts are more robust, HTML is cleaner, and less code is needed.

Interestingly, Grid also presents unified concepts that allow designers and developers to communicate more effectively. Grids are not new to the web; they have long been emulated (the 960 Grid System, for instance, has existed almost as long as I can remember). The existence of CSS Grid, however, means that we have the power of a fully fluid, web native, grid system—without working against the web's grain.

Fallbacks for CSS Grid

With so many benefits, it's difficult not to be enticed by CSS Grid. Soon, I suspect it will be the de facto technique for creating layouts on the web, so it's important to learn regardless of whether you choose to use it in production yet. At Si digital, we have started to sprinkle CSS Grid into websites where possible.

There is no magic method for making Grid layouts work on unsupported browsers. Its capabilities simply cannot be retrofitted to work with older layout techniques, so typically we provide a simpler alternative for web browsers that do not support Grid. Sometimes an alternative can be provided with Floats, Table display, or inline-block. I am very cautious of creating complicated forks in CSS to coerce a layout into looking the same everywhere. Your technical choices should be guided by your website's usage stats. If you need to provide an enhanced experience for less capable web browsers, it might be better to hold fire on Grid for now.

Autoprefixer does have the ability to transpile Grid declarations to the equivalent -ms-grid properties for the most recent versions of IE. Unfortunately, the IE implementation of Grid does not match the current spec, so it's far from a sure shot. In my experience, Autoprefixer works well for a small number of simple Grid layouts. Most are better handled with a feature query.

Custom Properties

CSS Custom Properties is the other feature that has made me fall in love with frontend web development again. If you've used a CSS preprocessor (such as Stylus or Sass), you probably at some point came to the disappointing realisation that there's no way to update a variable in a media query. That's because the variable only exists at build time, at which point the preprocessor inserts the static value into the output CSS. Custom Properties not only bring the convenience of variables to native CSS, but allow variables to be updated at run time.

Media queries now have the ability to update variables used across our stylesheet, answering many questions about how we should structure CSS in a responsive world. Typography, layout, and even colour schemes can now be modified in a single location in response to media queries that we before would have peppered across our CSS.

I've found it really effective to move values such as spacing to Custom Properties, making it simple to keep components spaced and positioned consistently across many display sizes. For a long time, I've experimented with CSS preprocessor mixins to achieve this, but it simply wasn't possible without creating very bloated output CSS. Now that Custom Properties are widely available, we have began using them in production.

Fallbacks for CSS Custom Properties

When discussing fallbacks for Custom Properties, we could be referring to a couple of scenarios:

  1. The variable is not defined.
  2. The web browser does not support Custom Properties.

Here, we are most concerned with browser support. Non existent variables can be addressed by providing a fallback to the var() function. Browser fallbacks, however, require a little more thought…

Technically, fallbacks are simple to create. Web browsers skip CSS declarations they do not recognise. We simply have to provide a constant value to fall back to for less capable browsers. To do that, we must make some assumptions. For example, if a Custom Property deals with responsive layout, we could choose a desktop applicable constant to fall back to. Most mobile browsers we target support Custom Properties, but IE—a desktop browser—does not. The trade off is that some responsive styles will be unavailable for these users, no matter what size their browser window is. It’s important to check website usage before we can safely select a fallback.

:root {
  --spacing: 1rem;
}

@media (min-width: 60em) {
  :root {
    --spacing: 2rem;
  }
}

.main-content {
  padding: 2rem;
  padding: var(--spacing);
}
Enter fullscreen mode Exit fullscreen mode

An example showing a fallback for a Custom Property. For browsers that do not support this feature (typically desktop web browsers), we fall back to the largest value of 2rem.

Improving workflow

Developers often find themselves wondering "Can I automate this? Is there a good abstraction?". Be wary that abstractions are frequently more complicated and brittle than the problems they actually solve: typically that code is repeated. But I couldn't help wondering if preprocessor mixins could be used to simplify our usage of Custom Properties.

I experimented by creating a Stylus mixin that creates both the Custom Property consumer and fallback declarations at the same time. It works under the assumption that a Stylus variable with the same name as the Custom Property exists.

customProp($propName, $varName)
  {$propName} lookup('$' + $varName)
  {$propName} s('var(--' + $varName + ')')
Enter fullscreen mode Exit fullscreen mode

Let's take a look at the mixin in use:

// Firstly, we set our Stylus variable that will be used as a fallback.
$spacing = 2rem

// We define our Custom Property in the usual way.
:root {
    --spacing: 1rem;
}

@media (min-width: 62em) {
  :root {
    --spacing: $spacing;
  }
}

// When creating a declaration that references a Custom Property, we use the customProp mixin.
body {
  customProp('padding', 'spacing')
}
Enter fullscreen mode Exit fullscreen mode

Although I don't think I'd recommend this approach, it's interesting to explore methods that improve our workflow. I'm increasingly inclined to argue we should reduce usage of CSS preprocessors. Repeating declarations allows us to be explicit about fallbacks and, importantly, stops us building up an esoteric layer of preprocessor code that makes our stylesheets difficult to reason about.

The relative ease of providing fallbacks in vanilla CSS means that we are often able to bring Custom Properties into production use today. They are an extremely powerful way to style websites that simply has not been possible up to this point in time.

Fully embracing the new baseline

It’s extremely exciting to imagine what will be possible when we can commit fully to CSS Grid and Custom Properties. That reality is possibly only 1–2 years away. Using Grid to control large parts of our layout, without worrying about fallbacks, will not only help to make code more maintainable, but make a whole new class of layouts possible to achieve simply. Jen Simmons' Experimental Layout Lab is a fantastic glimpse into the type of layouts that are now possible to implement for the web.

Subgrid is hopefully just around the corner, and will bring even more power to CSS. The most significant item that remains on my wish list for the web is container queries: the ability to respond to the actual size of a component, rather than the entire display size. Until then, responsive design remains a challenge.

Many aspects of designing for a sprawling, uncontrollable, and flexible medium remain the same, but the web’s grain continues to change. In recent years we've seen exciting new abilities that were beyond my imagination when I started building websites. They have changed what it means to design and build for the web. I can't wait to see the advances in visual design and technical implementation as these abilities become available to more people.


1. It's true that not all mobile browser match this description (Opera Mini, for instance). For better or worse, I've infrequently had to cater for such browsers. Don't forget that many mobile devices have extremely limited power.

2. Table display did bring us some limited reordering capabilities. See Colin Toh's The Anti-hero of CSS Layout - "display:table". Colin summarises "I have to emphasize that CSS Table is not the silver bullet for layouts". It's still neat to take a look at what could be achieved in 2014.

Top comments (0)