Skip to content
Change the Case of Labels

Change the Case of Labels in Maptoolkit Maps JS

The text-transform layout property on symbol layers controls whether labels appear in uppercase, lowercase, or their original mixed case. You can apply it to all symbol layers at once by iterating over the style layers and updating the property on each one. Use this to match a brand’s typographic style, reduce visual noise in dense label areas, or implement a toggle that lets users switch label casing.

const API_KEY = 'YOUR_API_KEY';

    const map = new maptoolkit.Map({
        container: 'map',
        apiKey: API_KEY,
        style: `https://styles.maptoolkit.net/maptoolkit/maptoolkit.summer.json?api_key=${API_KEY}`,
        center: [11.39085, 47.27574],
        zoom: 10,
        attributionControl: { compact: false }
    });

    function setCase(textTransform) {
        if (!map.isStyleLoaded()) return;
        const layers = map.getStyle().layers;
        for (const layer of layers) {
            if (layer.type === 'symbol' && layer.layout && layer.layout['text-field']) {
                map.setLayoutProperty(layer.id, 'text-transform', textTransform === 'none' ? undefined : textTransform);
            }
        }
    }
<!DOCTYPE html>
<html lang="en">
<head>
    <title>Change the Case of Labels - Maptoolkit Maps JS</title>
    <meta property="og:description" content="Change text case of map labels using the text-transform layout property." />
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <script src="https://unpkg.com/@maptoolkit/maps@11.0.0-beta.3/dist/maptoolkit.js"></script>
    <link rel="stylesheet" href="https://unpkg.com/@maptoolkit/maps@11.0.0-beta.3/dist/maptoolkit.css" />
    <style>
        html, body { width: 100%; height: 100%; margin: 0; padding: 0; }
        #map { width: 100%; height: 100%; }
        #controls {
            position: absolute;
            top: 10px;
            left: 10px;
            display: flex;
            gap: 6px;
        }
        #controls button {
            padding: 8px 14px;
            background: #3887be;
            color: white;
            border: none;
            border-radius: 3px;
            cursor: pointer;
            font-size: 13px;
        }
        #controls button:hover { background: #2c6d9e; }
    </style>
</head>
<body>
<div id="map"></div>
<div id="controls">
    <button onclick="setCase('none')">Default</button>
    <button onclick="setCase('uppercase')">UPPERCASE</button>
    <button onclick="setCase('lowercase')">lowercase</button>
</div>
<script>
    const API_KEY = 'YOUR_API_KEY';

    const map = new maptoolkit.Map({
        container: 'map',
        apiKey: API_KEY,
        style: `https://styles.maptoolkit.net/maptoolkit/maptoolkit.summer.json?api_key=${API_KEY}`,
        center: [11.39085, 47.27574],
        zoom: 10,
        attributionControl: { compact: false }
    });

    function setCase(textTransform) {
        if (!map.isStyleLoaded()) return;
        const layers = map.getStyle().layers;
        for (const layer of layers) {
            if (layer.type === 'symbol' && layer.layout && layer.layout['text-field']) {
                map.setLayoutProperty(layer.id, 'text-transform', textTransform === 'none' ? undefined : textTransform);
            }
        }
    }
</script>
</body>
</html>

Use the prompt below with any LLM to get the same result. Make sure the Maptoolkit MCP server is connected first — check out AI Integration & MCP to get started.

Use the Maptoolkit Connector. Create an interactive map with zoom level 10, centered around [11.39085, 47.27574]. Add buttons to change map label text case between default, uppercase, and lowercase.

How it works

text-transform is a layout property, not a paint one, and it takes uppercase, lowercase or none. Passing undefined clears the override and restores whatever the style itself specified, which is what “none” does here.

The same per-layer loop as the language example applies it: walk the style’s layers, skip anything that is not a symbol with a text-field, and call setLayoutProperty on the rest. There is no global text setting.

Layout changes are more expensive than paint changes. Case affects glyph widths, so the renderer re-lays out labels and may show or hide different ones as collisions change. That is fine on a button press and wrong in an animation loop.

Uppercase costs horizontal space, so long labels that fitted before may be dropped by collision detection afterwards.

Next steps

Case is a small part of label styling, and the properties around it do more: size, letter spacing, halo colour and width are what make labels readable over a busy map, and a wider halo usually helps more than a case change.

Applying different treatments to different layer groups is the step after, since countries, cities and streets rarely want the same styling, and that is a good moment to consider editing the style itself rather than overriding it at runtime.