Cloud Four Blog

Technical notes, War stories and anecdotes

Two pretty-good techniques for styling tricky form elements

Confession time: For most of my career, I despised form elements. Checkboxes, radios, selects and file inputs seemed to gleefully defy what little control I expected from an HTML element. Their penchant for idiosyncracy drove me to almost as much hair-pulling and teeth-gnashing as IE6 or web-safe fonts.

These days, my frustration with form elements has quieted. Partly that’s because browsers and development tools are so much better. But more significantly, I now understand the benefits of surrendering some control to the operating system. As devices continue to accept a greater and greater variety of input methods (keyboard, mouse, touch, voice, gesture, remote, etc.) while browsers adopt an astounding variety of new input types , it’s a gift for vendors to provide default experiences consistent with the user’s expectations of the platform.

So I no longer strive for “pixel perfection” when styling form elements. I don’t need absolute control. All I want is something easy to tap that feels intentional.

When the browser defaults don’t get me there, here are my go-to workarounds.

Checkboxes and Radios: Styled Sibling

This technique works in any browser that supports CSS3 selectors (basically IE9+). If you read Radio-Controlled Web Design a few weeks ago, this should feel familiar. Let’s start with a checkbox example.

We’ll need a few HTML elements:

  • The <input> itself.
  • A dummy element to style (right next to the <input>).
  • A containing <label> that passes click events to the aforementioned <input>.

I like to wrap the <input> and dummy elements in a container to keep everything nice and tidy, but strictly speaking it isn’t required. Here’s what that markup might look like:

<label>
  <span class="checkbox">
    <input type="checkbox">
    <span class="checkbox-value" aria-hidden="true"></span>
  </span>
  Set phasers to stun
</label>

We’re now free to visually hide the checkbox, styling .checkbox-value however we like:

/* hide the "real" checkbox visually */
.checkbox input {
  border: 0;
  clip: rect(0 0 0 0);
  height: 1px;
  margin: -1px;
  overflow: hidden;
  padding: 0;
  position: absolute;
  width: 1px;
}
 
/* style the "fake" checkbox */
.checkbox-value {
  /* default/unchecked styles */
}
input:checked + .checkbox-value {
  /* checked styles */
}

When the user clicks the label, the click is passed along to the <input>, which toggles the state of :checked, which affects the appearance of .checkbox-value.

Here’s an example that styles the checkbox like an iOS-style switch:

See the Pen Styled checkbox by Tyler Sticka (@tylersticka) on CodePen.

Here’s the same idea applied to radio buttons with a slightly more conventional design (incorporating a base64-encoded SVG checkmark):

See the Pen Styled radios by Tyler Sticka (@tylersticka) on CodePen.

This technique has a few drawbacks. It requires some extra markup. It won’t work in IE8 or earlier without a fallback. It could probably use another pass for accessibility. But compared to most of the JavaScript solutions I’ve tried, this feels straightforward, consistent and predictable.

Selects and File Inputs: Transparent Overlay + JavaScript

For more complex elements like <select> and <input type="file">, we can’t get by on CSS alone (though it gets us further than one might expect).

Our markup is similar to the previous set of checkbox/radio examples, except we won’t need a <label> for click events:

<div class="select">
  <select>
    <option>Option 1</option>
    <option>Option 2</option>
    <option>Option 3</option>
  </select>
  <span class="select-value" aria-hidden="true"></span>
</div>

Instead of hiding the <select> entirely, we want to position it over the rest of our element, allowing it to intercept click events and correctly position any dropdown it may display. Because this technique relies on JavaScript, we’ll qualify some of our selectors with .js (since you’re probably already using Modernizr).

.js .select {
  position: relative;
  /* default styles */
}
.js .select:hover {
  /* hover styles */
}
.js .select.focus {
  /* focus styles */
}
 
/* nicer default styles for "real" <select> */
.select select {
  cursor: pointer;
  display: block;
  width: 100%;
}
/* hide and overlay when JavaScript is enabled */
.js .select select {
  left: 0;
  height: 100%;
  min-height: 100%;
  min-width: 100%;
  opacity: 0;
  position: absolute;
  top: 0;
}

Already, this “works.” Options will display on click. But there are some problems. The value doesn’t update. There are no hover or focus styles. That’s where JavaScript comes in!

(Although I’ve chosen to write this in jQuery for the sake of readability, remember: You Might Not Need jQuery!)

