Mobile Web Superpowers – Ambient Light API

Patrick Catanzariti

The web has become a virtual environment that brings with it a whole range of experiences. If someone wants to look up the latest discouraging remarks about Ben Affleck’s casting as Batman on their smartphone while discussing the new Batman movie at a picnic. They can read as many comments as their heart desires. We live in an age where, as developers, we can provide the public with resources, knowledge and experiences that compliment their day to day lives and random interests wherever they are. With new devices APIs and sensors, we’re starting to see possibilities that will allow us to respond to their environment, location and device state.

There’s a lot happening in the world of device APIs. For eager developers like myself, there’s an exciting opportunity to start exploring how we can use these upcoming APIs to improve the experience of visitors to our website/web app.

Are they in a dark room where they’d rather not have a bright white background burning their retinas when they access our new “Gotham” TV show fansite?

Are they likely to be struggling at the aforementioned picnic – squinting at our text through the midday sun?

Is their phone battery about to run out, making it likely they’ll not want to play that streaming video background of the Gotham city skyline as they read the latest Batman fan fiction?

With this series of articles, I’ll be covering various APIs like these along with demos and potential uses for each one. Hopefully it’ll shake up some ideas of your own for an upcoming project!

We’ll start with the W3C Ambient Light API which will allow us to respond to the levels of light around a device.

The basics of the Ambient Light API

The Ambient Light API provides developers with a way to sense the light intensity around a device. It measures the light around the device in lux, an international unit of measurement for light intensity. The MDN’s article on Using light sensors provides a good overview of what these lux value ranges represent:

10 ~ 50 lux: Dim Environment

100 ~ 1000 lux: Normal

10000 lux: Bright

I’d recommend for each implementation you do a bit of trial and error with these values. My light level trigger points in the demos below are slightly different.

Browser compatibility

The Ambient Light API is still in its early stages. At the time of writing it is only supported by Firefox 22 on Mac OS X and Firefox for Android. Hopefully further support will come soon, however it is something which can gracefully degrade – if a device or browser doesn’t support the API, then it is ignored and we continue as if it were never there! For those using supported browsers, we give them a nicer experience.

Using these values in JavaScript

To read in the light intensity around your device, add an event listener to the window object that listens in for an event called devicelight. This sample returns our value in lux to the console.log:

window.addEventListener("devicelight", function (event) {
  var luminosity = event.value;
  console.log(luminosity);
});

Which returns this on Firefox for Mac OSX:
Firefox console

What could we use this Ambient Light API for?

Think about the possibilities here, you can enter a whole new realm of responsive design. Rather than just responding to a user’s viewport size and device, you can respond to whether their environment is very bright or very dark and adjust accordingly.

It’s demo time!

To show the potential of this API, we’ll start by building a simple one page website with some text and an svg image. We’ll be able to manipulate how they look by changing the class name on our body tag.

We’ll start with a very basic responsive page, without any Ambient Light API implementation. A short snippet of the page is shown below. For the full starting markup, see this Codepen.

<!DOCTYPE html>
<html>
<head>
  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
  <title>Ambient Light demo - Text changes</title>
  <style type="text/css">
    body {
      font-family: "Trebuchet MS", sans-serif;
      font-size: 16px;
      padding: 0 50px;
    }
    h1 {
      text-align: center;
    }

    @media all and (max-width: 960px) {
      body {
        padding: 0 25px;
      }
      svg {
        clear: both;
        display: block;
        float: none;
        margin: 0 auto;
        width: 80%;
      }
    }
  </style>
</head>
<body>
  <h1>The Gentlemen's Book of Etiquette and Manual of Politeness</h1>
  <svg><!-- our svg element here --></svg>
  <p>Man was not intended to live like a bear or a hermit, apart from others of his own nature, and, philosophy and reason will each agree with me, that man was born for sociability and finds his true delight in society. Society is a word capable...</p>
  ...
</body>
</html>

We’ll bring in our Ambient Light API call by adding JavaScript that reads in our devicelight event and changes the class name of our tag depending on the luminosity value it receives:

<script>
window.addEventListener("devicelight", function (event) {
    var luminosity = event.value;

    if (luminosity <= 5) {
      document.body.className = "darkness";
    } else if (luminosity <= 50) {
      document.body.className = "dim";
    } else if (luminosity <= 1000) {
      document.body.className = "bright";
    } else if (luminosity > 1000) {
      document.body.className = "ahhhmyeyes";
    }
  });
</script>

If it’s really low light, then our device appears to be in almost pitch black darkness (chances are it’s night time or they are in a dark alley about to stop a midnight jewelry store robbery). For these devices, we will color the background dark purple, lighten our text and the color of our SVG image:

.darkness {
  background-color: #2d004f;
  color: #b5aaff;
}
.darkness svg path {
  stroke: #b5aaff;
  fill: #b5aaff;
}

In dark situations where there is a little light around, we’re lightening the background purple a little bit and lightening the text too:

.dim {
  background-color: #6600b4;
  color: #b5aaff;
}
.dim svg path {
  stroke: #c8c3ff;
  fill: #c8c3ff;
}

The color for our average light range will be a relatively calm purple and darker text. I’ve also included the same colors in my body CSS definition for any devices that don’t support the API or for times when the API doesn’t kick in yet. So this will be our default set of styles:

.average {
  background-color: #ab49f6;
  color: #333;
}
.average svg path {
  stroke: #333;
  fill: #333;
}

