Category Archives: CSS

Reality is messy

We like to believe that the right framework, method, approach, or conventions will allow us to create perfect projects. Our code will be beautiful, pure, performant, and maintainable. Outside of some developer blogs however, this is often not the case.

Reality is messy.

Some people are fortunate enough not to have to deal with this reality on a daily basis. There are people who work for browser-makers. Their projects are not most projects. There are people who work for large-scale and popular “startups”, who have the luxury of focusing on a limited number of components. Their projects are not most projects. Although we can (and do) learn a lot from posts on Medium about month-long experiments in link underlining, many of us have pressing deadlines. Processes can be messy because they involve other people and limited resources, tight budgets, difficult stakeholders and ridiculous time constraints.

Outside of the product world, many of us work in creative and/or technical services. Our job is to help our clients. These clients have concerns during the design and development process that we need to address. Sometimes, we can’t do everything exactly as we would like. Client needs trump our own.

I’ll give you an example: a project I worked on where my job was to help take an existing desktop-centric design and make it responsive. My task was to determine exactly how everything would work responsively. My deliverable was a series of more than 20 design comps built with HTML and CSS. The comps were themselves responsive, so stakeholders and the developers knew what the end result should be.

Here’s the thing: there were extreme time constraints. We basically had two months to get this fairly complex website responsive. In order to do this, the developer would change as little HTML as possible, as this would mean rewriting components all over the place. Yes, we wanted to see that happen, but it wasn’t feasible. So I used the existing HTML whenever possible, and I cringed while doing it, because holy shit, this HTML (with all due respect to the developers; you know CMSes). But it was practical and allowed the developer to reuse a lot of my CSS. Which was a lot more CSS than I would have had to write if I were able to rewrite the HTML.

Could I have said no? Sure, but I wouldn’t have been helping anyone, least of all myself, by doing so. This client has interesting challenges, and I wasn’t willing to just say no to four months of work with them because of a tight deadline.

Another issue I had to deal with was working in weekly (!) sprints. Coming up with responsive strategies for each component of certain screen types and then prototyping them in one week was not easy. In order to do it without creating conflicts and still get things done on time, I had to namespace each logical group of components, like this:


.product {
  /* Styles, including media queries, here. */
}

.account {
  /* Same idea, different logical group */
}

While doing this for each round of logical prototype groups allowed me to avoid conflicts with prototypes I had done or those I would do in future sprints, it made me repeat myself across those blocks, since I had literally no time to constantly refactor. And it was not my job to create the front-end code, though I knew the developer was using and altering snippets from my CSS to save time. Result: my comps had way too much CSS.

Could I have an approach like BEM? Yes, I could have. But since some CSS methodologies eschew inheritance, I lose a huge time benefit. And remember, HTML changes were required to be minimal, and that’s not feasible when choosing a CSS approach that involves moving the dirty work into class attributes.

What’s your goal?

In the project above, the thing that kept me sane was focusing on the specific reason I was asked to join the project: to decide how everything should look and work responsively, and to visualize this for stakeholders and the developers, in such a way that they could actually experience it on actual devices so that it is clear what needs to be done.

That had to be my focus.

We finished the work in two months with just a few people. And a phase two was planned to go in and refactor, to improve lots of things, including performance. That’s the right time for optimizing HTML and CSS, and improving things like performance. Ideal? Certainly not. Realistic based on the needs of the client? Absolutely. This particular client sees their website (100% of their revenue comes from the website) as a process rather than a product. I think that’s a healthy way of looking at things. It means they have a responsive site, built within two months time, that customers could enjoy right away. That site, even with sub-optimal HTML and CSS, performed twice as well as the previous desktop version. Customers don’t care about what the source looks like, and phase two, almost underway, is intended for code optimization and other quality improvements.

Messy, isn’t it? It certainly is. But really, it’s often the reality of a service business. It’s natural to try and find processes or approaches that work for every project, but you won’t. And they don’t. Embracing this fact is one step toward pleasing clients, and also helps deal with the frustration that we can’t always make everything as perfect as we’d like it to be. Of course, that shouldn’t keep us from trying.

