Cloud Four Blog

Technical notes, War stories and anecdotes

Will someone do this on mobile?

A frequent question that product owners face is whether not someone will do a particular activity on a mobile device or not.

In my experience, people often arrive at two answers based on context.

  1. When looking at your own product:
    Of course, no one would ever try to do this on a mobile device.
  2. When using someone else’s product:
    Of course, this should work on mobile.


Design accordingly.

Responsive Images, Part 10: Conclusion

Phew. We made it! We’ve come to the end of the Responsive Images 101 series.

Before we part ways with this series, I want to pass along some tips, resources and final thoughts on where responsive images are heading next.

Responsive image audits

Were this a book, I would have devoted a chapter to responsive image audits. It is the first thing we do when we start looking at how to convert a site to responsive images.

And it is most likely your next step towards taking what you’ve learned and applying it to your sites.

Fortunately, I wrote about these audits in great detail recently. Instead of repeating it in the 101 series, I encourage you to read what I wrote about responsive image audits now. Consider that article Part 9a.

Compatibility

Browser support for responsive images standards is growing rapidly. As of August 2015, Chrome, Opera and Firefox all support picture, srcset, sizes, and type.

Microsoft Edge and Safari support srcset with display density (x) descriptors, but not the width descriptors. Microsoft has started development to support the full responsive images standard.

Apple hasn’t committed to supporting the standard yet, but Apple knows responsive images support is important and Yoav Weiss has been contributing to the WebKit implementation.

When it comes to image-set(), there is still a lot more work to be done.

PictureFill

But even if all the browsers currently supported the responsive images standards, we’d still need a way to help older browsers understand the new syntax. That’s where the PictureFill polyfill comes in.

PictureFill will allow you to use the new responsive images syntax now.

Automating your image processing

In Part 9, I said that humans shouldn’t be picking image breakpoints. Instead, we should have software doing this automatically for us.

I want to expand on this point and say that most of what we deal with when it comes to responsive images is not something that designers and developers should be thinking about on a regular basis.

The goal for most organizations should be to centralize image resizing and processing and automate as much of their responsive images as possible.

In my ideal world, a responsive images workflow for resolution switching would look something like this:

  • Where possible, use resolution independent SVG images.
  • When creating or modifying the design of templates, the template author provides the sizes attribute for the various images in the template.
  • The srcset attribute with width descriptors is inserted by the server which does all of the heavy lifting of figuring out what image breakpoints to choose for each image.
  • Content authors never worry about any of this. Their only responsibility is to upload the highest quality source available and let the image resizing service take care of the rest.

This isn’t a far-fetched scenario. Many organizations already have image resizing services. And if your organization doesn’t, I maintain a spreadsheet of image resizing services and tools that you can consider (be sure to read the explanatory blog post as well).

And many content management systems are starting to look for ways to incorporate responsive images. The Responsive Images Community Group (RICG) maintains a WordPress plugin and they are currently looking at how to add it to WordPress core. Drupal 8 will ship with a responsive images module (more details).

The only thing these image resizing services need to add is support for figuring out how many image sources to supply for a given image and to output the proper markup for those image sources. They may not even need to worry about the markup if Client Hints takes off.

(More on Client Hints soon. This is a 201 topic.)

But regardless of how you automate it, I believe that centralizing image resizing and processing is essential to maintaining your sanity. When we talk to new companies exploring responsive images, one of the first things we assess is their image workflow and how much of it we can automate.

Future of responsive images

We’re just getting started when it comes to responsive images. We have thousands of sites to update to use the new image standards. Many organizations need to update how they handle images to centralize and automate what has until now been a manual process.

Even though there’s still a lot of work ahead of us, it feels like we’re finally on the downhill slope. We’re no longer struggling to find solutions that everyone can agree on. Implementations are landing in browsers. We have PictureFill to help us fill the gaps.

And now the wider web development community is beginning to look at how they are going to implement these new standards which means that we can start learning from each other.

If you’ve read this entire 101 series, you have everything you need to get started with responsive images. I can’t wait to see what you do with the new standards. Please share what you learn!

Thank you for reading.


Responsive Images 101 Series
  1. Definitions
  2. Img Required
  3. Srcset Display Density
  4. Srcset Width Descriptors
  5. Sizes
  6. Picture Element
  7. Type
  8. CSS Responsive Images
  9. Image breakpoints
  10. Conclusion

The Death of Progressive Enhancement(?) and Responsive Animation

We have two more exciting Responsive Field Day topics to announce this week including our first potential “hot drama”1 discussing the recent controversies over progressive enhancement.

