Using the Web Storage API

The Web Storage API provides mechanisms by which browsers can securely store key/value pairs, in a much more intuitive fashion than using cookies. This article provides a walkthrough of how to make use of this simple technology.

Basic concepts

Storage objects are simple key-value stores, similar to objects, but they stay intact through page loads.  The keys and the values are always strings (note that integer keys will be automatically converted to strings, just like what object do). You can access these values like an object, or with the getItem() and setItem() methods.  These three lines all set the colorSetting entry in the same way:

JavaScript
localStorage.colorSetting = '#a4509b';
localStorage['colorSetting'] = '#a4509b';
localStorage.setItem('colorSetting', '#a4509b');

The two mechanisms within Web Storage are as follows:

  • sessionStorage maintains a separate storage area for each given origin that's available for the duration of the page session (as long as the browser is open, including page reloads and restores).
  • localStorage does the same thing, but persists even when the browser is closed and reopened.

These mechanisms are available via the Window.sessionStorage and Window.localStorage properties (to be more precise, in supporting browsers the Window object implements the WindowLocalStorage and WindowSessionStorage objects, which the localStorage and sessionStorage properties hang off) — invoking one of these will create an instance of the Storage object, through which data items can be set, retrieved, and removed. A different Storage object is used for the sessionStorage and localStorage for each origin — they function and are controlled separately.

So, for example, initially calling localStorage on a document will return a Storage object; calling sessionStorage on a document will return a different Storage object. Both of these can be manipulated in the same way, but separately.

Feature-detecting localStorage

To be able to use localStorage, we should first verify that it is supported and available in the current browsing session.

Testing for support vs availability

Browsers that support localStorage will have a property on the window object named localStorage. However, for various reasons, just asserting that property exists may throw exceptions. If it does exist, that is still no guarantee that localStorage is actually available, as various browsers offer settings that disable localStorage. So a browser may support localStorage, but not make it available to the scripts on the page. One example of that is Safari, which in Private Browsing mode gives us an empty localStorage object with a quota of zero, effectively making it unusable. Our feature detect should take these scenarios into account. 

Here is a function that detects whether localStorage is both supported and available:

JavaScript
function storageAvailable(type) {
	try {
		var storage = window[type],
			x = '__storage_test__';
		storage.setItem(x, x);
		storage.removeItem(x);
		return true;
	}
	catch(e) {
		return false;
	}
}

And here is how you would use it:

JavaScript
if (storageAvailable('localStorage')) {
	// Yippee! We can use localStorage awesomeness
}
else {
	// Too bad, no localStorage for us
}

You can test for sessionStorage instead by calling storageAvailable('sessionStorage')

See here for a brief history of feature-detecting localStorage.

A simple example

To illustrate some typical web storage usage, we have created a simple example, imaginatively called Web Storage Demo. The landing page provides controls that can be used to customize the color, font, and decorative image:

When you choose different options, the page is instantly updated; in addition, your choices are stored in localStorage,  so that when you leave the page and load it again later on, your choices are remembered.

We have also provided an event output page — if you load this page in another tab, then make changes to your choices in the landing page, you'll see the updated storage information outputted as a StorageEvent is fired.

Note: As well as viewing the example pages live using the above links, you can also check out the source code.

Testing whether your storage has been populated

To start with on main.js, we will test whether the storage object has already been populated (i.e., the page was previously accessed):

JavaScript
if(!localStorage.getItem('bgcolor')) {
  populateStorage();
} else {
  setStyles();
}

The Storage.getItem() method is used to get a data item from storage; in this case we are testing to see whether the bgcolor item exists; if not, we run populateStorage() to add the existing customization values to the storage. If there are already values there, we run setStyles() to update the page styling with the stored values.

Note: You could also use Storage.length to test whether the storage object is empty or not.

Getting values from storage

As noted above, values can be retrieved from storage using Storage.getItem(). This takes the key of the data item as an argument, and returns the data value. For example:

JavaScript
function setStyles() {
  var currentColor = localStorage.getItem('bgcolor');
  var currentFont = localStorage.getItem('font');
  var currentImage = localStorage.getItem('image');

  document.getElementById('bgcolor').value = currentColor;
  document.getElementById('font').value = currentFont;
  document.getElementById('image').value = currentImage;

  htmlElem.style.backgroundColor = '#' + currentColor;
  pElem.style.fontFamily = currentFont;
  imgElem.setAttribute('src', currentImage);
}

Here, the first three lines grab the values from local storage. Next, we set the values displayed in the form elements to those values, so that they keep in sync when you reload the page. Finally, we update the styles/decorative image on the page, so your customization options come up again on reload.

Setting values in storage

Storage.setItem() is used both to create new data items, and (if the data item already exists) update existing values. This takes two arguments — the key of the data item to create/modify, and the value to store in it.

JavaScript
function populateStorage() {
  localStorage.setItem('bgcolor', document.getElementById('bgcolor').value);
  localStorage.setItem('font', document.getElementById('font').value);
  localStorage.setItem('image', document.getElementById('image').value);

  setStyles();
}

The populateStorage() function sets three items in local storage — the background color, font, and image path. It then runs the setStyles() function to update the page styles, etc.

We've also included an onchange handler on each form element, so that the data and styling is updated whenever a form value is changed:

JavaScript
bgcolorForm.onchange = populateStorage;
fontForm.onchange = populateStorage;
imageForm.onchange = populateStorage;

Responding to storage changes with the StorageEvent

The StorageEvent is fired whenever a change is made to the Storage object. This won't work on the same page that is making the changes — it is really a way for other pages on the domain using the storage to sync any changes that are made. Pages on other domains can't access the same storage objects.

On the events page (see events.js) the only JavaScript is as follows:

JavaScript
window.addEventListener('storage', function(e) {  
  document.querySelector('.my-key').textContent = e.key;
  document.querySelector('.my-old').textContent = e.oldValue;
  document.querySelector('.my-new').textContent = e.newValue;
  document.querySelector('.my-url').textContent = e.url;
  document.querySelector('.my-storage').textContent = e.storageArea;
});

Here we add an event listener to the window object that fires when the Storage object associated with the current origin is changed. As you can see above, the event object associated with this event has a number of properties containing useful information — the key of the data that changed, the old value before the change, the new value after that change, the URL of the document that changed the storage, and the storage object itself.

Deleting data records

Web Storage also provides a couple of simple methods to remove data. We don't use these in our demo, but they are very simple to add to your project:

  • Storage.removeItem() takes a single argument — the key of the data item you want to remove — and removes it from the storage object for that domain.
  • Storage.clear() takes no arguments, and simply empties the entire storage object for that domain.

Specifications

Specification Status Comment
Web Storage (Second edition) Recommendation  

Browser compatibility

Feature Chrome Firefox (Gecko) Internet Explorer Opera Safari (WebKit)
localStorage 4 3.5 8 10.50 4
sessionStorage 5 2 8 10.50 4
Feature Android Firefox Mobile (Gecko) IE Phone Opera Mobile Safari Mobile
Basic support 2.1 ? 8 11 iOS 3.2

All browsers have varying capacity levels for both localStorage and sessionStorage. Here is a detailed rundown of all the storage capacities for various browsers.

Note: since iOS 5.1, Safari Mobile stores localStorage data in the cache folder, which is subject to occasional clean up, at the behest of the OS, typically if space is short.

See also

License

© 2016 Mozilla Contributors
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-us/docs/web/api/web_storage_api/using_the_web_storage_api

API Guide localStorage sessionStorage Storage storage Web Storage API