Skip to content


Password field UX woes


How do I know my keyboard is dropping characters on a password field?

The Long

A power cut took out my home server–a Mac Mini running macOS High Sierra. It (sensibly?) has a boot password and encrypted SSD. I brought the system back online to be prompted with the usual login screen. No matter what I did, it would not accept my password.

The Good

After 3 attempts, macOS prompted me with a “reminder” (and suggested I could use a recovery key).

The Bad

The rarely-typed password is pretty hard to enter correctly (that’s on me). But you cannot use a password manager this early in the boot process. There is also no feedback other than the masked characters in the input field, no way to visibly validate the characters being entered into the password field.

There’s a good pattern used in web for assisting here: put the visibility of unmasked password fields in the hand of the user. In my case, the Bluetooth keyboard was misbehaving: it apparently was dropping keypresses (a desperate keyboard swap accidentally fixed the problem).

The UX

Arguably this was all an edge case. I mean how often do you have a broken keyboard? But then you’d be ignoring an accessibility red flag: the input fails due to physical device awkwardness with no user feedback what so ever (other than “try again”). So what about users with alternative input devices?

Apple solved this on iOS. When you tap a key on any field (including password fields) you can get brief flash of that key. Elsewhere on web, a field can toggled between text/password visually, giving the user control of when the field is exposed.

Here’s a demo I put together a while back with progressively enhance password toggling for web:

Screenshot of form with regular password field
Password field (open to see on CodePen)

The question is why this sort of toggle hasn’t made it into macOS.

Visual regression testing with Wraith

I’ve had a play with this before, but new machine, new set-up, this time I’ll document it…

First, what is Visual Regression Testing?

Simply, the visual comparison of two versions of a page, and highlighting any differences. It’s spot the difference for web folks.

It’s important to note this compliments other testing, catching the sort of difference easily missed in QA and by functional testing (be that in in CI or elsewhere). It also still requires someone to actually look and the output. Humans are significantly better at spotting things that are wrong, but they first need to be presented with the possibility that something could be wrong.

Okay, what is Wraith?

Wraith is a tool created by the BBC for automating some aspects visual regression testing.

Given two domains, it can compare pages between those domains. Wraith will highlight differences between pages (for example, a page on your local dev or pre-prod environment and a production environment) and save these as a screenshot for you to manually check. It will also flag unexpected percentage of difference, indicating if you have a potential problem.

Screenshot of Wraith output
Wraith output
Wraith output screenshot
Wraith visual output screenshot

Installing Wraith

  • Install HomeBrew. This is will take all the pain away. HomeBrew is a package manager for macOS and saves you having to mess around with installation paths and version management.
  • Install ImageMagick. This is required by Wraith to generate screenshots for comparison. From a terminal:
brew install imagemagick
  • Intall PhantomJS. This is a headless web browser that will load your site
brew install phantomjs
  • Install Wraith. Wraith itself is a Ruby package, and this assumes you have Ruby installed. Ruby ships with macOS, so we’re good to go:
gem install wraith

Now we have all the bits we need to run Wraith, we need to configure it to run.

You could run wraith setup but I prefer a hand-crafted config. You can save this into a config.yaml folder in your project, or wherever you’re doing CI testing. It should be pretty self-explanatory. Here’s the config for one one my sites:

browser: "phantomjs"
  current:  ""
  dev:   "http://localhost:3001"
  home:     /
  - 320
  - 600x768
  - 768
  - 1024
  - 1280
directory: 'wraith'
fuzz: '20%'
Default: 0
threshold: 5
  template: 'slideshow_template'
  thumb_width:  200
  thumb_height: 200
mode: diffs_first

On my particular setup, I have a dev copy running on port 3001 of my local Mac. This could be set to wherever your test environments live (CI environment, for example).

Running Wraith

As we installed a global ruby gem for Wraith and global prerequisites via Homebrew, you can run Wraith from anywhere on your system. It doesn’t have to be in your project folder.