You could define all these styles in one place by defining the body and the .average styles at the same time. Or you could not set any styles for .average, so that it falls back to the body default styles. It’s a personal preference. On a production site to keep things clean and easy to understand, I’d be tempted to use the last option and not define .average at all. For the example, I’ve defined it so that it’s clear to anyone skimming through these examples.

When it starts to get a bit bright, we turn the background white and set our text and image to be black. We also increase our font size to make it easier to read:

.bright {
  background-color: #fff;
  color: #000;
  font-size: 20px;
}
.bright svg path {
  stroke: #000;
  fill: #000;
}

If we hit light levels that are really bright, we use the same styles as the .bright class but we’ll boost the font size a little bit more:

.ahhhmyeyes {
  background-color: #fff;
  color: #000;
  font-size: 22px;
}
.ahhhmyeyes svg path {
  stroke: #000;
  fill: #000;
}

In action

In action, there were three lighting levels that really stood out when testing this, so I’ve included samples of these below.

Under relatively average lighting (the image below was taken whilst sitting on the train):

Average Lighting

Average Lighting

In very bright conditions outdoors, our page becomes easier to read:

Bright Lighting

Bright Lighting

In very dark conditions, the page becomes darker so we don’t blind our users with bright light:

Dark Lighting

Dark Lighting

Getting the transitioning smooth

To make sure that colors change smoothly and avoid any abrupt style changes, we add in CSS transitions to the body tag’s styles. This could be done in a more efficient way by listing the specific properties you’ll be changing. For simplicity in this example, I’ve stuck with all:

-webkit-transition: all 0.5s ease-in-out;
-moz-transition: all 0.5s ease-in-out;
-o-transition: all 0.5s ease-in-out;
transition: all 0.5s ease-in-out;

Transitions also help make it clear a user hasn’t been moved to a different website. A sudden change from a black and white design to a colored one could easily confuse users. I find CSS transitions ease this confusion a little bit.

Our Ambient Light API empowered page can be seen in action in this Codepen

Subtle YouTube cinema

You know that joyous moment when the cinema lights dim announcing the start of your movie? I thought it would be a fun demo idea to build my own YouTube cinema complete with fancy red curtains. When you turn your own room lights off to watch the video, the cinema dims its own lights too.

Much of our above concepts remain pretty similar for this second demo. Instead of affecting the body element, we instead use a new element called .lights-off which is used as a fixed positioned black cover behind the video.

<div class="lights-off"></div>
<h1>YouTube Cinema</h1>
<div class="youtube-video">
  <iframe width="640" height="360" src="//www.youtube.com/embed/3wyXaAXajhc" frameborder="0" allowfullscreen></iframe>
</div>

It starts out totally transparent so our pretty curtains show through:

.lights-off {
  background-color: #000;
  height: 100%;
  left: 0;
  opacity: 0;
  position: fixed;
  top: 0;
  width: 100%;
  z-index: -1;

  -webkit-transition: opacity 0.5s ease-in-out;
  -moz-transition: opacity 0.5s ease-in-out;
  -o-transition: opacity 0.5s ease-in-out;
  transition: opacity 0.5s ease-in-out;
}

I then apply a class of .darkness which increases our .lights-off element’s opacity to 70%. This has the effect of dimming the lights:

.darkness .lights-off {
  opacity: 0.7;
}

Our JS becomes much shorter too:

window.addEventListener("devicelight", function (event) {
  var luminosity = event.value;

  if (luminosity <= 5) {
    document.body.className = "darkness";
  } else {
    document.body.className = "";
  }
});

What’s this look like?

Our before (lights on) and after (lights off) with both examples showing:
Before and after

You can check out this demo in action right here: http://codepen.io/patrickcatanzariti/pen/uxEkc.

Purple pages? A cinema? Seriously? Why would you even need this?

Real world usage wouldn’t need to be as colorful as my text example. You should aim for subtlety:

  • Rather than switching to dark purple in low light, you could switch the background to a light grey rather than white.
  • You could tone down any bright buttons you have and any font icons or SVG icons could change too.
  • In very bright situations, you could aim to increase contrast between colors. Rather than having a colorful call to action button, change the button to black and white or give the text a darker color and the button a lighter background.

The Internet of Things might just love this

There’s potential for using ideas like this on devices in the realm of the Internet of Things. A few possibilities that float through my mind:

  • Touchscreen controls on walls throughout your home powered by the web that display differently depending on the light levels of the room.
  • A remote control mobile web app for your TV or air conditioner that provides a dark interface when the room is pitch black but a brighter interface when the room is lit up.
  • Video streaming apps like home security systems or teleconferencing systems which automatically increase the contrast and/or brightness of video playback depending on the levels of light in a room.

Conclusion

The Ambient Light API is a small yet effective bit of functionality to add to your arsenal against the growing range of environments our devices are used in today. It provides us with that tiny bit of extra information that can make a huge difference. Hopefully soon the pains of very awkward squinting at your phone in the midday sun will be lessened as our device capabilities evolve to help out.

This is just one of many new device APIs out there, keep an eye out for my next article where I’ll explore yet another API that’ll bring even more new potential to developers.

Got a particular API you’re keen to find out more about? Leave your thoughts in the comments below.

Other resources

For those interested in reading more on the Ambient Light API, here are a few useful links:

Free book: Jump Start HTML5 Basics

Grab a free copy of one our latest ebooks! Packed with hints and tips on HTML5's most powerful new features.

  • http://www.cdnmobilesolutions.com/ Mobile Application Development

    Thanks for sharing this helpful coding and its explanation.