Cloud Four Blog

Technical notes, War stories and anecdotes

One amazing video that shows the potential of the physical web

Michael Mahemoff‘s recent article on how Progressive Web Apps have Leapfrogged the Native Install Model reminded me of a video I discovered while researching my new Adapting to Input talk.

I keep revisiting the video because it shows how the physical web can provide a substantially better experience than the native app install process.

Here’s the video from Matthew Sibigtroth:

Let’s compare the install process for the physical web versus what it would likely take using native apps.

Physical web install process

  1. Look in drawer for physical web beacons.
  2. Select physical web beacon.
  3. Web page launches. Prompts for pairing with toy.
  4. Select toy to complete pairing.
  5. Control toy.

There are two challenges in this process that will be solved with time. First, people need to know about physical web beacons. Second, the physical web and web bluetooth specifications are new and cross browser support is limited.

In fact, this process will likely be streamlined further in the future when the phone automatically notifies the user about nearby beacons.

Native app install process

  1. Confirm that the toy has an app for your platform.
  2. Open app store.
  3. Search for toy. Hope the toy has a unique name so you can find the app easily.
  4. Install the app and enter app store password if necessary.
  5. Wait for app to download.
  6. Open app.
  7. Pair with toy.
  8. Control toy.

Three fewer steps may not seem like much, but the total process is much slower. Apps are usually several megabytes in size making that step alone take much longer than the comparable step for the physical web.

Put a different way, it only takes 18 seconds from when the person first touches the screen to when the toy can be controlled. And that is with the person going slowly so that the people viewing the video can see each step.

It took me nearly 8 seconds on my phone to simply find, launch, and get to the home screen of the app store.

Yes, that will be faster for other people depending on placement of the app store icon, how recently they used the store, and network speed. But it is hard to envision that process ever being faster than simply following the physical web beacon.

The easier install process of the physical web and progressive web apps makes for an exciting future.

Jeb Bush’s Responsive Images Problem

It’s political season here in the United States, and it is great to see politicians taking technology issues seriously.

Take Jeb Bush for example. His campaign has gone out of its way to highlight the importance of planning the focal point of your responsive images carefully.

On small screens, the web page carefully positions the campaign logo right in the middle of the candidate’s face. This makes sense as there are two Bushes in the photograph so the logo helps us identify which Bush is running this time.

Screenshot of Jeb Bush web page on iPhone 4s where the logo is on top of Jeb's face

Careful planning ensures that there aren’t any embarrassing crops of the Bush brother we’re focusing on.

Jeb Bush split in half by a crop

At wider screens, the campaign crops out one Bush brother so we can focus in on the signup form. The last thing the campaign wants is for Jeb’s brother to overshadow him.

Wider screen that only shows George Bush

Animated gif showing unintentional cropping of Jeb Bush

You can see the full cropping in action at the Jeb Bush SC Signup Page or in the video below:

Alright, I’ve had enough fun at poor Jeb’s expense. This could easily happen to any web site owner.

Jeb Bush’s signup page demonstrates the needs for organizations to coordinate on how photographs will be created and utilized within responsive designs—particularly in cases where cropping will occur in the browser.

And it illustrates why Simon Bächler has started the Universal Images Working Group—a W3C Community Group—to work on embedding art direction rules inside meta data on the image files themselves.

The meta data would contain information on what can be cropped from an image and where the safety area—the area that should never be cropped—is located:

Photo of Monks containing crop marks and safety areas

The above image is from the Universal Images Demo page.

This idea is similar to what film and TV have been doing for years to ensure their work is cropped in an acceptable fashion. I’m already seeing organizations adopting this technique for responsive images.

Kevin Mack and Tim Vonderloh presented how they used what they called Asset Template Guides (video, slides) on a client project.

Netflix provides photographers with a prototype of the page in addition to guidelines and a template. “The photographer had the tool to be able to drop the images in as he was shooting them and we could see them in a prototype and see how they would look across screen sizes,” Anna Blaylock explained in an interview.

If you’re interested in working on this problem, the Universal Images Community Group could certainly use your help.

