Tags: frontend

623

sparkline

Thursday, January 19th, 2017

Improving accessibility in Co-op wills – Digital blogs

Some interesting insights from usability and accessibility testing at the Co-op.

We used ‘nesting’ to reduce the amount of information on the page when the user first reaches it. When the user chooses an option, we ask for any other details at that point rather than having all the questions on the page at once.

bastianallgeier/letter: Letter is a simple, highly customizable tool to create letters in your browser.

A nice little use of print (and screen) styles from Bastian—compose letters in a web browser.

Instead of messing around in Word, Pages or even Indesign, you can write your letters in the browser, export them as HTML or PDF (via Apple Preview).

Understanding the Critical Rendering Path

A nice and clear description of how browsers parse and render web pages.

Let them paste passwords - NCSC Site

Ever been on one of those websites that doesn’t allow you to paste into the password field? Frustrating, isn’t it? (Especially if you use a password manager.)

It turns out that nobody knows how this ever started. It’s like a cargo cult without any cargo.

Making input type=date complicated – Samsung Internet Developers – Medium

PPK has posted some excellent thinking on calendar widgets to Ev’s blog.

Sunday, January 15th, 2017

Using the aria-current attribute – Tink

The aria-current attribute is very handy and easy to implement. Léonie explains it really well here.

Modernizing our Progressive Enhancement Delivery | Filament Group, Inc., Boston, MA

Scott runs through the latest improvements to the Filament Group website. There’s a lot about HTTP2, but also a dab of service workers (using a similar recipe to my site).

Browser Support for evergreen websites

Oh, how I wished everyone approached building for the web the way that Rachel does. Smart, sensible, pragmatic, and exciting!

Wednesday, January 11th, 2017

Making Resilient Web Design work offline

I’ve written before about taking an online book offline, documenting the process behind the web version of HTML5 For Web Designers. A book is quite a static thing so it’s safe to take a fairly aggressive offline-first approach. In fact, a static unchanging book is one of the few situations that AppCache works for. Of course a service worker is better, but until AppCache is removed from browsers (and until service worker is supported across the board), I’m using both. I wouldn’t recommend that for most sites though—for most sites, use a service worker to enhance it, and avoid AppCache like the plague.

For Resilient Web Design, I took a similar approach to HTML5 For Web Designers but I knew that there was a good chance that some of the content would be getting tweaked at least for a while. So while the approach is still cache-first, I decided to keep the cache fairly fresh.

Here’s my service worker. It starts with the usual stuff: when the service worker is installed, there’s a list of static assets to cache. In this case, that list is literally everything; all the HTML, CSS, JavaScript, and images for the whole site. Again, this is a pattern that works well for a book, but wouldn’t be right for other kinds of websites.

The real heavy lifting happens with the fetch event. This is where the logic sits for what the service worker should do everytime there’s a request for a resource. I’ve documented the logic with comments:

// Look in the cache first, fall back to the network
  // CACHE
  // Did we find the file in the cache?
      // If so, fetch a fresh copy from the network in the background
      // NETWORK
          // Stash the fresh copy in the cache
  // NETWORK
  // If the file wasn't in the cache, make a network request
      // Stash a fresh copy in the cache in the background
  // OFFLINE
  // If the request is for an image, show an offline placeholder
  // If the request is for a page, show an offline message

So my order of preference is:

  1. Try the cache first,
  2. Try the network second,
  3. Fallback to a placeholder as a last resort.

Leaving aside that third part, regardless of whether the response is served straight from the cache or from the network, the cache gets a top-up. If the response is being served from the cache, there’s an additional network request made to get a fresh copy of the resource that was just served. This means that the user might be seeing a slightly stale version of a file, but they’ll get the fresher version next time round.

Again, I think this acceptable for a book where the tweaks and changes should be fairly minor, but I definitely wouldn’t want to do it on a more dynamic site where the freshness matters more.

Here’s what it usually likes like when a file is served up from the cache:

