Change the color of a webpage dynamically using JS and CSS

By

Learn how to change a web page colors on the fly with JavaScript and the CSS filter property, switching between pastel, grayscale, and normal modes.

~~~

You can change the colors of an entire web page at runtime by setting the CSS filter property on the html element with JavaScript. One line of JS is enough to make the whole page grayscale, or to soften its colors into a pastel look.

The filter property applies visual effects like grayscale(), saturate(), brightness() and blur() to an element and everything inside it. Apply it to the root element, and the whole page changes.

Here’s a set of links that switch between three modes:

<a href='javascript:document.querySelector("html").setAttribute("style","filter: saturate(60%) brightness(80%);")'>
  pastel
</a>

<a href='javascript:document.querySelector("html").setAttribute("style","filter: grayscale(100%); ")'>
  grayscale
</a>

<a href='javascript:document.querySelector("html").setAttribute("style","filter:  ")'>
  normal
</a>

Each link uses a javascript: URL, so clicking it runs the code instead of navigating. The code selects the html element and sets its style attribute.

The pastel mode combines two filters. saturate(60%) reduces how vivid the colors are, and brightness(80%) darkens the page a bit. grayscale(100%) removes color entirely. The last link sets an empty filter, which restores the page to normal.

You can do the same from a regular click handler, which is cleaner than inline javascript: URLs:

document.querySelector('#grayscale').addEventListener('click', () => {
  document.querySelector('html').style.filter = 'grayscale(100%)'
})

Setting style.filter only touches the filter, while setAttribute('style', ...) replaces the entire inline style. If your page already has inline styles on the html element, setAttribute() wipes them out. Use style.filter in that case.

When is this useful?

I’ve used this trick to preview how a design reads without color, which is a quick accessibility check. It’s also a fast way to build a “reading mode” or a low-stimulation theme without touching every color in your stylesheet.

One thing to watch out for

Be careful with position: fixed elements. When an element has a filter applied, it becomes the containing block for its fixed-position descendants. A navbar that used to stick to the viewport now sticks to the filtered element instead.

If that happens, apply the filter to a wrapper div that contains your content but not the fixed elements, instead of applying it to html.

~~~

Related posts about js: