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.

Service Workers at Scale, Part I: CDNs and Multiple Origins

We recently got the opportunity to develop a service worker for use on Smashing Magazine, which we’ll write about in more detail soon. This is the first of a multi-part article that will examine some of the solutions we arrived at and lessons we learned.

One of the challenges we’ve encountered while developing this worker is strategic caching for external resources. Most of the service worker examples we’ve seen address handling requests for local resources on the same domain. But pages served by complex sites often need to fetch (and cache) assets from external domains as well. Things can get complicated when these various domains need special handling, so we need a manageable way to structure our service worker to evaluate requests for both local and external resources.

Special handling for CDNs and subdirectories

The host of our service worker happens to be a WordPress site with assets requested from both the local server as well as CDNs. We need to handle fetch events differently depending on which domain or subdirectory they relate to. Some CDN requests need to be routed to cache functions, and some local requests (such as those for pages within the admin area) need to be ignored altogether. To fulfill this behavior, we need some way to designate rules for different URL origins.

One approach uses regular expressions. We need to match the URLs of fetch event requests against a set of base URLs, and using RegExp for this makes sense. In practice, this method works well initially, but maintenance becomes more of a concern as the patterns get more complex.

Take for example an entry to match “content pages”:

const CACHE_PATTERNS = {
  // ...
  contentPage: new RegExp(
    `^${self.location.origin}\/((?!wp-admin).*)$`
  ),
  // ...
};

This will match any local URLs except for ones with wp-admin following the first slash. It’s not a complicated pattern as-is, but what about when we need to add another subdirectory exception? Is there another approach that will cater more to maintainability and comprehension?

Comparing URLs with the URL class

Let’s substitute the great power and responsibility of regular expressions for a more explicit way to classify URLs. Using a Map structure to represent the base URLs to handle fetch events for, we can “flag” some items to indicate them as subdirectories to ignore:

const CACHE_FLAGS = {
  ignore: -1
};
 
const URL_MAP = new Map([
  ['/'],
  ['/wp-admin/', CACHE_FLAGS.ignore],
  ['/search-results/', CACHE_FLAGS.ignore],
  ['http://1.gravatar.com/'],
  ['https://media-mediatemple.netdata-ssl.com/wp-content/'],
]);

It’s more verbose, but it provides a clear interface for maintaining the list of base URLs we want to act on.

From this core list, we can derive more specific ones. Each of the derived lists consists of URL instances:

const URLS_TO_IGNORE = [];
const URLS_TO_HANDLE = [];
 
URL_MAP.forEach(function (flag, baseUrl) {
  const url = new URL(baseUrl, self.location);
  if (flag === CACHE_FLAGS.ignore) {
    URLS_TO_IGNORE.push(url);
  } else {
    URLS_TO_HANDLE.push(url);
  }
});

With our subjects of interest stored as URL instances, we can then use properties like origin and pathname in our logic:

function isIgnoredUrl (url) {
  // URL minus the query string and hash
  const urlBase = `${url.origin + url.pathname}/`;
  const isMatch = ({ origin, pathname }) =>
    urlBase.startsWith(origin + pathname);
 
  return URLS_TO_IGNORE.some(isMatch) // flagged "ignore"
    || !URLS_TO_HANDLE.some(isMatch); // altogether unlisted
}

Should this request be handled?

With our URL classifications and helper functions in place, the fetch event handler can use them to decide if it needs to intercept a request:

self.addEventListener('fetch', function (event) {
  const request = event.request;
  const url = new URL(request.url);
  const isGet = request.method === 'GET';
 
  // Requests we don't care to handle
  if (!isGet || isIgnoredUrl(url)) {
    event.respondWith(fetch(request));
    return;
  }
 
  // Requests we do care to handle
  event.respondWith(
    // Additional cache and/or fetch strategy
  );
});

Coming up next: Using URL properties for Offline fallbacks

In part two, we’ll take a look at another unique challenge this project presented: serving URL-aware offline fallbacks.

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.