A screen is built in layers. The page sits at the back, content sits on it, and a few things stand above that. Each layer has its own surface token, so neighbouring layers always contrast, in both themes.
The three levels
| Level | Token | Use it for |
|---|---|---|
| Base | --color-background-surface-neutral-base | Page backgrounds that group content, such as settings, search pages and overviews |
| Default | --color-background-surface-neutral-default | Content-first views, forms, flows, modals and bottom sheets |
| Elevated | --color-background-surface-neutral-elevated | Cards, navigation tiles and other things that need to stand out |
Base
neutral-base is the background for a page whose content is grouped visually, like utilities. Use it when the page is made of separate blocks, not one continuous piece of content.
- Settings, for example notification settings
- Search pages
- Overviews
- Navigation
Nesting: default components or pages can be nested inside a base screen background. Content then sits on the base surface in default or elevated containers.
Default
neutral-default is for default views, where the page is content first.
- Articles and blogs
- Forms and flows
- Anything for reading, including rich text
- Interactive elements
- Modals, sidebar menus and bottom sheets
- Primary containers and focused flows
Modals, sidebar menus and bottom sheets always use default, whatever surface is behind them.
Elevated
neutral-elevated is for components that need to stand out from the default background. Use it sparingly. If everything is elevated, nothing stands out.
Avoid elevated backgrounds for large surfaces or full pages. They are reserved for components.
- Cards
- Navigation tiles
- Elevated UI sections
Always pair an elevated surface with a border token, and add a shadow if it needs more lift. In light mode the elevated and default surfaces are the same colour, so the border or shadow is what separates the two layers. Use a border token such as --color-border-soft (see Using borders). If you add a shadow, keep the border: shadows are barely visible in dark mode, so the border is what keeps the layers apart there.
Choosing a level
- Start with the page. If it is content first, use default. If it groups separate blocks, use base.
- Put ordinary content on the layer above the page: default components or whole pages can sit inside a base screen background.
- Raise a component to elevated only when it has to stand out from what is around it, and give it a border token. Add a shadow only on top of a border, never instead of one.
- Do not step more than one level at a time. An elevated element sits on default or base, never on another elevated element.
In code
Set the level with the emphasis prop on Surface. Card passes it through to its Surface.
// A settings page: base background, default panel, one elevated tile.
// Card brings its own soft border, which is what separates the elevated layer.
<Surface emphasis="base" className="p-6">
<Surface className="rounded-lg p-6">
<Card emphasis="elevated" content="Notification settings" />
</Surface>
</Surface>
default is the default, so a plain <Surface> is the default level. The same props exist on React Native.
Inverse surfaces have elevated and base as well. Brand surfaces do not, and keep their default background for those values. See Surface for the full emphasis table.
Android
On Android the surface tokens arrive as Material 3 colour roles, from checkatradeLightColorScheme() and checkatradeDarkColorScheme() in com.checkatrade.designsystem:tokens. Read them through MaterialTheme.colorScheme.
| Level | Token | Compose role | Use it for |
|---|---|---|---|
| Base | surface-neutral-base | background | The page behind scrollable content: settings, search pages and overviews |
| Default | surface-neutral-default | surface | Content-first screens, modals, sidebar menus and bottom sheets |
| Elevated | surface-neutral-elevated | surfaceBright | Components that need to stand out, such as cards and navigation tiles |
The other neutral tokens map to Material’s container roles: soft to surfaceContainer, strong to surfaceContainerHigh, strongest to surfaceDim, alt to surfaceContainerHighest and pure to surfaceContainerLowest. Use them for the Material components that expect them, not as a substitute for the three levels above. Inverse surfaces map to inverseSurface.
Material’s own sheets, drawers and dialogs default to the container roles, so set their container colour to surface yourself: modals, sidebar menus and bottom sheets always use default. An elevated component still needs a border, and outline is the default border role (see Using borders).
// A settings screen: base page, elevated card with a border
Scaffold(containerColor = MaterialTheme.colorScheme.background) { padding ->
Card(
modifier = Modifier.padding(padding),
colors = CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.surfaceBright),
border = BorderStroke(1.dp, MaterialTheme.colorScheme.outline),
) { /* content */ }
}
// A bottom sheet: always default
ModalBottomSheet(
onDismissRequest = onDismiss,
containerColor = MaterialTheme.colorScheme.surface,
) { /* content */ }
Examples
Two layouts that use the levels together. The callouts name the surface token for each layer and the ink token for the text on it.