The big lesson here is that if cropping is part of your responsive images strategy, you need to plan ahead to avoid accidentally cropping the most important parts of a photograph.

Jeb and George chest bump

Thanks to Aileen for pointing out the Jeb Bush sign up page.

Simpler SVG Icons

As a follow-up to my post discouraging the use of icon fonts, I recently wrote about the SVG icon process we’ve been using at Cloud Four. While most of the feedback I received was positive, some felt the steps I described seemed complicated, even intimidating.

I can’t entirely disagree. Our designers find the process easy to use (save SVG to folder, optionally update YAML file, use in HTML), but it does require quite a bit of elbow grease up-front.

And while I’d argue that our process is only modestly more complex than comparable icon font setups (examples here, here, here and here), I completely understand how it might feel overwhelming to anyone new to the SVG format (which is most of us, if we’re honest).

So I thought it might be helpful (and fun!) to devote a post to some of the simpler ways you can start using SVG icons today. Whether these options serve as your “toe in the water” or your production-ready technique of choice, I think you’ll find all of them more approachable.

Use Images

SVG is an image format, which means you can use it just like an image:

<img src="my-icon.svg" alt="Niftiest Icon Ever">

Crazy, right? Or if your icons are purely decorative:

.my-icon {
  background-image: url("my-icon.svg");
  /* width, height, etc. */
}

Neither of these techniques inherit the parent element’s text color, a feature we’ve all taken for granted since 2011. But unless your site’s color palette is enormous, they’ll probably work just fine.

Copy and Paste SVG Source

We use this technique a lot when we’re prototyping. Most of the time, you can copy and paste the source of an SVG right into your HTML document:

See the Pen SVG icon pasted into HTML by Tyler Sticka (@tylersticka) on CodePen.

The markup’s a little messy and there’s no caching to speak of, but it works just fine. SVG elements can even inherit the parent text color!

(Tip: If you find yourself saving files over and over just to copy their contents, try clicking the “Show Code” button in Illustrator’s Export dialog instead. There’s also a “Copy Layer as SVG” plugin for Sketch.)

Use a GUI

Detail of IcoMoon interface

If you really want to compile your icons into a single resource but don’t want to mess with Gulp or Grunt, several web apps exist that will guide you through the process. Our favorites are:

  • IcoMoon: Can generate an SVG sprite or an icon font (or both) using any combination of stock icons or your own.
  • Grumpicon: Generates a CSS file with embedded SVG, as well as PNG fallbacks.

Both apps are free and easy to use, generating helpful code samples along with the assets themselves.

Use Pre-Made Icons

In addition to the stock icons available via the aforementioned IcoMoon, there are a growing number of SVG icon packs available. Some of the best we’ve seen so far:

  • Material icons: Google’s material design icons are open source, and available individually or as as a sprite.
  • Evil Icons: Free and open source icon pack with an intuitive markup syntax.
  • Glyph: Large icon pack available via Creative Commons.
  • Iconic: Not free, but SVG version is incredibly full-featured.
  • Resources like The Noun Project, SVG Icons and iconmonstr offer lots of great stock icons in SVG format.

If you have a favorite icon pack that doesn’t offer SVG as an option, ask for it! For example, here’s an open issue in the FontAwesome repo requesting the format.

And Many More!

SVG as a format is only as complicated as you need it to be. None of the aforementioned techniques are inherently less valid than the fancy-schmancy process we use at Cloud Four. You can start simple and stay there, or you can choose to expand on your process later on.

So give it a try! It’s probably less scary than you think.

Case Study: Our SVG Icon Process

When I wrote about why you shouldn’t use icon fonts in your next web project, I had no idea it would spark so much heated debate and intense discussion. One recurring question stood out to me: How might one actually implement an SVG icon system?

It’s a surprisingly difficult question to answer. Should you use <img>, <svg>, <object> or pure CSS? Will you combine your icons into a single sprite or keep them separate? If you do combine them, do you use an old-school technique or embrace SVG’s built-in features? Can JavaScript factor in somehow?

Though this variety of options might feel overwhelming, it’s ultimately a good thing. SVG’s versatility empowers us to craft the most appropriate solution for our audience and use-case.