Tom Dale: Progressive Enhancement is Dead, Long Live Progressive Enhancement

Tom DaleSome say that using a JavaScript framework means sacrificing core web principles—universal access, graceful degradation—in exchange for developer convenience. Are JavaScript peddlers like me the Pied Pipers of doom, leading the community astray from web righteousness? Let’s look at why devs are drawn to the benefits of JS frameworks—and discuss whether the rampant hand-wringing about progressive enhancement is deserved or a relic from an older age.

Val Head: Animation in Responsive Design

Val HeadAnimation often needs some space to move in, but with responsive design we know the space we have is ever-changing. Balancing those two factors can lead to some tricky design problems for web animation, especially when you throw performance and design concerns into the mix! Val will break down examples and show you how to design animations that work well at all viewport sizes without driving yourself crazy.

Responsive Field Day is now only five week away! Don’t miss your chance to hear Tom Dale, Val Head and our other fantastic speakers on Friday, September 25th in Portland’s Revolution Hall. Get your tickets while you can!


Footnotes
  1. “Hot drama” trademark Shop Talk Show. ;-)

Shifty Tile Flyouts

Although my favorite projects will always be those that allow us to re-evaluate a user experience from the ground up, sometimes that isn’t realistic. That’s where Responsive Retrofitting comes in: The process of making small, surgical changes to existing interfaces to improve the small-screen experience incrementally.

Each and every retrofit is a little different, but patterns do emerge. In the past couple of years, I’ve noticed one particularly challenging bit of UI that’s cropped up multiple times for multiple clients.

Illustration of tile-based interface with flyout

Here’s how it works: We have tiles separated into rows and columns. Each tile represents some form of summary content; contact info or payment options, for example. Selecting a tile (or clicking an “edit” button therein) expands a flyout below with some sort of form content, which spans the entire available width and “pushes” down any tiles below.

Every time I’ve encountered this, it’s been implemented in the same way. Because the design is fixed-width, the number of columns in each row is predictable. Flyout elements are simply inserted between rows:

<div class="Tiles">
  <div class="Tile">
    <div class="Tile-content">
      Tile 1
    </div>
  </div>
  <div class="Tile">
    <div class="Tile-content">
      Tile 2
    </div>
  </div>
  <div class="Tile">
    <div class="Tile-content">
      Tile 3
    </div>
  </div>
  <div class="Tile">
    <div class="Tile-content">
      Tile 4
    </div>
  </div>
  <div class="Flyout is-open js-flyout">
    <div class="Flyout-content">
      Flyout 1
    </div>
  </div>
  <div class="Flyout Flyout--2of4 js-flyout">
    <div class="Flyout-content">
      Flyout 2
    </div>
  </div>
  <div class="Flyout Flyout--3of4 js-flyout">
    <div class="Flyout-content">
      Flyout 3
    </div>
  </div>
  <div class="Flyout Flyout--4of4 js-flyout">
    <div class="Flyout-content">
      Flyout 4
    </div>
  </div>
  <div class="Tile">
    <div class="Tile-content">
      Tile 5
    </div>
  </div>
  <div class="Tile">
    <div class="Tile-content">
      Tile 6
    </div>
  </div>
  <div class="Flyout js-flyout">
    <div class="Flyout-content">
      Flyout 5
    </div>
  </div>
  <div class="Flyout Flyout--2of4 js-flyout">
    <div class="Flyout-content">
      Flyout 6
    </div>
  </div>
</div>

See the Pen Shifty Tiles: Part 1 by Tyler Sticka (@tylersticka) on CodePen.

The content order’s pretty messed up, but it works as intended. Or it would have, if it hadn’t been for that meddling Ethan Marcotte and those media queries of his. When you throw responsive into the mix, that predictable column count we depended on goes right out the window:

Animation of responsive tiles with flyout

We could listen to resize events and move the flyouts around with JavaScript. But you and I both know that’s a bad idea. Let’s see how we can solve this problem with CSS alone, maybe even improving the content order along the way.

To Float or Not To Float

If we revise our markup so that the tiles and flyouts are unified (instead of separated by arbitrary “rows”), we’ll discover that the floats we were using to arrange tiles side-by-side do not handle change well. Depending on which tile flyout is expanded, subsequent tiles attempt to float around it, resulting in an inconsistent (and frankly, upsetting) experience for wider viewports:

See the Pen Shifty Tiles: Part 2 by Tyler Sticka (@tylersticka) on CodePen.

Well that’s it, then! Floats don’t work, we need tiles to float, time to throw in the towel and handle this with JavaScript.

Not so fast!

