Back to Leaflet

Leaflet 2.0 Alpha released

docs/_posts/2025-05-18-leaflet-2.0.0-alpha.md

1.9.48.4 KB
Original Source

After two and a half years of hard work, we’re thrilled to announce the first alpha release of Leaflet 2.0!

This release marks a major modernization of the Leaflet codebase. We've dropped support for Internet Explorer, removed legacy methods and polyfills, adopted modern standards like Pointer Events, and now publish Leaflet as an ESM module. The global L is no longer part of the core package (though it’s still available in the bundled version leaflet-global.js for backward compatibility).


<div class="announcement">August 16, 2025 — The blog has been updated to the alpha.1 release!</div>

What's New in Leaflet 2.0

  • Fully ESM support
  • New renderer superclass: BlanketOverlay
  • Switched from Mouse and Touch events to PointerEvents
  • Point and LatLng now include a .validate() method
  • Automatic OSM attribution if none is provided when using OSM tiles
  • Numerous small cleanups and internal improvements
  • We replaced layers.png with layers.svg for the Control.Layers. Adjust your bundler configuration if necessary.
  • Introduced LeafletMap as an alias for Map.

Migration

  1. Replace all factory methods with constructor calls: L.marker(latlng)new Marker(latlng)
  2. Change the <script> tag to module: <script type='module'>
    • To have global access to variables of a module-script, assign them to the window object (Not recommended): window.map = map
  3. Replace usage of L with explicit imports from the Leaflet package: import { Marker } from 'leaflet'
  4. Consider Leaflet V1 Polyfill if you are using outdated plugins

Old implementation

<script src="https://unpkg.com/[email protected]/dist/leaflet.js"></script>
<script>
	const map = L.map('map').setView([51.505, -0.09], 13);

	const tiles = L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
		maxZoom: 19,
		attribution: '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
	}).addTo(map);
</script>

New implementation

Module

<script type="importmap">
	{
		"imports": {
			"leaflet": "https://unpkg.com/[email protected]/dist/leaflet.js"
		}
	}
</script>
<script type="module">
	import {LeafletMap, TileLayer, Marker, Circle, Polygon, Popup} from 'leaflet';

	const map = new LeafletMap('map').setView([51.505, -0.09], 13);

	const tiles = new TileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
		maxZoom: 19,
		attribution: '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
	}).addTo(map);
</script>

Global Script

<script src="https://unpkg.com/[email protected]/dist/leaflet-global.js"></script>
<script>
	const map = new L.Map('map').setView([51.505, -0.09], 13);

	const tiles = new L.TileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
		maxZoom: 19,
		attribution: '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
	}).addTo(map);
</script>

Major Changes & Cleanups

Modules & Browser Support

  • Dropped UMD and global L in favor of modern ESM
  • Targeting only evergreen browsers
  • Rewritten using standardized ES6 classes
  • Removed legacy SVG.VML renderer
  • ... as well as various other ES6 features

Browser

  • Removed detection flags: ie, ielt9, edge, webkit, android, android23, androidStock, opera, gecko, phantom, opera12, win, ie3d, webkit3d, gecko3d, any3d, mobileWebkit, mobileWebkit3d, msPointer, mobileOpera, mobileGecko, passiveEvents, canvas, svg, vml, inlineSvg, touch, touchNative
  • Flags like L_NO_TOUCH and L_DISABLE_3D are also gone

DomUtil

  • setPosition and getPosition no longer rely on _leaflet_pos
  • Removed: getStyle, testProp, empty, remove, TRANSITION, TRANSITION_END, TRANSFORM, removeClass, setOpacity, addClass, setClass, getClass, hasClass
  • enableTextSelection and disableTextSelection now use standard userSelect style (no vendor prefixes anymore)
  • setTransform drops vendor prefixed style transform too

Util

DomEvent

  • getMousePosition renamed to getPointerPosition
  • disableClickPropagation no longer supports mouse and touch events
  • getPropagationPath polyfill for ev.composedPath() removed
  • getWheelDelta cleaned up from old Firefox/IE quirks
  • DomEvent.Pointer module has been removed
  • Aliases addListener and removeListener have been removed

Map

  • Renamed event mapping methods:
    mouseEventToContainerPoint, mouseEventToLayerPoint, mouseEventToLatLng
    pointerEventToContainerPoint, pointerEventToLayerPoint, pointerEventToLatLng
  • Removed mouse and touch event support (fully replaced by pointer events)
  • Uses ResizeObserver instead of window.onresize
  • Map container has now the aria-keyshortcuts attribute

Layers

  • bubblingMouseEvents renamed to bubblingPointerEvents
  • Prevent outline-box on Chromium when clicking a vector with a tooltip

Class

  • Removed Class.__super__

Draggable & BoxZoom

  • Replaced deprecated button checks:
    (e.which !== 1 && e.button !== 1)(e.button !== 0)
  • Removed old IE-specific correspondingUseElement
  • Fixed tooltip visibility while panning the map

CSS

  • Tiles no longer inherit the filter CSS property

Layers Control

  • Replaced <section> with <fieldset>
  • Removed aria-haspopup for IE
  • Refocus map after interacting with control
  • New option collapseDelay

PinchZoom

  • Renamed TouchZoom to PinchZoom to better reflect functionality
  • touchZoom alias remains for backward compatibility

Factory Methods

  • All factory methods removed — use constructors directly:
    L.marker(latlng)new Marker(latlng)
  • Point, LatLng, and Bounds constructors no longer return null for invalid inputs
  • Point and LatLng now include .validate() method

Events

  • Removed deprecated layer property — use propagatedFrom instead
  • Cleaned up DOM event listeners when destroying Map’s animation proxy
  • mozEvent warning removed
  • Removed aliases addEventListener, removeEventListener, addOneTimeEventListener, fireEvent, hasEventListeners

Icon.Default

  • Image path auto-detection now only runs if IconDefault.imagePath is unset

Circle

  • Removed support for creating a circle with the radius as second argument L.circle(latlng, radius, options)

GridLayer

  • Now constructs tile URLs with integer {z} even on fractional zoom

Canvas

  • Added support for dashOffset

VideoOverlay

  • New option controls
  • Fixed issue with seek bar in Safari

Want the Full Details?

You can explore all changes included in this release through the following resources:


Need Legacy Support?

Check out this polyfill package to help ease the transition for legacy apps: Leaflet V1 Polyfill


Thanks to everyone who contributed ideas, code, feedback, and testing over the years. This release is a major step forward for Leaflet, and we can’t wait to see what you build with it!

Cheers,
The Leaflet Team