caches.match(request)
  .then( responseFromCache => {
  // Did we find the file in the cache?
  if (responseFromCache) {
      return responseFromCache;
  }

I’ve introduced an extra step where the fresher version is fetched from the network. This is where the code can look a bit confusing: the network request is happening in the background after the cached file has already been returned, but the code appears before the return statement:

caches.match(request)
  .then( responseFromCache => {
  // Did we find the file in the cache?
  if (responseFromCache) {
      // If so, fetch a fresh copy from the network in the background
      event.waitUntil(
          // NETWORK
          fetch(request)
          .then( responseFromFetch => {
              // Stash the fresh copy in the cache
              caches.open(staticCacheName)
              .then( cache => {
                  cache.put(request, responseFromFetch);
              });
          })
      );
      return responseFromCache;
  }

It’s asynchronous, see? So even though all that network code appears before the return statement, it’s pretty much guaranteed to complete after the cache response has been returned. You can verify this by putting in some console.log statements:

caches.match(request)
.then( responseFromCache => {
  if (responseFromCache) {
      event.waitUntil(
          fetch(request)
          .then( responseFromFetch => {
              console.log('Got a response from the network.');
              caches.open(staticCacheName)
              .then( cache => {
                  cache.put(request, responseFromFetch);
              });
          })
      );
      console.log('Got a response from the cache.');
      return responseFromCache;
  }

Those log statements will appear in this order:

Got a response from the cache.
Got a response from the network.

That’s the opposite order in which they appear in the code. Everything inside the event.waitUntil part is asynchronous.

Here’s the catch: this kind of asynchronous waitUntil hasn’t landed in all the browsers yet. The code I’ve written will fail.

But never fear! Jake has written a polyfill. All I need to do is include that at the start of my serviceworker.js file and I’m good to go:

// Import Jake's polyfill for async waitUntil
importScripts('/js/async-waituntil.js');

I’m also using it when a file isn’t found in the cache, and is returned from the network instead. Here’s what the usual network code looks like:

fetch(request)
  .then( responseFromFetch => {
    return responseFromFetch;
  })

I want to also store that response in the cache, but I want to do it asynchronously—I don’t care how long it takes to put the file in the cache as long as the user gets the response straight away.

Technically, I’m not putting the response in the cache; I’m putting a copy of the response in the cache (it’s a stream, so I need to clone it if I want to do more than one thing with it).

fetch(request)
  .then( responseFromFetch => {
    // Stash a fresh copy in the cache in the background
    let responseCopy = responseFromFetch.clone();
    event.waitUntil(
      caches.open(staticCacheName)
      .then( cache => {
          cache.put(request, responseCopy);
      })
    );
    return responseFromFetch;
  })

That all seems to be working well in browsers that support service workers. For legacy browsers, like Mobile Safari, there’s the much blunter caveman logic of an AppCache manifest.

Here’s the JavaScript that decides whether a browser gets the service worker or the AppCache:

if ('serviceWorker' in navigator) {
  // If service workers are supported
  navigator.serviceWorker.register('/serviceworker.js');
} else if ('applicationCache' in window) {
  // Otherwise inject an iframe to use appcache
  var iframe = document.createElement('iframe');
  iframe.setAttribute('src', '/appcache.html');
  iframe.setAttribute('style', 'width: 0; height: 0; border: 0');
  document.querySelector('footer').appendChild(iframe);
}

Either way, people are making full use of the offline nature of the book and that makes me very happy indeed.

ryanmcdermott/clean-code-javascript: Clean Code concepts adapted for JavaScript

This looks a sensible approach to writing clean JavaScript.

A Tale of Four Caches · Yoav Weiss

A cute explanation of different browser caches:

  • memory cache,
  • service worker cache,
  • disk cache, and
  • push cache.

Friday, January 6th, 2017

Redesign v15 Notes | CSS-Tricks

Chris redesigned CSS Tricks and it’s got some really nice touches. I particularly like the stacked card view on mobile.

Thursday, January 5th, 2017

What AMP (Maybe) Means for News Developers - Features - Source: An OpenNews project

So if AMP is useful it’s because it raises the stakes. If we (news developers) don’t figure out faster ways to load our pages for readers, then we’re going to lose a lot of magic.

A number of developers answered questions on the potential effects of Google’s AMP project. This answer resonates a lot with my own feelings:

AMP is basically web performance best practices dressed up as a file format. That’s a very clever solution to what is, at heart, a cultural problem: when management (in one form or another) comes to the CMS team at a news organization and asks to add more junk to the site, saying “we can’t do that because AMP” is a much more powerful argument than trying to explain why a pop-over “Like us on Facebook!” modal is driving our readers to drink.

But the danger is that AMP turns into a long-term “solution” instead of a stop-gap:

So in a sense, the best possible outcome is that AMP is disruptive enough to shake the boardroom into understanding the importance of performance in platform decisions (and making the hard business decisions this demands), but that developers are allowed to implement those decisions in standard HTML instead of adding yet another delivery format to their export pipeline.

The ideal situation looks a lot more like Tim’s proposal:

I would be much more pleased with AMP if it was a spec for Google’s best-practice recommendations rather than effectively a new non-standard format. By using standard HTML/CSS/JS as the building blocks, they’re starting on the right foot, but the reliance on a Google-decreed AMP JavaScript library, use of separate AMP-specific URLs, and encouragement to use a Google-provided CDN are all worrying aspects.

Tuesday, January 3rd, 2017

Kiss My Classname - Zeldman on Web & Interaction Design

I understand how bloated and non-reusable code can get when a dozen people who don’t talk to each other work on it over a period of years. I don’t believe the problem is the principle of semantic markup or the cascade in CSS. I believe the problem is a dozen people working on something without talking to each other.

Pattern patter. — Ethan Marcotte

Ethan has been thinking smarty-thinky thoughts about patterns and pattern libraries.

Does Google execute JavaScript? | Stephan Boyer

Google may or may not decide to run your JavaScript, and you don’t want your business to depend on its particular inclination of the day. Do server-side/universal/isomorphic rendering just to be safe.

Vertical limit

When I was first styling Resilient Web Design, I made heavy use of vh units. The vertical spacing between elements—headings, paragraphs, images—was all proportional to the overall viewport height. It looked great!

Then I tested it on real devices.

Here’s the problem: when a page loads up in a mobile browser—like, say, Chrome on an Android device—the URL bar is at the top of the screen. The height of that piece of the browser interface isn’t taken into account for the viewport height. That makes sense: the viewport height is the amount of screen real estate available for the content. The content doesn’t extend into the URL bar, therefore the height of the URL bar shouldn’t be part of the viewport height.

But then if you start scrolling down, the URL bar scrolls away off the top of the screen. So now it’s behaving as though it is part of the content rather than part of the browser interface. At this point, the value of the viewport height changes: now it’s the previous value plus the height of the URL bar that was previously there but which has now disappeared.

I totally understand why the URL bar is squirrelled away once the user starts scrolling—it frees up some valuable vertical space. But because that necessarily means recalculating the viewport height, it effectively makes the vh unit in CSS very, very limited in scope.

In my initial implementation of Resilient Web Design, the one where I was styling almost everything with vh, the site was unusable. Every time you started scrolling, things would jump around. I had to go back to the drawing board and remove almost all instances of vh from the styles.

I’ve left it in for one use case and I think it’s the most common use of vh: making an element take up exactly the height of the viewport. The front page of the web book uses min-height: 100vh for the title.

Scrolling.

But as soon as you scroll down from there, that element changes height. The content below it suddenly moves.

Let’s say the overall height of the browser window is 600 pixels, of which 50 pixels are taken up by the URL bar. When the page loads, 100vh is 550 pixels. But as soon as you scroll down and the URL bar floats away, the value of 100vh becomes 600 pixels.

(This also causes problems if you’re using vertical media queries. If you choose the wrong vertical breakpoint, then the media query won’t kick in when the page loads but will kick in once the user starts scrolling …or vice-versa.)

There’s a mixed message here. On the one hand, the browser is declaring that the URL bar is part of its interface; that the space is off-limits for content. But then, once scrolling starts, that is invalidated. Now the URL bar is behaving as though it is part of the content scrolling off the top of the viewport.

The result of this messiness is that the vh unit is practically useless for real-world situations with real-world devices. It works great for desktop browsers if you’re grabbing the browser window and resizing, but that’s not exactly a common scenario for anyone other than web developers.

I’m sure there’s a way of solving it with JavaScript but that feels like using an atomic bomb to crack a walnut—the whole point of having this in CSS is that we don’t need to use JavaScript for something related to styling.

It’s such a shame. A piece of CSS that’s great in theory, and is really well supported, just falls apart where it matters most.

Update: There’s a two-year old bug report on this for Chrome, and it looks like it might actually get fixed in February.

Exciting times: 2017 and the web - Tales of a Developer Advocate by Paul Kinlan

Paul takes a look at the year ahead on the web and likes what he sees. There’s plenty of new browser features and APIs of course, but more interesting:

The web reaching more people as they come online with Mobile. There is still a huge amount of potential and growth in India, Indonesia, China, Thailand, Vietnam, all of Africa. You name it, mobile is growing massively still and the web is accessible on all of these devices.

Sunday, January 1st, 2017

In Praise of On Resilient Web Design by Jeremy Keith

I’m really touched—and honoured—that my book could have this effect.

It made me fall back in love with the web and with making things for the web.

Front-end Style Guides by Anna Debenham

Anna has just published a lovely new version of her excellent little book on pattern libraries. EPUB, MOBI, and PDF versions are yours for a mere $8.