// For each .select element
$('.select').each(function(){
  // Save some elements as variables
  var $element = $(this);
  var $select = $element.find('select');
  var $value = $element.find('.select-value');
  // Bind event handlers to <select>
  $select.on({
    // On change or keyup, update the value text
    'change keyup': function () {
      $value.text($select.val());
    },
    // On focus, add the focus class
    'focus': function () {
      $element.addClass('focus');
    },
    // On blur, remove the focus class
    'blur': function () {
      $element.removeClass('focus');
    }
  });
  // Trigger the change event so the value
  // is current
  $select.trigger('change');
});

Here’s how all of that comes together:

See the Pen Styled select by Tyler Sticka (@tylersticka) on CodePen.

With some tweaks, the same basic technique can also work for file inputs (assuming experimental WebKit/Blink features aren’t your thing):

See the Pen Styled file input by Tyler Sticka (@tylersticka) on CodePen.

This idea isn’t new. Peter-Paul Koch wrote about it quite a while back. Yet I rarely see it in use outside of a few large mobile frameworks. I’m honestly not sure why.

…and beyond?

What do all of these examples have in common? They don’t mess with the form element too much! By worrying less about customizing behavior and more on simply triggering it, we can indulge some of our designerly impulses without discarding all a given platform has to offer.

Consistency and functionality… no hair-pulling or teeth-gnashing required!

Update: September 8, 2014

A reader pointed out that the select example wasn’t responding to keyboard input in Firefox. I discovered that Firefox doesn’t fire the change event for selects like other browsers do, so I’ve updated the demo and example code so that it binds to both change and keyup.

I also learned that Firefox doesn’t show the full dropdown on any keypress, but this seems to be true of unstyled <select> elements as well. I encourage developers to use these examples as a starting point, and to augment usability shortcomings on a case-by-case basis if the default browser behavior isn’t cutting it.

More on CSS Media Queries for Mobile

My previous post on CSS Media Queries kicked off quite a bit of conversation. I wanted to follow up on a few points that have been made and a couple of things I failed to communicate well in the original post.

CSS Media Queries are a Useful Tool for Mobile

One of the unfortunate side effects of the strident title I chose was that it gave many people the impression that I didn’t think CSS Media Queries were useful at all for mobile.

That’s not the case. We’re using them in two mobile projects right now and contemplating using them for a third.

I wrote in the post that “CSS media queries are a tool, but they are not a silver bullet.” But that point was overshadowed by the post title and the rest of the article talking about the problems that you need to be aware of when using them.

I got a chance to chat with Ethan Marcotte via Twitter. He wrote:

I think we agree on the fundamental points, honestly—the implementation should always be tailored to the site/audience.

I wholeheartedly agree. In fact, Ethan wrote in his article about Responsive Web Design:

That’s not to say there isn’t a business case for separate sites geared toward specific devices; for example, if the user goals for your mobile site are more limited in scope than its desktop equivalent, then serving different content to each might be the best approach.

In the same way in which my more nuanced opinion about media queries was skewed by my poor choice of title, I think Ethan’s nuanced opinion about when and how media queries can be used for mobile has been skewed by the enthusiasm that people had in response to his A List Apart article and how they might use the technique for mobile.

As I said in my post and reaffirmed to Ethan over Twitter, I’m actually quite excited about Responsive Web Design. I’m going to write more about that separately.

What I really meant to say was…

Even though Ethan never intended media queries to be seen as a total solution for mobile, that view has been enthusiastically adopted by others. I’ve read many blog posts and tweets on the topic. There was a session at Web Visions called Mobile Web Dev without Developing a Mobile Site based on building sites using media queries.

PPK got is right when he said that I “challenged the conventional view that media queries are all we need to make a website mobile-friendly.” There was a growing consensus that media queries were all that was needed and that consensus needed to be challenged.

In rereading my post, there is one sentence that I think best summarizes my view:

The way in which CSS media query has been promoted for mobile hides tough problems and gives developers a false promise of a simple solution for designing for multiple screens.

I’ve modified the sentence slightly to make it clearer that it was the way media queries were being promoted as a solution for mobile that was the real problem.

It is also clear that fool’s gold is not the right phrase. Fool’s gold is something that looks like something of worth, but in reality has no intrinsic value. Media queries do have value and are useful tools.

I’m sorry for poor title choice.