I start every project with a lofty goal of achieving perfection. I’ve never reached it. I make mistakes all the time. I look back and immediately see things I would have done differently. I try to learn from those mistakes. I try to remember that making those mistakes and dealing with the messy reality of the work, while still trying to do my best work, puts me on a path of constant improvement.

We need to give ourselves a break. I hope I’m learning more and becoming just slightly better every day. I hope you are, too. In our line of work, where everything moves so quickly, that’s something to be happy about.

Here’s to a better imperfect year than the last one.

Choosing between min-width and max-width media queries

I’m often asked a variation of the following question:

Should I use min-width or max-width media queries?

The obvious answer is, of course, “yes”. But you know what they’re asking: which of the two is better?

Those for whom responsive design has become second nature might find it an odd question, and will know that the answer is, “it depends”. But having seen lots of responsive design implementations, it’s clear to me that many designers and developers aren’t quite sure. And I’m happy to share my own opinion of what “it depends” means regarding this particular question.

Desktop first and max-width

There’s a decent number of designers/developers that still think of “the desktop” as their primary design manifestation, with other (generally smaller) sizes as secondary; often these appear as afterthoughts, since there can be significant visual clues as to the amount of effort that has gone into these other screen sizes when compared to their desktop counterparts. Often, when one examines the CSS of these sites, `max-width` is the media feature of choice.

This makes sense. If a design is built desktop-first, then all the CSS for the desktop-ish version of the design has been written, and must be overridden with more CSS for any other breakpoints. If a given desktop-ish width is our baseline and we are unwilling or unable to refactor our CSS, then it seems logical to override what is now our base CSS for all viewport widths with those we only want to apply to smaller widths.

This can lead to a situation I’ve often joked about: writing styles only to undo them later. This is an example I often use (assume .related takes the form of a sidebar):


.content {
  width: 60%;
}

.related {
  width: 40%;
}

@media screen and (max-width: 37.4em) {
  .content,
  .related {
    width: 100%;
  }
}

The above example omits a lot, but I’m sure you get the idea. This approach, when used over a bunch of components, can greatly increase the amount of CSS needed to complete the project. But the main problem is how illogical it is, because when embracing the fact the block-level elements are 100% of their parent by default, then the following makes much more sense:


@media screen and (min-width: 37.5em) {
  .content {
    width: 60%;
  }

  .related {
    width: 40%;
  }
}

Here, we’re making use of the default state of block-level elements, and overriding them when they need to change from the default. Again, it might seem clear to some readers, but it doesn’t take looking at the source of many websites before you understand why I’m clarifying it here.

Using max-width against your better judgement

There are a couple of reasons why, even when you know better, you might deliberately choose to use an approach similar to max-width approach above:

  1. You’re a developer and you received desktop-only, desktop-first, or other-sizes-as-an-afterthought comps from the designer. How can you know? If you’ve only designed or received designs for desktop-ish widths, this is what you’re dealing with. If you’ve got nice detailed desktop-ish designs with a few “mobile” or “tablet” examples thrown in there, this is what you’re dealing with. In these cases, may the max-width be with you, unless you have a budget and/or schedule that allows you to refactor during development.
  2. You’re making an existing website responsive, and the existing CSS is design baggage you’ve inherited and cannot change, for whatever reason.
  3. You’re compensating for the fact that we don’t currently have element queries, and you’re handling this with CSS instead of using a JavaScript polyfill for a non-existent spec.

So, what’s the best to use?

Here’s my clarification of “it depends” for this particular question. And remember it’s just my own opinion based on my own experiences: look at default display of a given element. If you have to override this default for smaller screens, use max-width. If the default is usable on small screens, use min-width, and only when the element needs to deviate from the default. And of course, I recommend letting the content determine where that happens.

A good example of using max-width to override an element’s default display so that it works better on smaller screens is when using tables. Imagine a table that contains too much content to display in its default form on small screens. One approach might be:


@media only screen and (max-width: 30em) {
  .big-table tr,
  .big-table td {
    display: block;
  }
}

This turns each row (and cell) into a block on narrow screens. The table can become quite long vertically and more styling is usually required, but it’s often better than the back-and-forth horizontal scrolling that would otherwise be required to read the content.

In this case, it makes all the sense in the world to leave the table in default form, except for in browsers that understand the media query and where the screen is no larger than, in this case, 30em.

Other elements (I would venture to say most other elements) that have defaults that work fine on smaller screens, only need changing when necessary on larger screens; using min-width is then a solid choice.

In short: let element defaults help determine which media feature to use in your media queries.

Thanks to Brad Frost for reviewing this. He also has a post with related topics.

Conditional multi-column sublists

Some designers are able to operate in that universe where anything goes, where the practicalities of implementation don’t exist. This can actually be a good thing at the beginning of the creative process; without this no-limit thinking, the design process might yield less creativity. Then again, many designers are fantastic at working within constraints.

At some point, though, either designers are confronted with constraints and must accommodate them, or this is implicitly tasked to developers. The latter is often the case, unfortunately. This almost always leads to a series of little development puzzles. “How might I implement this?”

We can do a lot with CSS, but sometimes we need a little help from JavaScript. I consider myself a designer who codes, which, to be clear, means “not a programmer”. Lucky for me, I have programmer friends, and I read a lot.

So while working on a recent project, I encountered a design comp that called for a few adjacent lists of “filters” (read: tags or categories). Each list had a heading above it.

(Note that the following examples are not indicative of the visual design. Note also that they no sense on narrow screens, where the lists could simply flow vertically.)

Lists.

Being as creative as the designer in the sense that I didn’t burden myself with such practicalities as browser support (yet), I figured I could mock this up with Flexbox. Each section containing a header and a list becomes a flex item, and let’s let those wrap if they need to wrap. Easy enough.

Lists with Flexbox applied (CSS).

Lists with Flexbox applied (output).

In the design, some lists were longer than others. Lists with many items were to be split into multiple columns. Flexbox was taking care of the necessary flexibility of the main lists, but what to do about the sublists that are too long? And can we have any flexibility in determining what “too long” means?

A simple solution for splitting a list into multiple columns is CSS Multi-Column Layout. Implementations aren’t totally consistent, and I wrote some time ago about some of those inconsistencies, but the very basics are pretty usable right now as a progressive enhancement to normal content. Lack of multi-column simply yields a one-column list.

If one were to set a specific height to the containing element, multi-column would do it’s thing automatically. But I didn’t like the idea of setting a specific height on anything. A more content-centric approach would be to determine how many items a list may have before it was split into columns.

I’m fairly sure that determining the number of columns as a condition of the number of children is not currently possible with CSS. So in this case, it’s JavaScript to the rescue.

I needed a function that takes whatever element I’m using as a list, plus a maximum number of list items per column, as parameters. It should look at each list, count the number of items in it, and if the maximum number of list items is exceeded, it should add a class to that list. The class allows application of the correct number of columns via CSS.

Here’s the function, after too many iterations, a beer, and another pair of eyes:

Here is the function.

And here’s the result:

Here is the result.

This is not completely bulletproof, but it does allow for some flexibility (“let’s allow 10 items per column instead of five”).

This was a fairly simple problem to solve (though I won’t be competing in the Array.prototype Olympics anytime soon). But I’d like to say this: designers and developers should think about these types of implementation issues together, and that should happen during the design process. Not afterward, when stakeholders have fallen in love with the design comps. This would allow for consensus on the baseline experience (stakeholders tend to see design comps as the baseline). Quick mockups in browser-based tools such as JSBin (which I used for this example) or CodePen could help solidify these types of design decisions, and allow both designers and developers to experience these decisions on actual devices and to design for contingencies as well.

Special thanks to Jake and Heydon for being kind enough to review my example.