Skip to content

Map

Map Canvas

The map canvas takes up the full viewport. For demo purposes, the container is constrained.

Map Canvas Placeholder

        <div
            id="map"
            style="
                width: 100%;
                height: 400px;
                background: var(--ss-color-surface-muted);
                position: relative;
            "
        >
            <div
                class="ss-c-map_canvas"
                style="width: 100%; height: 100%; position: relative"
            >
                <!-- Map tiles would be rendered here by a mapping library -->
                <div
                    style="
                        display: flex;
                        justify-content: center;
                        align-items: center;
                        height: 100%;
                        color: var(--ss-color-text-muted);
                    "
                >
                    Map Canvas Placeholder
                </div>
            </div>
        </div>
        

Layer Controls

Base Layers


        <!-- Layer controls fill their positioned map container -->
        <div style="position: relative; min-height: 200px">
            <div
                class="ss-c-layer_control_base"
                role="group"
                aria-labelledby="map-base-layers"
                style="
                    padding: 16px;
                    background: var(--ss-color-surface-alt);
                    color: var(--ss-color-text);
                    border-radius: var(--ss-radius-lg);
                    pointer-events: auto;
                "
            >
                <h3 id="map-base-layers">Base Layers</h3>
                <label>
                    <span>
                        <input
                            type="radio"
                            name="base-layer"
                            value="streets"
                            checked
                        />
                        <span>Streets</span>
                    </span>
                </label>
                <label>
                    <span>
                        <input type="radio" name="base-layer" value="satellite" />
                        <span>Satellite</span>
                    </span>
                </label>
                <label>
                    <span>
                        <input type="radio" name="base-layer" value="terrain" />
                        <span>Terrain</span>
                    </span>
                </label>
            </div>
        </div>
        

Overlay Controls

Overlays


        <!-- Layer controls fill their positioned map container -->
        <div style="position: relative; min-height: 200px">
            <div
                class="ss-c-layer_control_overlay"
                role="group"
                aria-labelledby="map-overlays"
                style="
                    padding: 16px;
                    background: var(--ss-color-surface-alt);
                    color: var(--ss-color-text);
                    border-radius: var(--ss-radius-lg);
                    pointer-events: auto;
                "
            >
                <h3 id="map-overlays">Overlays</h3>
                <label>
                    <span>
                        <input type="checkbox" name="overlay" value="traffic" />
                        <span>Traffic</span>
                    </span>
                </label>
                <label>
                    <span>
                        <input type="checkbox" name="overlay" value="transit" />
                        <span>Transit</span>
                    </span>
                </label>
                <label>
                    <span>
                        <input type="checkbox" name="overlay" value="bike" />
                        <span>Bike Lanes</span>
                    </span>
                </label>
            </div>
        </div>
        

Leaflet controls

Inside ss-c-map, Leaflet's zoom bar, layer switcher, attribution, scale, popups and tooltips read the colour, radius, shadow and focus tokens, so they follow the dark theme. Leaflet still positions and sizes them. Load stylescape after leaflet.css. The markup below is what Leaflet 1.9 renders (no tiles in this demo).