Great Ways to Use CSS Media Queries

There are a few great use cases for media queries for mobile. I highlighted selected web apps and html emails in my previous email. A few others are:

  • As PPK suggests, pairing media queries with javascript could be the core of a mobile web solution. The javascript can be used to swap the correct images in for each context. This is most effective if you start from a mobile design and use media queries and javascript to add functionality for desktop users. You also need to understand which devices your customers are using to make sure this technique works for those browsers.
  • As Pim Derks commented on my post, in situations where “a client has a limited budget, but wants his site to look good on iPhone.” Given the alternative of no mobile web site, it makes sense. I’d suggest looking to see what you can do to stop unnecessary downloads where possible.
  • And the most likely use of media queries, as a small part of a larger mobile optimization effort or a discrete tool being used in one off situations like web apps or html emails.

You’ll notice that the solution that PPK suggests is quite a bit different than starting from the desktop web and simply adding media queries.

It requires images to be uploaded in multiple sizes. For optimal use, it requires html to be retooled to start with mobile web appropriate html only and then javascript to enhance it.

It is entirely possible that a great mobile solution could be built that way. I question the likelihood that web sites are going to be retooled to deliver mobile html first and then progressively enhanced with javascript and css. But I’d be happy to be wrong about that.

What are the Tough Problems that Discussion of Media Queries Obscures?

I’ve enumerated many of the technical challenges with media queries, but when I talk about media queries hiding tough problems, I’m not talking about any of the issues I raised in my previous post.

What I was referring to was the idea that there was a simple solution to creating a mobile web site obscures a series of infrastructure issues that I believe web developers are going to be confronting over the next few years.

Let’s assume for a moment that there are situations in which you need to deliver different html and associated assets to different mobile devices. To do so requires that your content management or ecommerce system is equipped to do the following:

  • Detect different devices and the capabilities of those devices.
  • Select the correct template based on the device. This implies that your system gracefully handles multiple templates.
  • Separate assets added by authors from the words that they write so that those photos, video, etc. can be resized and reformatted appropriately for the device.
  • Provide tools or establish processes for resizing images and videos. Either manually, or better yet automatically, encode video in multiple formats based on the device.
  • Support non-web consumption of content (e.g., native applications). This will likely require further consideration of how to remove markup and presentation from content.

And many more obstacles created by legacy web publishing tools designed long before we started thinking seriously about mobile.

The big challenges our clients face are rethinking and retooling their infrastructure for mobile. It’s going to be a massive undertaking for a lot of businesses.

The sooner we realize this fact, the sooner we can get to work figuring out the best ways to build that infrastructure.

CSS Media Query for Mobile is Fool’s Gold

Read the follow up article written August 21, 2013

Ethan Marcotte’s article Responsive Web Design has caught the imagination of web developers. Several subsequent articles have touted the CSS media query feature as a way to build mobile-optimized web sites.

Even I’m guilty of contributing to this meme with my article on CSS orientation.

Unfortunately, CSS media query is fool’s gold for mobile devices. It hides tough problems and gives developers a false promise of a simple solution for designing to multiple screens.

The Short Version

Ferreting out the problems with CSS media queries for mobile devices is easy if you look at what media queries purportedly promise:

All you need to do to transform your desktop web design into something optimized for devices with smaller screens, less powerful CPUs, and slower network connections is to add more code.

The idea of adding more code—adding more to download—in order to optimize for mobile should be the first clue that this isn’t a good solution.

Core Assumption: Speed Matters More on Mobile

I’m going to point out several technical flaws with media queries. Nearly all of them rely on my belief that speed matters more on mobile devices.

That isn’t to say that we’re more tolerant of slow desktop web pages. Instead, that mobile is more likely to be used in situations were the speed of access matters more (urgently looking for a business) and under conditions (network speed, device processing power) that are less optimal for speed.

When designing for mobile, performance is a key consideration.

Letting the Browser Scale Images is a Bad Idea

Ethan’s article on Responsive Web Design relies on a technique he calls Fluid Images.

The idea behind fluid images is that you deliver images at the maximum size they will be used at. You don’t declare the height and width in your html, but instead let the browser resize the images as needed while using CSS to guide their relative size.

This technique is a bad idea for mobile for a couple reasons.

Full Images = Unnecessarily Large Files to Download