Note: You may actually want to avoid committing your Wraith configuration to your project as it could expose testing URLs and other setup that you don’t want public.

  • Run Wraith with our configuration
wraith capture ./configs/capture.yaml

Wraith terminal screenshot

Wraith terminal screenshot

  • Wraith will provide a summary and will generate a series of screenshots. These can be found (in my case) in ./wraith/home/. These contain screenshots of each URL, a thumbnail, and a 3rd file containing the differences between URL.
  • Wraith also generates a gallery of ./wraith/gallery.html

In my setup I ran Wraith from my project folder, so Wraith’s gallery was served along with that on port 3001

Wraith gallery screenshot


Wraith documentation

Personal site refresh and BrowserSync gotcha

This sketch never made it into Sketch App…

After the experiments with branding earlier this week, it was about time I gave my ‘business card’ site at a lick of paint. Didn’t want anything showy. Just a nice landing page for my main domain that leads off to various places I squirrel stuff.

It’s hand-crafted with no frameworks with SCSS, and a custom grunt job to glue it all together. While grunt has been somewhat superseded by other (“better”) task runners, it’s still dirt simple to put something together that’ll compile your SCSS on the fly and give a live-view (via BrowserSync) in a browser as you’re building. The latter I find essential when building more traditional projects.

The code for this project can be found in github.

Screenshot of version 1.0
I guess I’m happy with this as a version 1.0.

Dev notes: BrowserSync failing to do anything via Grunt.

Had an interesting issue with BrowserSync and Watch tasks. BrowserSync was refusing to refresh (or even load). Turns out that the task order in Grunt matters a lot when it comes to BrowserSync. Any watch tasks must happen after BrowserSync or it can just silently fail.

Working example:

grunt.registerTask('default', [], () => {
 grunt.loadNpmTasks('grunt-contrib-watch');'browserSync', 'version', 'styles', 'watch');

Personal branding experiments

I’m having a lot of fun working on a personal brand at the moment. Part in due for being back on the market for a new front end role, but also because it has been ages since I got to dig into some design work for me.

But then again, I’m my own worst client. I knew I wanted something tactile, something that hinted at development, design and my nickname (origins decades old, don’t ask), something that would work well online and print. Tough getting all that into something simple.

After much sketching, pondering Pinterest boards, and staring bleakly at empty PhotoShop artboards, it was folding a paper plane for my daughter that inspired the design I’m happiest with.

An image of tiles demonstrating different logo treatments
I think “4b” works best

Then came the iterations, testing out business card and web layouts, but I’m pretty pleased with the results so far.

A stylised letter S

  • A chevron (think </> code)
  • A hint of an “S”.
  • Could be a physical foldable thing
  • Simple and geometric, lending itself for fun animations
  • …and lots of reusable elements.




Which is all fine on paper (uh, in Sketch app), but it needs to work online. Given the nice geometric nature of the elements of the logo, it’s not too hard. This would’ve been a nightmare if I’d started out in PhotoShop, and I’m a big fan of doing as much as possible in Sketch these days.

  • Sketch app (Mac)
  • Sketch ‘edit’ symbols to get corner coordinates for each triangle >
  • Manually enter coordinates as clip masks in CSS (CodePen)

And finally, we can play with it in CodePen. This gives me loads of room for adding nice folding animations (a task for another evening).

Animating SVG (CSS vs. GreenSock GSAP)

Inline SVGs (not those loaded as images) can be styled like any other collection of DOM elements. But there appear to be a few limitations. Primarily, due to the way transforms (coordinates) are handled within SVG relative positioning is hard.

I really wanted to explore animating SVG elements with purse CSS, and to an extent this went swimmingly… until I started trying to animate the SVGs child elements.

CSS animation on CodePen 

Screenshot of CSS animated SVG
Animated via CSS (CodePen)

As the coordinates inside an SVG are relative to the grouped elements inside the SVG definition (rather than the HTML DOM, or the window), when we start trying to position child elements I quickly hit a wall.


Defeated (for now) I picked up the oddly named GreenSock animation library (GSAP). It’s shockingly easy to get up and running. Once we have the GSAP library referenced in our code,

var myElementHandle = new
  document.getElementById("mySVGElement"), 160, 
    rotation: 360, transformOrigin:"center center", ease: Linear.easeNone, repeat:-1

GSAP animation on CodePen

Screenshot of SVG animated with GSAP
Animated via GSAP (CodePen)

Now we can target anything we want using names or class and GSAP will do the heavy lifting. A passive function of GSAP is how it handles changing animations (for example, triggering a new animation on mouseover on an element that is already animating). GSAP will blend any active animations to ensure a smooth interaction—something not possible in CSS.

As we’re relying on JS, it’s really easy for us to start manipulating our SVG in other ways too, such as generating new elements and handling interaction. For example, I added a couple of experimental functions:

// Creates a new svg element [id] attached to [parentID]
function createSVGElement(id, cssClass, x, y, parentID) {
  var svg = document.createElementNS("","circle");
  svg.setAttributeNS(null, "class", cssClass);

And this…

// Creates a clone of svg element [id] as [newID]
function cloneSVG(id, newID, x, y, parentID) {
  var node = document.getElementById(id);
  var newNode = node.cloneNode("true"); = newID;
  newNode.setAttributeNS(null, "cx", x);
  newNode.setAttributeNS(null, "cy", y);

Dev Notes

I’ve used SVG shapes generated from Sketch here, so had to make sure any elements / groups I wanted to target with JS had names. Sketch will slugify the names if you don’t add something JS-safe yourself.


Linked radio buttons with CSS

Screenshot of styled radio buttons
Regular form elements, heavily styled.


It’s a pattern we see fairly often across the web: a series of ‘buttons’ connected by lines to indicate procession, ratings or steps. The trick is to make it as flexible and accessible as possible, and this is perfectly achievable without JavaScript.

Using regular form elements as our base, we can use a little extra markup and some trickery with CSS ::before and ::after to create attractive (or… excessively pink) results without sacrificing the underlying accessibility.


So we start with a regular ordered list:

<ol class="nodes">
 <li class="node">
   <input class="radio" type="radio" id="r1" name="radio-set">
   <label class="label" for="r1">1</label>
 <li> ... </li>

We’re using accessible markup, making sure we have a label and that the label is referencing the field (via for=). Any interaction with the label will be passed onto the field itself, which is key as we’re going to play with the label to give us our fancy inputs.


We take the label, and use ::before and ::after to position circles on top of the real form input to mask it, and getting our desired look. As these pseudo-elements are children of the <label>, any interaction with this label is passed through to the form field below. We simply layer things up:




.label {

 &::before {
  display: block;
  position: absolute;
  left: 0; right: 0; bottom: 0; top: 0; // trick to fill element
  margin: auto;
  z-index: 1; // ensures this is displayed above form field
  width: 60px;
  height: 60px;
  content: " ";
  border-radius: 50%;
  background-color: pink;
 &::after {

The final step is ensuring that the :checked state of the radio button is reflected by our fancy styling:

 .radio:checked + .label::after {
   background-color: white;

As we want our list to adapt to the space available in the browser, we can use css flex with justification property to ensure each li is evenly spaced:

.node {
 display: flex;
 justify-content: space-between;

By adding an additional  ::after on the .node itself, we can join the nodes together. Note, we’re deliberately offsetting the start of the pseudo-element so that the line stretches from the centre of the element to the right edge of the <li>.

.node::after {
  display: block;
  position: absolute;
  left: 60%; right: 0; bottom: 0; top: 50%;
  content: " ";
  height: 6px; width: 100%;
  background-color: lighten($color-base, 20%);

Finally, you’ll need to remove the line from the last child as we do not want a line going off into nowhere:

.node:last-child {
  &::after {
   display: none;

Interaction and animation

By adding transforms and transition delays we can achieve all kinds of over-the-top effects. Advice: don’t over use this, remember the UX.

Go have a play (CodePen)

Dev notes

We’re making heavy use of display:flex and positioned elements here, and while it all remains flexible across most modern browsers, flex can be rather buggy. You could probably achieve much of this using CSS display:table, or if you were daring, regular float.

Magic social icons with CSS

Screenshot of a social icon selected with CSS
Social icons selected via CSS

This is a simple trick for automatically displaying icons (such as social icons) without any script. Using a CSS wildcard selector, we check the href of our link and display a pseudo-element with matching content.

a[href*=""]::before {
 content: "\f113";

The above example uses a Font-Awesome glyph as content, but this could easily be replace with an image: content: url(/path/image.svg). Any subsequent link matching our selector would display our pseudo-element.

A demo of this technique can be found here on CodePen.

Dev notes

Be careful with your selectors. You could end up accidentally styling links that have been entered into a user-editable field (such as a CMS)… unless that’s what you really want. Wildcard selectors require the browser to do extra work, so you should use sparingly.

Playing with SCSS loops

Screenshot of tiles
Tiles using flex, loop and one preset colour.

SCSS offers a few control directives that enable us to perform some rather interesting effects.

In this example, I use a simple for loop to change a single colour value and apply that to a series of 25 <div> elements.


A basic loop is straight forward:

 @for $i from 1 through 25 {

So, if we have a base colour $color-green: #00ff00 we can simply multiply the current iteration $i by an arbitrary value, and perform an SCSS filter (such as darken, lighten) on that value. Bingo:

$color-green: #00ff00;
$increment: 1.5;

.my-class {
  @for $i from 1 through 25 {
    &:nth-child( #{$i} ) {
      $col: $i * $increment;
      background-color: darken($color-green, $col);

This will loop through 25 elements that have the class my-class and apply an increasingly dark background colour to each.

An little expermiment featuring this can be found over here on CodePen.

Dev Notes

I’m using flex and vw/vh units to give us a perfectly tiled full-page result. This may not work in all browsers. I wrote a little about viewport units in another post earlier.

Battery Status API experiment

Screenshot of JavaScript battery API experiment
Battery UI element

The JavaScript Battery Status API offers some interesting additional functionality that we can leverage for UI elements. Browser support is getting better—at the time of writing (Feb, 2017), Chrome, FireFox and Opera are good to go, but leaves glaring omissions of Safari/iOS.

This little experiment creates a simple battery UI element, with its background an indicator of battery percentage remaining (plus percentage text): CodePen Experiment

The API provides a bunch of events we can hook into:

  • chargingchange – is the battery charging?
  • levelchangepercentage of battery remaining
  • chargingtimechangeamount of time until battery is charged (estimate)
  • dischargingtimechangeamount of time until batter is discharged (estimate)

All we need to do is check that we have support for the API and off we go:

navigator.getBattery().then(function(battery) { ... });

Once we know we have battery API support, we can go ahead and add some listeners for the new events and update our UI as we need. Note, we don’t use any libraries here, this is raw JavaScript:

const $batteryPercentage = document.querySelector(".js-guage");
const $batteryPercentageDisplay = document.querySelector(".js-percentDisplay");
const $batteryStatusDisplay = document.querySelector(".js-statusDisplay");

navigator.getBattery().then(function(battery) {
 function initBattery(){
 battery.addEventListener('chargingchange', function(){
 battery.addEventListener('levelchange', function(){
 function updateChargeInfo(){
   let _batteryChargeStatus = battery.charging ? "Battery Charging" : "Battery Draining"; 
   $batteryStatusDisplay.innerHTML = _batteryChargeStatus;

 function updateLevelInfo(){
   let _batteryLevel = Math.round(battery.level * 100) + "%";
   $ = _batteryLevel;
   $batteryPercentageDisplay.innerHTML = _batteryLevel;


What could we use the Battery Status API for?

  • Intensive or full-screen scripts could warn the user if the battery was low before beginning, such as Canvas, WebGL or media handling.
  • Coupled with up-coming CSS selector prefers-reduced-motion we could trigger low-animation CSS when the battery is getting tight.

Details of support for the Battery Status API can be found on Can I Use.

Responsive navigation UX experiment

Mobile navigation frequently consists of a burger menu placed in the top right of the viewport. But consider this: a user with a large phone using just one hand, can their thumb stretch that far? This is particular issue on the larger format phones such as an iPhone 7 Plus.

Some of the UX niggles in mobile navigation:

  • Awkward one handed navigation
  • Fiddly menu and links
  • Inappropriate menu items for context of device
  • Little room for styled menus or call to actions

The following experiment explores an alternative to the hamburger menu, with a focus on improving the UX. I’m using a tiny bit of JavaScript to handle the mobile navigation toggle, but the layout is entirely through CSS.

Screenshot of mobile menu opened (links to demo CodePen)
Mobile UI

The experiment

  • Move the navigation to the bottom. By placing the menu toggle where it is easily reached in one-handed use. It also keeps the navigation controls for your site close to the control UI provided by most mobile browsers (bottom of the web view).
Screenshot of mobile menu
Mobile, menu located at viewport bottom

We reposition the menu with CSS, meaning the underlying HTML document remains logically (seminally) ordered for screen readers and document parsers.

Screenshot of desktop menu
The same menu, but on a desktop

Ultimately it’ll be worth considering an additional breakpoint for portrait tablets—one that follows a more traditional burger pattern. Why? Tablets are generally not held in one hand, but the screen remains practically too small for the full extent of a desktop-ish navigation. A combination of burger + shortened desktop menu could work here, but that would require a JavaScript solution based on viewport width (which is less attractive).

  • Leave the brand where it is (top). We don’t want to waste our precious mobile screenspace, so we avoid making it “sticky” or “fixed” or anything else that obscures the content. In this example the brand is fairly large, but we should try to keep it small and out of the way. On visiting a site on a mobile, I want to know what that site is about quickly and without scrolling, so lets promote the content and not waste screen space with branding.
  • Screenshot of expanded menu
    Mobile, menu expanded

    Tiles, not links. Links can be hard to tap on a mobile. We can significantly increase the hitbox for each menu entry by making them tiles. This also provides a lot of opportunity for branding or colourful styling—but not at the expense of a clear, readable label.

  • You don’t have to show everything. I’ve noticed many mobile menus try to show all the things, which may not actually be that useful for different devices. Why not hide the menus we don’t want? In this experiment, we can tag menu elements with menu-item--hide-desktop class to hide (natch) content from the desktop. We could equally do that for mobile.
  • Don’t be afraid to repeat links, sometimes it’s fine. Here, I’ve taken what I think are the three most important menu entries and explicitly called them out as additional ’tiles’ to display along side the mobile navigation button. Quick access for the user, without distraction.

What’s next

This experiment could be taken much further if we start introducing more JavaScript. I’ve also barely touched on accessibility, but this experiment is ‘fairly accessible’. There are additional tricks that I’ll address in some future post. Best tip, fork the demo on CodePen and have a play.

View this experiment on CodePen.

Dev notes

Encountered a strange issue with Safari while building this one. An absolutely positions display:fixed element (the mobile nav, viewport bottom) was not being rendered at all. Chrome and FireFox were displaying the menu perfectly. This was due to Safari ignoring width: 100% on the menu wrapper. Replacing width with left: 0; right: 0 resolved the issue.

This experiment is reliant on flexbox (display: flex) support in your browser. These days that covers most browsers, but if you do need to support older browsers, consider adding a fallback to CSS tables.