A simple and lightweight Leaflet plugin to apply CSS filters on map tiles.
npm install leaflet.tilelayer.colorfilterA simple and lightweight Leaflet plugin to apply CSS color filter on map tiles.
> Important: Breaking Changes in ColorFilter v2.x
> * For existing projects on Leaflet 1.x, you can continue using v1.2.5 (release, readme) of this plugin without any changes.
> * With the release of Leaflet 2.0, this plugin has been updated to v2.x. This version introduces breaking changes to simplify usage and ensure compatibility. For details, please see the Upgrading section.
- Demo with a few presets.
- Make your own filter.
NPM:
```
npm install --save leaflet.tilelayer.colorfilter
Or download a release from the repository.
This plugin can be used with Leaflet 2 and it's legacy versions.
For legacy versions of Leaflet, you need to include the leaflet-tilelayer-colorfilter-global.min.js file after Leaflet.
`html`example/using-leaflet-legacy-1.9.4.html
A complete, working example can be found in , and example/using-leaflet-legacy-0.7.0.html.
For Leaflet 2 using global scripts, include leaflet-tilelayer-colorfilter-global.min.js.
`html`example/using-leaflet-2.0.0-global.html
A complete, working example can be found in .
When using Leaflet 2 as an ES module, you can import the plugin directly.
`html`example/using-leaflet-2.0.0-module.html
A complete, working example can be found in . To run this example, you need to serve it through a local web server. This is because browsers restrict the use of ES modules (import/export) from local file paths for security reasons. A simple way to do this is to run python3 -m http.server in the project's root directory and then navigate to http://localhost:8000/example/using-leaflet-2.0.0-module.html in your browser.
> Technical Note.
> The plugin is designed to be imported for its side effects, which means it modifies Leaflet's TileLayer directly rather than exporting a new class. This is why the import is import 'leaflet-tilelayer-colorfilter';. This design prevents conflicts with other plugins; if this plugin exported its own TileLayer subclass, you couldn't use it with other plugins that do the same. By augmenting the original TileLayer, features from multiple plugins can be used together on the same layer.
After succesfully importing the plugin, TileLayer will have the new option colorFilter inside options parameter.
colorFilter accepts an array of string filters with the following format:
| Filter | Aliases | Description | Example | Default |
| --- | --- | --- | --- | --- |
| Blur | blur | Applies a Gaussian blur filtering measured in pixels | ['blur:2px'] | 0px |['brightness:150%']
| Brightness | brightness, bright, bri | Controls the brightness of tile image | | 100% |['contrast:150%']
| Contrast | contrast, con | Changes the color contrast of tiles | | 100% |['grayscale:100%']
| Grayscale | grayscale, gray | Changes the color of tiles to a grayscale | | 0% |['hue:180deg']
| Hue-Rotate | hue-rotate, hue-rotation, hue | Applies a hue rotation in degrees on tile colors | | 0deg |['opacity:60%']
| Opacity | opacity, op | Defines the opacity of the tiles | | 100% |['invert:100%']
| Invert | invert, inv | Invert the tile colors | | 0% |['saturate:150%']
| Saturate | saturate, saturation, sat | Saturates the tile colors | | 100% |['sepia:0%']
| Sepia | sepia, sep | Converts the tile colors to sepia | | 0% |
For CSS Filter Browser Compatibility please, refer to Browser Compatibility.
On the fly changes on filter is supported with the updateColorFilter function (demo):
`js
let map = L.map('map').setView([51.505, -0.09], 14);
let oldFilter = [
'grayscale:100%',
'invert:100%',
]
let myTileLayer = L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap',
colorFilter: oldFilter,
}).addTo(map);
myTileLayer.updateColorFilter(['brightness:110%', 'hue:90deg', 'saturate:120%']);
`
Useful Tips
The following settings is enough to make most of the light maps to become dark:
`js`
let myFilter = [
'grayscale:100%',
'invert:100%',
]
!dark
To keep water and street colors, a hue rotation around 180deg is very helpful to correct the color inversion:
`js`
let myFilter = [
'hue:180deg',
'invert:100%',
]
!dark-colorized
Light maps may also look good:
`js`
let myFilter = [
'brightness:110%',
'hue:90deg',
'saturate:120%',
]
!colorized
The filter order matters:
`js
let leftColoFilter = [
'invert:100%',
'brightness:115%',
'hue:186deg',
]
let rightColorFilter = [
'hue:186deg',
'brightness:115%',
'invert:100%',
]
`
!filterorder
If you are using Leaflet 1.x, you can either continue using v1.2.5 of this plugin without any changes (see the v1.2.5) or upgrade to v2.x by following the steps below. To use Leaflet 2, you must use v2.x of this plugin.
When upgrading this plugin to v2.x, you will need to:
- Update the imports according to the Leaflet version you are using.
- For Leaflet 2 in Global Script mode (or Leaflet 1.x and older), use leaflet-tilelayer-colorfilter-global.min.js.leaflet-tilelayer-colorfilter.min.js
- For Leaflet 2 in Module mode, use .
- Update your code to use the new syntax. For the correct syntax, refer to the example that matches your Leaflet version: Leaflet 1.x and older, Leaflet 2.x Global, or Leaflet 2.x Module. In summary:
- The plugin now extends TileLayer directly.filter
- The option has been renamed to colorFilter.updateFilter()
- The method has been renamed to updateColorFilter()`.
For a full list of changes, see the CHANGELOG.md.
This project is licensed under the MIT License. (c) 2018-2025, Cláudio T. Kawakani.