The full image is downloaded despite the fact that it will only be seen at a fraction of the size on a mobile device. In the Responsive Web Design example page, the images are 330 x 345 pixels in true size, but when viewed on an iPhone, they are only ever seen at approximately 150 x 157 pixels.

The six images of characters from Sherlock Holmes that are included in the example page total 208K. Resizing those images and optimizing them reduces the total file size for all six images to 45K. That’s an 78% reduction in file size and download time.

Original Resized K Saved % Saved
Total 208.3K 45.8K 162.5K 78.0%
Holmes 34.7K 8.1K 26.6K 76.6%
Watson 39.0K 8.4K 30.6K 78.4%
Mycroft 30.5K 6.7K 23.8K 78.0%
Moriarty 43.4K 8.2K 35.2K 81.1%
Adler 26.0K 6.6K 19.4K 74.6%
Winter 34.7K 7.8K 26.9K 77.5%

Downloading 162K unnecessarily on a mobile device is nothing to sneeze at no matter how good the mobile phone is.

Browser Resizing Can Be CPU and Memory Intensive

Yes, desktop browsers and iPhones have no trouble resizing images, but what about older or cheaper phones with less formidable CPUs? With this technique, we’re asking them to download larger images, uncompress them to their full size in memory, and then resize them to fit the screen.

Even Apple’s Mobile Safari documentation says “You need to size images appropriately. Don’t rely on browser scaling.”

Using Media Queries to Deliver Different Images Doesn’t Work

I know what many of you are probably thinking. So the fluid images technique doesn’t work. Let’s just use media queries to deliver different images depending on screen size.

There are two ways this can be accomplished. The first is to have image tags that are hidden by CSS. The second is to use CSS background images and switch the background image. Let’s look at both techniques.

Hiding Image Tags Using CSS Media Queries

Rachel Andrew‘s article about CSS media queries showcased dConstruct’s web site as an example.

dConstruct Desktop View

The dConstruct site is beautiful. The site grows bigger as your browser gets bigger. The photographs come to life when you hover over them. It’s truly worth a look.

The large photographs of the speakers are placed on the page using image tags. The black and white images are a single sprite that is layered over the color photographs using CSS.

dConstruct Mobile ViewAnd if you view the site on a mobile device, the large photographs of the speakers are hidden from view. You get a simple list that fits well on the screen.

A CSS media query instruction is used to set display:none on the div containing the speaker images.

However, the iPhone still downloads the images even though they are not displayed.

There was a some speculation during the Big Web Show interview with Ethan Marcotte that perhaps the tools that were reporting what the browser was downloading were erroneously inflating the number of files that were truly download.

To verify that images are downloaded despite CSS media queries, I tested two different ways. First, I made a copy of a page using the responsive design onto a local server, loaded it on an iPhone, and then watched the web server logs to observe what was downloaded. Second, I set my iPhone to use my Mac as a proxy server so every request to dConstruct’s site was logged.

In both cases, it showed the image files are downloaded despite the fact that the media query has set them to display:none. This means that the iPhone downloads an extra 172K for photos that the user will never see.

Hiding CSS Background Images

Surely CSS background images will work better than image tags, right? Wrong.

I tested a few different combinations of CSS background images and media queries. What I found was:

  • Using CSS media query to set display:none on an element containing a background image does not prevent Mobile Safari from downloading it.2
  • Using CSS media query to override a background image with one created specifically for mobile results in both the desktop and the mobile image getting downloaded.4

Two methods that appear to work are:

  • Setting the parent of an element with a background image to display:none.3
  • Using media query min-width declaration to only specify a minimum browser width for the desktop image and a max-width for the mobile image does result in only the mobile image being downloaded in Mobile Safari.5

These two options mean that using CSS media queries isn’t completely impossible, but using the parent element to hide images and changing existing desktop CSS to add min-width declarations are significant changes to existing CSS. It isn’t going to be as simple as adding a CSS media query for mobile and calling your job done.

FWIW, it is this behavior of downloading images even if they are currently not displayed that allows us to have images show up in pull down menus and on other hover events without a delay while the image is downloaded. This is generally a good thing.

CSS Media Queries Do Not Optimize HTML or Javascript

My first introduction to media queries was when we were asked to assist another web developer who had built a page that contained a Google Map on the desktop version, but the div containing the map was hidden on the mobile web version using a media query.

Unfortunately, even though the map no longer showed up, the 180K javascript library was still downloaded by the browser.