Instead of floating the tiles, we can steal borrow a technique from the SUIT CSS grid component and use display: inline-block instead. Combined with vertical-align: top, the tallest tile in a row should push down everything beneath it (just like a tall image in a line of text would affect adjacent rows).

Let’s give it a whirl:

See the Pen Shifty Tiles: Part 3 by Tyler Sticka (@tylersticka) on CodePen.

Success! Even as flyouts shove their way between rows, the tiles retain their horizontal position.

But those flyouts are still awfully narrow at larger sizes. Let’s fix that.

Manifest Destiny

Our goal is for the flyouts to occupy 100% of the available width across all viewports. So far, they’re only ever as wide as the tiles themselves. If we’re decreasing tile widths at larger breakpoints, we should also increase flyout widths by the same factor.

If you’re using a preprocessor like Sass and you hate solving the same math problems over and over as much as I do, now’s a great time to write a mixin to handle this logic across multiple breakpoints:

@mixin generate-tile-grid($columns) {
  .Tile {
    // divide the available width by the number of columns
    width: (100% / $columns);
  }
 
  .Tile-flyout {
    // extend beyond the tile width by the same factor
    width: (100% * $columns);
  }
 
  .Tile-flyout:before {
    // adjust the position of the flyout caret
    left: (100% / 2 / $columns);
  }
}
 
@media (min-width: 30em) {
  @include generate-tile-grid(2);
}
 
/* etc. */

Here’s where that gets us:

See the Pen Shifty Tiles: Part 4 by Tyler Sticka (@tylersticka) on CodePen.

So close! The widths are correct, but we haven’t accounted for the tile’s changing horizontal position. Let’s revise that mixin we wrote, using :nth-child selectors to offset the flyouts per column:

@mixin generate-tile-grid($columns) {
  .Tile {
    width: (100% / $columns);
  }
 
  .Tile-flyout {
    width: (100% * $columns);
  }
 
  // for every column in this grid
  @for $column from 1 through $columns {
    .Tile:nth-child(#{$columns}n+#{$column}) {
      .Tile-flyout {
        // offset the left margin by the number of preceding columns
        margin-left: (-100% * ($column - 1));
      }
 
      .Tile-flyout:before {
        // adjust the caret position similarly
        left: (100% / $columns * ($column - 0.5));
      }
    }
  }
}

Drumroll, please…

See the Pen Shifty Tiles: Part 5 by Tyler Sticka (@tylersticka) on CodePen.

…and boom goes the dynamite.

In Practice

Because this technique is initially counter-intuitive (at least to me), I kept the examples pretty simple. If you’re still a little fuzzy on how this interface pattern might work in practice, here’s a more complex demo involving hypothetical payment methods and their associated edit forms. Tap or click a tile to toggle:

See the Pen Responsive tiles with column-spanning flyouts by Tyler Sticka (@tylersticka) on CodePen.

Having retrofitted this type of UI multiple times now, I’d be remiss if I didn’t voice some concerns I have about its usability. Because the vertical position of subsequent tiles changes as flyouts expand and collapse, it can be frustrating to use on smaller screens without a nightmarish amount of fragile and jank-inducing scroll management. If redesigning is an option for this pattern, I recommend reading Luke W’s post about dropdowns for some much more straightforward alternatives.

Or better yet, drop us a line. Solving these problems is kind of our thing.

Introducing Leveller: Please Avoid Using It

This happens to me over and over: I have a multi-column grid of tiles, each with varying heights. This means the bottom of certain rows can appear jagged and difficult to scan visually:

See the Pen Leveller: Before by Tyler Sticka (@tylersticka) on CodePen.

Ideally, I’d use flexbox to solve that problem with a shockingly small amount of CSS (especially if you use Autoprefixer). Seriously, look how well that works:

See the Pen Leveller: Flexbox Alternative by Tyler Sticka (@tylersticka) on CodePen.

Sadly, that solution rarely makes it into production on the projects I’ve worked on. Sometimes browser support is the culprit. Other times we’ve inherited particularly uncooperative grid patterns (either from an existing project, or an overzealous framework).

Over the last few years, I wrote and re-wrote project-specific, bespoke JavaScript to solve this problem. I’ve finally accepted that it isn’t going away, at least not as quickly as I’d like it to.

So I’ve written a jQuery plugin for equalizing element heights. It’s called Leveller:

See the Pen Leveller: After by Tyler Sticka (@tylersticka) on CodePen.

Don’t use Leveller if you can help it. Flexbox is way more appropriate. If you only need to adjust min-height properties, Equalizer is a leaner, dependency-free solution.

But if all else fails, Leveller is available now on GitHub (and also via npm). Godspeed!