Skip to main content
Version: v8

Advanced Theming

CSS-based theming enables apps to customize the colors quickly by loading a CSS file or changing a few CSS property values.

theme-color Meta

The theme-color value for a meta tag indicates a color that browsers can use to customize the display of a page or of the surrounding interface. This kind of meta tag can also accept media queries which allow developers to set the theme color for both light and dark modes.

The content value for the theme-color meta must contain a valid CSS Color and cannot contain CSS Variables.

note

The theme-color meta controls the interface theme when running in a web browser or as a PWA and has no effect when an app is deployed using Capacitor or Cordova. If you are looking to customize the area under the status bar, we recommend using the Capacitor Status Bar Plugin.

The example below demonstrates how to use theme-color to style the browser interface on iOS 15.

<meta name="theme-color" media="(prefers-color-scheme: light)" content="#0054e9" />
<meta name="theme-color" media="(prefers-color-scheme: dark)" content="#eb445a" />
Light ModeDark Mode
The light mode theme color in a browser interface.The dark mode theme color in a browser interface.

The theme-color meta can also be used to customize the toolbar in Safari on macOS Monterey or newer.

Safari on iOS 15 and macOS will automatically determine an appropriate theme color to use, but adding this meta tag is useful if you need more control over the theme.

There is a small subset of colors that browsers will not use as they interfere with the browser interface. For example, setting content="red" will not work in Safari on macOS because that color interferes with the red close button in the toolbar. If you run into this situation, try altering your color selection slightly.

note

Browsers will prefer the theme-color meta over theme in manifest.json if both are present.

For more information, see the MDN theme-color documentation.

Global Variables

While the application and stepped variables in the themes section are useful for changing the colors of an application, often times there is a need for variables that are used in multiple components. The following variables are shared across components to change global padding settings and more.

Application Variables

NameDescription
--ion-font-familyFont family of the app
--ion-statusbar-paddingStatusbar padding top of the app
--ion-safe-area-topAdjust the safe area inset top of the app
--ion-safe-area-rightAdjust the safe area inset right of the app
--ion-safe-area-bottomAdjust the safe area inset bottom of the app
--ion-safe-area-leftAdjust the safe area inset left of the app
--ion-marginAdjust the margin of the Margin attributes
--ion-paddingAdjust the padding of the Padding attributes
--ion-placeholder-opacityAdjust the opacity of the placeholders used in the input, textarea, searchbar, and select components

Grid Variables

NameDescription
--ion-grid-columnsNumber of columns in the grid
--ion-grid-padding-xsPadding of the grid for xs breakpoints
--ion-grid-padding-smPadding of the grid for sm breakpoints
--ion-grid-padding-mdPadding of the grid for md breakpoints
--ion-grid-padding-lgPadding of the grid for lg breakpoints
--ion-grid-padding-xlPadding of the grid for xl breakpoints
--ion-grid-column-padding-xsPadding of the grid columns for xs breakpoints
--ion-grid-column-padding-smPadding of the grid columns for sm breakpoints
--ion-grid-column-padding-mdPadding of the grid columns for md breakpoints
--ion-grid-column-padding-lgPadding of the grid columns for lg breakpoints
--ion-grid-column-padding-xlPadding of the grid columns for xl breakpoints

Known Limitations with Variables

The Alpha Problem

There is not yet full browser support for alpha use of a hex color. The rgba() function only accepts a value in R, G, B, A (Red, Green, Blue, Alpha) format. The following code shows examples of correct and incorrect values passed to rgba().

/* These examples use the same color: blueviolet. */
.broken {
--violet: #8a2be2;

/* rgba(#8a2be2, .5) */
color: rgba(var(--violet), 0.5); /* ERROR! Doesn't support hex. */
}

.working {
--violet-rgb: 138, 43, 226;

/* rgba(138, 43, 226, .5) */
color: rgba(var(--violet-rgb), 0.5); /* WORKS! */
}
note

See the CSS Variables section for more information on how to get and set CSS variables.

Ionic uses colors with an opacity (alpha) in several components. In order for this to work, those properties must be provided in RGB format. When changing any of the properties that have a variation ending in -rgb, it is important they are also provided in a comma separated format without parentheses. Below are some examples for changing text and background color.

:root {
/* These examples use the same color: sienna. */
--ion-text-color: #a0522d;
--ion-text-color-rgb: 160, 82, 45;

/* These examples use the same color: lightsteelblue. */
--ion-background-color: #b0c4de;
--ion-background-color-rgb: 176, 196, 222;
}

Note that the RGB formatted colors are the exact same color as the hex properties, but can now be used with rgba(). For example, --ion-text-color-rgb can now be used in the following way

body {
color: rgba(var(--ion-text-color-rgb), 0.25);
}

Variables in Media Queries

CSS variables in media queries are not currently supported, but there are open drafts to add custom media queries and custom environment variables that would solve this problem! However, with the current state of support, the following will not work:

:root {
--breakpoint: 600px;
}

@media (min-width: var(--breakpoint)) {
/* Doesn't work :( */
}

Modifying CSS Color Variables

While it is possible to easily alter a color in Sass using its built-in functions, it is currently not as easy to modify colors set in CSS Variables. This can be accomplished in CSS by splitting the RGB or HSL channels and modifying each value, but it is complex and has missing functionality.

What exactly does this mean? Basically, using a CSS preprocessor, such as Sass, allows us to use functions to manipulate a single color. For example, we can create the following colors in Sass:

// Background color, shade, and tint
$background: #0054e9;
$background-shade: mix(#000, $background, 12%);
$background-tint: mix(#fff, $background, 10%);

// Text color, darker and lighter
$text: #444;
$text-darker: darken($text, 15);
$text-lighter: lighten($text, 15);

After running through the Sass compiler, the colors will have the following values:

VariableValue
$background#0054e9
$background-shade#004acd
$background-tint#1a65eb
$text#444444
$text-darker#1e1e1e
$text-lighter#6a6a6a

However, because CSS variables can be set at runtime and are more dynamic, it is not currently possible to manipulate them using a simple function.

This is normally not a problem, but when an application needs to have dynamic theming it presents issues. In Ionic, this is the reason that there are variations to each color, and it is also why stepped colors are necessary for theming.

There are drafts and issues discussing color modification proposals that would make this possible.

Safe Area Padding

The safe area of a display is the section that is not covered by the device's notch, status bar, or other elements that are part of the device's UI and not the app's. The dimensions of the safe area are different across devices and orientations (portrait or landscape).

For example, below are screenshots of an iPhone 14 Pro Max. The red section is the safe area, and the white sections are places where the app's content would be covered up.

PortraitLandscape

To accommodate this, Ionic automatically adds padding to certain components. For example, the first ion-toolbar component placed in an ion-modal will receive padding according to the top edge of the device's safe area. This avoids the device's notch covering up the header text.

This padding can be manually adjusted through CSS using the --ion-safe-area-(dir) variables described in Application Variables. Values can be set for the whole application, or on a per component basis. For example:

html {
--ion-safe-area-left: 25px;
}

ion-modal {
--ion-safe-area-top: 0;
}