Harbour office
Open 8:00–17:00
200 m
Leaflet | © OpenStreetMap contributors
HTML
<div class="ss-c-map">
            <div class="ss-c-map__canvas leaflet-container leaflet-touch" tabindex="0" aria-label="Harbour map (Leaflet)">
                <div class="leaflet-pane leaflet-map-pane">
                    <div class="leaflet-pane leaflet-tooltip-pane">
                        <div class="leaflet-tooltip leaflet-tooltip-top" role="tooltip" style="left: 120px; top: 210px;">Pier 4</div>
                    </div>
                    <div class="leaflet-pane leaflet-popup-pane">
                        <div class="leaflet-popup" style="left: 330px; bottom: -150px;">
                            <div class="leaflet-popup-content-wrapper">
                                <div class="leaflet-popup-content" style="width: 168px;"><strong>Harbour office</strong><br />Open 8:00–17:00</div>
                            </div>
                            <div class="leaflet-popup-tip-container"><div class="leaflet-popup-tip"></div></div>
                            <a class="leaflet-popup-close-button" role="button" aria-label="Close popup" href="#close"><span aria-hidden="true">×</span></a>
                        </div>
                    </div>
                </div>
                <div class="leaflet-control-container">
                    <div class="leaflet-top leaflet-left">
                        <div class="leaflet-control-zoom leaflet-bar leaflet-control">
                            <a class="leaflet-control-zoom-in" href="#" title="Zoom in" role="button" aria-label="Zoom in"><span aria-hidden="true">+</span></a>
                            <a class="leaflet-control-zoom-out leaflet-disabled" href="#" title="Zoom out" role="button" aria-label="Zoom out" aria-disabled="true"><span aria-hidden="true">−</span></a>
                        </div>
                    </div>
                    <div class="leaflet-top leaflet-right">
                        <div class="leaflet-control-layers leaflet-control-layers-expanded leaflet-control">
                            <section class="leaflet-control-layers-list" aria-label="Layers">
                                <div class="leaflet-control-layers-base">
                                    <label><span><input type="radio" class="leaflet-control-layers-selector" name="leaflet-base" checked /><span> Streets</span></span></label>
                                    <label><span><input type="radio" class="leaflet-control-layers-selector" name="leaflet-base" /><span> Aerial</span></span></label>
                                </div>
                                <div class="leaflet-control-layers-separator"></div>
                                <div class="leaflet-control-layers-overlays">
                                    <label><span><input type="checkbox" class="leaflet-control-layers-selector" checked /><span> Moorings</span></span></label>
                                </div>
                            </section>
                        </div>
                    </div>
                    <div class="leaflet-bottom leaflet-left">
                        <div class="leaflet-control-scale leaflet-control"><div class="leaflet-control-scale-line" style="width: 82px;">200 m</div></div>
                    </div>
                    <div class="leaflet-bottom leaflet-right">
                        <div class="leaflet-control-attribution leaflet-control"><a href="https://leafletjs.com">Leaflet</a> | © <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors</div>
                    </div>
                </div>
            </div>
        </div>

MapLibre and Mapbox GL controls

The same for .maplibregl-ctrl* and .mapboxgl-ctrl*: control groups, attribution, scale and popups (every anchor). The libraries draw their control icons as dark images; in dark mode they are inverted through --ss-map-icon-filter.

Ferry terminal
Next departure 14:20
100 m
HTML
<div class="ss-c-map">
            <div class="ss-c-map__canvas maplibregl-map" tabindex="0" aria-label="Harbour map (MapLibre)">
                <div class="maplibregl-popup maplibregl-popup-anchor-bottom" style="transform: translate(-50%, -100%) translate(380px, 190px);">
                    <div class="maplibregl-popup-tip"></div>
                    <div class="maplibregl-popup-content">
                        <button class="maplibregl-popup-close-button" type="button" aria-label="Close popup">×</button>
                        <strong>Ferry terminal</strong><br />Next departure 14:20
                    </div>
                </div>
                <div class="maplibregl-control-container">
                    <div class="maplibregl-ctrl-top-right">
                        <div class="maplibregl-ctrl maplibregl-ctrl-group">
                            <button class="maplibregl-ctrl-zoom-in" type="button" title="Zoom in" aria-label="Zoom in"><span class="maplibregl-ctrl-icon" aria-hidden="true"></span></button>
                            <button class="maplibregl-ctrl-zoom-out" type="button" title="Zoom out" aria-label="Zoom out"><span class="maplibregl-ctrl-icon" aria-hidden="true"></span></button>
                            <button class="maplibregl-ctrl-compass" type="button" title="Reset bearing to north" aria-label="Reset bearing to north"><span class="maplibregl-ctrl-icon" aria-hidden="true"></span></button>
                        </div>
                    </div>
                    <div class="maplibregl-ctrl-bottom-left">
                        <div class="maplibregl-ctrl maplibregl-ctrl-scale" style="width: 74px;">100 m</div>
                    </div>
                    <div class="maplibregl-ctrl-bottom-right">
                        <div class="maplibregl-ctrl maplibregl-ctrl-attrib">
                            <div class="maplibregl-ctrl-attrib-inner"><a href="https://maplibre.org/">MapLibre</a> | © <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a></div>
                        </div>
                    </div>
                </div>
            </div>
        </div>

Other map libraries

ss-c-map themes the chrome of Leaflet, MapLibre GL and Mapbox GL only. OpenLayers, Google Maps and ArcGIS draw their own controls and keep their own look; they are not themed on purpose, because each ships its own stylesheet and class structure. The frame, canvas and ss-c-map__control overlay work with any library. To theme another library's controls, scope a few rules under .ss-c-map with the same tokens, for example for OpenLayers:

CSS
.ss-c-map .ol-control button {
            background-color: var(--ss-color-surface);
            color: var(--ss-color-text);
            border-radius: 0;
        }
        .ss-c-map .ol-control button:hover {
            background-color: var(--ss-color-surface-hover);
        }
        .ss-c-map .ol-attribution {
            background-color: var(--ss-color-surface);
            color: var(--ss-color-text);
        }