CSS media queries will not remove unnecessary html nor remove javascript that will slow down mobile browsers.

CSS Media Queries aren’t Supported Well

If you can overcome all of the challenges I’ve outlined above, you’ll find that CSS media queries are not supported by many mobile browsers. PPK’s compatibility table shows that even amongst modern smartphones, the support is spotty and inconsistent.

The picture is much worse when you decide to support older browsers.

If you choose to use media queries to provide a mobile version of your web site, you’re not only picking a poor solution, but you’re excluding a large number of mobile users.

People with modern smartphones may be the demographic you care about, but you should be make a conscious decision about what device classes you support.

Ignoring the Mobile Context

The promise of CSS media queries is that you can take your existing desktop web site html and add this additional presentation layer for mobile. Doing so ignores the fact that a mobile user may have very different needs than a desktop user.

There is a great quote from Brian Fling in his book on mobile design:

Create a product, don’t re-imagine one for small screens. Great mobile products are created, never ported.

Does your desktop web home page use geolocation lookups? Probably not. Should your mobile site home page? Quite possibly.

If you send the same HTML and Javascript to the mobile user that you do for the desktop user, even if you format it to fit their screen, you’re likely missing opportunities to provide a great mobile experience based on the capabilities of the device and the context of the mobile user.

Separate Mobile Web Sites are a Good Thing

I know separate mobile web sites are a pain to develop. We have a lot of infrastructure to build to make the mobile web go, and I’m going to be writing more about that soon. But there are good reasons why we need separate mobile web sites.

During Ethan’s interview on the Big Web Show, some time was spent discussing how sharing links from the New York Times doesn’t work the way you would hope. If you send a link from the mobile site and someone opens it on their desktop browser, it is still formatted for mobile.

The conclusion drawn from this during the podcast is that CSS media queries might be a better solution because there would only be one URL, and it would work for both desktop and mobile.

Here’s some hard numbers to consider from a YSlow examination of the New York Times desktop and mobile home pages:

YSlow results for the New York Times Mobile and Desktop Home Pages

As you can see, the mobile web site has a fifth of the HTTP requests of the desktop version and is 583K smaller. That’s over 90% smaller and significantly faster on a mobile device.

(As an aside, HTTP requests are much more expensive on mobile devices than on desktop due to the latency of wireless network connections.)

I agree that the NY Times links should work, but the solution isn’t to take the bloated desktop home page and add more CSS code to make it mobile (un)friendly.

Some Good Uses of CSS Media Queries

There are some good uses of CSS media queries. If you’re building a discrete web application where you have more control and can make sure that the desktop web isn’t bloated, it can make sense.

Also, Ros Hodgekiss from Campaign Monitor wrote an exceptional article on how you can use media queries in html email to provide a mobile optimized layout. This is perhaps the ideal use case because when you send html email, you have no choice but to send a single html document regardless of what device the recipient will be using.

Responsive Web Design Still Rocks

Wait? Responsive web design still rocks? Hard to believe after everything I’ve written, eh?

I’m not talking about CSS media queries, but instead of the idea of building around a grid, planning your design for different screen sizes, and thinking about the modular building blocks and how they can be moved based on screen size.

That is the real gem in Ethan’s article. I hope we see two things come from his responsive web design piece:

  • More desktop web sites that take advantage of fluid grids and CSS media queries to optimize for the multiple sizes of desktop screens. Media queries still make sense for desktop designs.
  • More designers and developers thinking about design as modular even if it isn’t implemented with media queries.

I find his comparisons to responsive architecture to be fascinating and the designs we’ve seen using these techniques to be compelling. But the core mechanism used to accomplish them, CSS media queries, isn’t up to the task when it comes to mobile development.

No Silver Bullets

Developing for the mobile web is difficult. There are no simple solutions that make it easy to provide a great mobile-optimized experience. CSS media queries are a tool, but they are not a silver bullet.

This shouldn’t be a surprise to us. We now take our content management systems for granted, but it wasn’t always this easy for the desktop web. We forget how difficult it was to simply get Apache running properly.

During the last big wave of technology, we had a lot of infrastructure to build before we could reliably deliver quality experiences for desktop browsers. We’ve got a similar road ahead when it comes to mobile.

But no matter how difficult, mobile is worth it. The power of having information in people’s hands—no matter where they are in the world—makes mobile worth the extra time and effort.