So as much as I’d like to, I can’t say exactly how you should implement SVG icons in your next project. There’s no substitution for research and trying stuff out when it comes to finding the best fit for your project.

Instead, I’m going to show how we tend to assemble and implement SVG icons, and why we do it that way.

What We Do

The icon process we’ve adopted here at Cloud Four is a byproduct of the types of projects we take on, which tend to be large responsive redesigns or brand-new responsive interfaces. Our most common deliverables are in-browser mockups and pattern libraries. We often work with existing in-house teams, designing or extending icon systems based on their brand guidelines.

The front-end problems we solve tend to be those that are too complex or idiosyncratic to tackle with a framework or a simple content reflow. Our most common use of icons is to reinforce the meaning or relative importance of interface controls (a plus next to the word “Add,” a checkmark next to the word “Okay,” etc.).

Our Requirements

With this context in mind, we can assemble a list of requirements:

  • Accessibility: Because our icons represent or reinforce content, they should exist in markup.
  • Design: Our icons will most often coexist with text. They should inherit the text color and flow with the text by default.
  • Performance: Icons should be consolidated into a single, external sprite to avoid multiple requests and maximize caching.
  • Workflow: Whatever icon prep we can automate should be baked into our existing development tools (Node.js and Gulp).
  • Browsers: Our projects tend to be optimized for IE9+, Android 4.3+ and the usual array of less finicky modern browsers.

With requirements in hand, it’s time to build an SVG icon system!

1. Exporting Icons

Though our team digs Sketch for UI explorations, we still feel like Illustrator is a bit more intuitive for the design of icons and other illustrative elements.

We maintain a master icons.ai file in a shared spot (usually Dropbox), with each icon in the library residing in its own named artboard. We can see every icon in the context of its siblings, make any final tweaks for consistency, and simplify or combine any overlapping or unnecessary paths.

Screenshots of Illustrator artboards with icons

During this process, we purposely avoid preparing different rotations of the same icon. Traditionally, icon sets have exported separate assets for “left arrow,” “right arrow,” etc., but with SVG this repetition is redundant and unnecessary. Later on, we’ll walk through how to create simple rotational variations of the same icon.

Once everything’s looking good and feeling clean, we use Illustrator CC’s recently-improved exporting to generate SVGs from our artboards. After removing anything Illustrator over-enthusiastically prepended to our filenames, we’re ready to smoosh all of our icons into a single sprite.

2. Creating Our Sprite

As mentioned earlier, our team likes using Gulp for our local environment. If you’ve never used Gulp before, here’s a great article covering the basics. We’re going to write a Gulp task called icons this will compile a folder of separate, unoptimized SVG icons into a single, optimized sprite we can reference from our HTML.

Of the handful of plugins we’ve tried for accomplishing this sort of thing, our favorite is currently gulp-svg-sprite. It boasts a wealth of output modes and configuration options, making it the perfect choice for control freaks like yours truly.

For our icons task, we’ll be using the plugin’s symbol “mode.” This will transform each of our SVG files into a <symbol> element, which we’ll be able to reference by ID later.

Here’s what our SVG task might look like:

var gulp = require('gulp');
var svgSprite = require('gulp-svg-sprite');
 
var svgSpriteConfig = {
  mode: {
    symbol: {
      dest: '',
      sprite: 'icons.svg'
    }
  }
};
 
gulp.task('icons', function () {
  return gulp.src('./src/icons/**/*.svg')
    .pipe(svgSprite(svgSpriteConfig))
    .pipe(gulp.dest('dist'));
});

This task will:

  1. Find every SVG file in the src/icons directory.
  2. Pass those files to the gulp-svg-sprite plugin, which combines them into a single icons.svg file using the symbol output mode.
  3. Output the result to the dist directory.

Now if we run gulp icons, we should find a shiny new icons.svg file in our dist directory, ready to be referenced from our markup.

3. Including Icons in Our Markup

Now that we have our SVG sprite, we can reference it from our markup using <svg> and the <use> element:

<svg>
  <use xlink:href="icons.svg#back"/>
</svg>

