Skip to main content

Style JSON

You can provide a custom style using a JSON object or file:
import React, { useState } from 'react';
import { Text } from 'react-native';
import { MapView, Camera, Style, StyleURL } from '@rnmapbox/maps';
import StyleJsonExample from './assets/style-json-example.json';
import StyleJsonExample2 from './assets/style-json-example2.json';

const StyleJson = () => {
  const [showAltStyle, setShowAltStyle] = useState(false);

  return (
    <>
      <MapView styleURL={StyleURL.Light} style={{ flex: 1 }}>
        <Camera 
          defaultSettings={{
            centerCoordinate: [-78.54382, 40.446947],
            zoomLevel: 3,
            minZoomLevel: 3,
          }} 
        />
        <Style
          json={showAltStyle ? StyleJsonExample2 : StyleJsonExample}
        />
      </MapView>
      <button onClick={() => setShowAltStyle(!showAltStyle)}>
        <Text>{showAltStyle ? 'Style 2' : 'Style 1'}</Text>
      </button>
    </>
  );
};

export default StyleJson;
The Style component allows you to override the base style URL with custom JSON. You can switch between different styles dynamically.

Modify Existing Layers

Change the color of an existing layer in the base style:
import React, { useState } from 'react';
import { Text } from 'react-native';
import { MapView, FillLayer, Camera } from '@rnmapbox/maps';

const ChangeLayerColor = () => {
  const [fillColor, setFillColor] = useState('');

  const onPress = () => {
    const randomColor = `#${Math.random().toString(16).substr(-6)}`;
    setFillColor(randomColor);
  };

  return (
    <>
      <MapView
        onPress={onPress}
        style={{ flex: 1 }}
      >
        <Camera 
          defaultSettings={{
            centerCoordinate: [12.338, 45.4385],
            zoomLevel: 17.4,
          }} 
        />
        {fillColor && (
          <FillLayer 
            id="water" 
            existing 
            style={{ fillColor }} 
          />
        )}
      </MapView>
      <button onClick={onPress}>
        <Text>Paint Water</Text>
      </button>
    </>
  );
};

export default ChangeLayerColor;
Use the existing prop to modify layers that are already part of the base style. The id must match the layer ID in the style.

Custom GeoJSON Layer

Add custom shapes using GeoJSON:
import React from 'react';
import {
  MapView,
  Camera,
  ShapeSource,
  FillLayer,
  VectorSource,
  BackgroundLayer,
  StyleURL,
} from '@rnmapbox/maps';
import gridPattern from './assets/grid_pattern.png';
import smileyFaceGeoJSON from './assets/smiley_face.json';

const layerStyles = {
  background: {
    backgroundPattern: gridPattern,
  },
  smileyFace: {
    fillAntialias: true,
    fillColor: 'white',
    fillOutlineColor: 'rgba(255, 255, 255, 0.84)',
  },
};

const GeoJSONSource = () => {
  return (
    <MapView style={{ flex: 1 }} styleURL={StyleURL.Dark}>
      <Camera 
        zoomLevel={2} 
        centerCoordinate={[-35.15165038, 40.6235728]} 
      />

      <VectorSource>
        <BackgroundLayer 
          id="background" 
          style={layerStyles.background} 
        />
      </VectorSource>

      <ShapeSource id="smileyFaceSource" shape={smileyFaceGeoJSON}>
        <FillLayer id="smileyFaceFill" style={layerStyles.smileyFace} />
      </ShapeSource>
    </MapView>
  );
};

export default GeoJSONSource;

Gradient Line

Create a line with gradient colors:
import React from 'react';
import { MapView, Camera, ShapeSource, LineLayer } from '@rnmapbox/maps';

const lineString = {
  type: 'Feature',
  geometry: {
    type: 'LineString',
    coordinates: [
      [-77.044211, 38.852924],
      [-77.045659, 38.860158],
      [-77.044232, 38.862326],
      [-77.040879, 38.865454],
      [-77.039936, 38.867698],
      [-77.040338, 38.86943],
      [-77.04264, 38.872528],
      [-77.03696, 38.878424],
      [-77.032309, 38.87937],
      [-77.030056, 38.880945],
      [-77.027645, 38.881779],
      [-77.026946, 38.882645],
      [-77.026942, 38.885502],
      [-77.028054, 38.887449],
      [-77.02806, 38.892088],
      [-77.03364, 38.892108],
      [-77.033643, 38.899926],
    ],
  },
};