This markup tells the browser “use the symbol with ID back from the file icons.svg.” This means our external file is nice and cacheable, and we can reference the same icon asset multiple times from the same file! Hooray!

Except, it looks like garbage:

Unstyled SVG icon in document

We haven’t told the browser how we want our icons to be sized, filled or aligned based on their surroundings. To do that, we need some CSS.

4. Styling Icons

We don’t want to style every svg because SVG can be used for a lot more than icons. Instead, we’re going to create a class. Our team likes using SUIT CSS naming conventions, so we’ll name our class Icon:

.Icon {
  /* Flow with text content */
  display: inline-block;
  /* Inherit the parent text color */
  fill: currentColor;
  /* Use the parent font-size for width and height */
  height: 1em;
  width: 1em;
  /* Vertically align icon with adjacent text */
  vertical-align: middle;
  /* Align more nicely with capital letters */
  position: relative;
  top: -0.0625em;
}

(Props to Chris Coyier and Jonathan Snook!)

Here’s the result after adding class="Icon" to our SVG element:

Styled SVG icon in document

Success! Our icons are successfully inheriting their size and color, and aligning nicely with adjacent type.

This accomplishes most of what we set out to do, but we haven’t taken advantage of what makes SVG special just yet. Let’s fix that.

5. Adding DRY Variations

Back when we were exporting icons, we only exported a single arrow asset (back.svg), the contents of which looked something like this:

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
  <path d="M22,10H6.83l3.59-3.59A2,2,0,0,0,7.59,3.59l-7,7a2,2,0,0,0,0,2.83l7,7a2,2,0,0,0,2.83-2.83L6.83,14H22A2,2,0,0,0,22,10Z"/>
</svg>

Let’s pop open our favorite code editor, and create a new forward.svg file to compliment it:

<svg xmlns="http://www.w3.org/2000/svg"
  xmlns:xlink="http://www.w3.org/1999/xlink" 
  viewBox="0 0 24 24">
  <use xlink:href="#back" transform="rotate(180 12 12)"/>
</svg>

Here’s what’s going on:

  1. Our <svg> element is identical to back.svg, except we’ve added an xmlns:xlink attribute. This helps avoid errors during optimization by letting the plugin know that this SVG will reference other elements.
  2. Instead of including the forward icon’s path data, we reference our existing #back icon from a <use> element (similar to how we reference icons from our markup).
  3. The transform attribute rotates the icon 180 degrees from the center of our viewBox.

If we recompile our sprite, we should now be able to reference both icons from our markup:

Original arrow icon and derivative icon in document

Any changes made to back.svg will cascade to forward.svg (or any future variations). Plus, we save a small amount of file-size in the compiled sprite. Win/win!

6. Enforcing Mandatory Colors

Sometimes there are icons that really shouldn’t inherit everything about the parent. A common concern we hear from design teams is that the meaning of certain icons (in particular those representing “error” or “warning”) can be diluted over time if they are applied inconsistently.

In these cases, it’s helpful to remember that SVG elements are subject to the same style cascade as everything else. By specifying mandatory colors via attributes on the elements themselves (fill, style, etc.), we can overrule some or all color inheritance.

As an example, this error.svg file has fill attributes on the elements themselves:

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
  <path fill="#ff4136" d="M13.74,3l9,15.7A2.21,2.21,0,0,1,20.9,22H3.1a2.21,2.21,0,0,1-1.8-3.34l9-15.7A2,2,0,0,1,13.74,3Z"/>
  <path fill="#fff" d="M10.59,17.82a1.41,1.41,0,1,1,1.4,1.4A1.42,1.42,0,0,1,10.59,17.82Zm2.77-9.63a32.3,32.3,0,0,1-.61,4.5l-0.34,2.11H11.6l-0.34-2.11a32.77,32.77,0,0,1-.61-4.5A1.24,1.24,0,0,1,12,6.78,1.24,1.24,0,0,1,13.36,8.18Z"/>
</svg>

Even with our .Icon class applied, these colors will not be overruled:

Error icon that will not inherit its fill color from document

7. Improving Accessibility

Arguably the best reason to adopt SVG is to take advantage of its accessibility features. Thanks to Léonie Watson’s Tips for Creating Accessible SVG, we know to add the following elements and attributes to our icons:

<svg
  xmlns="http://www.w3.org/2000/svg" 
  viewBox="0 0 24 24"
  aria-labelledby="title desc">
  <title id="title">Back</title>
  <desc id="desc">A leftward arrow</desc>
  <path d="M22,10H6.83l3.59-3.59A2,2,0,0,0,7.59,3.59l-7,7a2,2,0,0,0,0,2.83l7,7a2,2,0,0,0,2.83-2.83L6.83,14H22A2,2,0,0,0,22,10Z"/>
</svg>

This insures that our icons have human readable fallbacks for blind and partially sighted people in a variety of user agents.

But there’s a problem with this approach. IDs must be unique, and we’ll be combining multiple files into a single SVG document. Our accessibility efforts will be thwarted if two <title> or <desc> elements attempt to use the same ID within the same document.

We could just be really diligent about choosing unique IDs, but that’s kind of a pain. If only we could manage these titles and descriptions in a central location, relying on our Gulp task to assign unique identifiers…

Luckily, we can! All we need to do is provide all our titles and descriptions in a separate YAML file:

back:
  title: Back
  description: A leftward arrow

error:
  title: Error
  description: A red sign with a white exclamation mark

forward:
  title: Forward
  description: A rightward arrow

search:
  title: Search
  description: A magnifying glass

Then update the Gulp task with the location of that file:

var svgSpriteConfig = {
  mode: { /* ... */ },
  shape: {
    // Titles and descriptions
    meta: './src/icons/icons.yaml'
  }
};

When we run gulp icons again, gulp-svg-sprite will add <title> and <desc> elements with unique, namespaced IDs and update the aria-labelledby attribute accordingly.

(It’s important to note that while we’ve specified <title> and <desc> elements within our sprite, you should still take care to use accessibility attributes in the page itself when the icon’s meaning is not re-enforced by its surrounding content.)

8. Supporting More Browsers

Time to address the elephant in the room…

Our icon sprite is a separate file, which is great for caching. But referencing symbols in an external file doesn’t work in Internet Explorer (though it does in Edge).

Icons not displaying in IE10

To address that, we’re going to use a polyfill called svgxuse. The script works by detecting failed external references, loading the referenced file via AJAX, injecting the sprite into the page itself, and updating the xlink:href attributes to point to the in-page resource. We like svgxuse because it minimizes the duplicated path data while retaining the ability for icons to reference each other.

The polyfill will work as-is, but we should make a couple of changes one small change to our task config to avoid any collisions with in-page content:

var config = {
  mode: { /* ... */ },
  shape: {
    // Titles and descriptions
    meta: SRC + '/icons/icons.yaml',
    // Add suffix to IDs
    id: {
      generator: '%s-icon'
    }
  }
};

Now we won’t have to worry about the SVG sprite being visible in Internet Explorer, and the IDs for our icons are far less susceptible to collisions once they coexist in the same document. Once we update our icon references to include the -icon suffix, we should have our target browsers covered:

Icons displaying in IE10 with svgxuse

Update: An earlier version of this post included specific configuration options for hiding the injected SVG sprite, but svgxuse handles that automatically now. Open source is awesome!

Putting It All Together

We made it! Here’s what we accomplished:

  • Our Gulp task will compile a folder of icons into a single, cacheable SVG sprite.
  • Individual icons can be referenced one or more times from anywhere in our HTML document.
  • By default, icons will base their position, size and color on their parent elements and surrounding text.
  • Icons may defy the default styles where appropriate.
  • To avoid repetition, some icons can be simple variations of others.
  • We can specify conflict-free accessibility details within icons.yaml.
  • When external references fail, the asset will be injected into the page itself.

You can see a live demo of the end result or browse the code.

Our completed SVG icon demo

Before we pat ourselves on the back too vigorously, it’s important to remember that that there is no one, true SVG icon process. Your ideal setup might involve the picture element, grunt-svgstore, SVGInjector or even an existing library. It can and should change based on the needs of your project. We modify ours all the time.

So consider this just one potential starting point for your own SVG icon system. I hope you’ll share what you come up with!