const GradientLine = () => {
  return (
    <MapView style={{ flex: 1 }}>
      <Camera
        defaultSettings={{
          centerCoordinate: [-77.035, 38.875],
          zoomLevel: 12,
        }}
      />
      <ShapeSource 
        id="line-source" 
        lineMetrics={true} 
        shape={lineString}
      >
        <LineLayer
          id="line-layer"
          style={{
            lineColor: 'red',
            lineCap: 'round',
            lineJoin: 'round',
            lineWidth: 14,
            lineGradient: [
              'interpolate',
              ['linear'],
              ['line-progress'],
              0, 'blue',
              0.1, 'royalblue',
              0.3, 'cyan',
              0.5, 'lime',
              0.7, 'yellow',
              1, 'red',
            ],
          }}
        />
      </ShapeSource>
    </MapView>
  );
};

export default GradientLine;
To use lineGradient, you must set lineMetrics={true} on the ShapeSource.

Data-Driven Styling

Use expressions to style features based on their properties:
import React from 'react';
import Mapbox from '@rnmapbox/maps';

const styles = {
  circles: {
    circleRadius: [
      'interpolate',
      ['exponential', 1.75],
      ['zoom'],
      12, 2,
      22, 180,
    ],
    circleColor: [
      'match',
      ['get', 'ethnicity'],
      'White', '#fbb03b',
      'Black', '#223b53',
      'Hispanic', '#e55e5e',
      'Asian', '#3bb2d0',
      /* other */ '#ccc',
    ],
  },
};

const DataDrivenCircleColors = () => {
  return (
    <Mapbox.MapView
      styleURL={Mapbox.StyleURL.Light}
      style={{ flex: 1 }}
    >
      <Mapbox.Camera
        defaultSettings={{
          centerCoordinate: [-122.400021, 37.789085],
          pitch: 45,
          zoomLevel: 10,
        }}
      />

      <Mapbox.VectorSource
        id="population"
        url="mapbox://examples.8fgz4egr"
      >
        <Mapbox.CircleLayer
          id="sf2010CircleFill"
          sourceLayerID="sf2010"
          style={styles.circles}
        />
      </Mapbox.VectorSource>
    </Mapbox.MapView>
  );
};

export default DataDrivenCircleColors;

Mapbox Expressions

Mapbox expressions provide powerful data-driven styling:
// Interpolate circle radius based on zoom level
circleRadius: [
  'interpolate',
  ['linear'],
  ['zoom'],
  10, 5,   // at zoom 10, radius is 5
  15, 15,  // at zoom 15, radius is 15
  20, 30   // at zoom 20, radius is 30
]

Layer Types

Mapbox supports various layer types:
LayerUse CaseExample
FillLayerFilled polygonsCountries, buildings, parks
LineLayerLines and strokesRoads, boundaries, routes
CircleLayerCircular pointsMarkers, data points
SymbolLayerIcons and textPOI markers, labels
HeatmapLayerDensity visualizationPopulation density, activity heat
FillExtrusionLayer3D buildingsBuilding heights, terrain
RasterLayerRaster tilesSatellite imagery, weather data
BackgroundLayerMap backgroundBase color or pattern

Common Style Properties

<FillLayer
  id="myFill"
  style={{
    fillColor: '#ff0000',
    fillOpacity: 0.5,
    fillOutlineColor: '#000000',
  }}
/>

Tips

Use slot property to control layer rendering order. Available slots: 'bottom', 'middle', 'top'.
Mapbox expressions are evaluated on the GPU, making them extremely performant even with large datasets.

Source Code

View the complete examples on GitHub:

Next Steps

Markers & Annotations

Add interactive markers to your map

Data Visualization

Visualize complex datasets

Build docs developers (and LLMs) love