How to Dynamically Theme Your Ionic App and Delight Your Users

As developers, we put a lot of thought into choosing the perfect color scheme and visual style for our mobile apps. But ultimately, no single theme will please every user. A dark mode that looks sleek to one person might strain the eyes of another. The colorful, playful palette you love could feel gaudy and unprofessional to someone else.

That‘s why building dynamic theme support into your Ionic app is a great way to make users happy. By allowing folks to choose from a set of carefully designed themes – or even create their own – you give them the ability to tailor the app experience to their personal tastes and needs.

Popular apps like Twitter, Slack, and Todoist have all embraced user-selectable themes. Now let‘s look at how you can implement this powerful feature in your own Ionic apps!

The Benefits of Dynamic App Themes

Before we dive into the technical details, it‘s worth taking a moment to appreciate how dynamic themes can improve the user experience of your app. The key benefits include:

Personalization: Letting users choose their theme provides a sense of ownership and investment in the app. It shows that you care about crafting an experience that feels personal to them.

Accessibility: Enabling high-contrast themes and text size adjustment can make your app more comfortable for visually impaired users and those with other accessibility needs. There‘s not always a one-size-fits-all solution.

Context Adaptation: Users may prefer different themes based on their current context and needs. For example, someone might enjoy your app‘s default bright theme during the day but switch to a darker, more subdued palette at night to avoid eye strain.

Novelty and Freshness: Regularly releasing new theme options, such as seasonal color palettes and tie-ins with cultural events, can help keep your app feeling fresh and drive repeat engagement.

Now that we‘ve established why dynamic themes are so great, let‘s look at how to actually implement them in an Ionic app! We‘ll start by generating an Ionic starter project.

Generating an Ionic Starter Project

First, make sure you have the latest Ionic CLI installed. Open a terminal and run:

npm install -g @ionic/cli

Next, navigate to the directory where you keep your coding projects and run the following command to generate a blank Ionic starter:

ionic start theming-demo blank --type=angular

Feel free to replace theming-demo with whatever you‘d like to call your project. The –type=angular flag specifies that we want to create an Ionic Angular project, but these theming principles will also work with Ionic React and Vue.

Once the starter project is generated, cd into its directory:

cd theming-demo

Then launch the Ionic development server to preview your new app in the browser:

ionic serve

You should see a basic Ionic starter app running at http://localhost:8100. Now we‘re ready to start implementing dynamic themes!

Creating Theme Files with Sass Variables

Ionic makes it easy to customize your app‘s visual theme using Sass variables. If you open up src/theme/variables.scss in your code editor, you‘ll see a bunch of Sass variables for colors, fonts, padding, and more:

/** Ionic CSS Variables **/
:root {
  /** primary **/
  --ion-color-primary: #3880ff;
  --ion-color-primary-rgb: 56, 128, 255;
  --ion-color-primary-contrast: #ffffff;
  --ion-color-primary-contrast-rgb: 255, 255, 255;
  --ion-color-primary-shade: #3171e0;
  --ion-color-primary-tint: #4c8dff;

  /** secondary **/
  --ion-color-secondary: #3dc2ff;
  --ion-color-secondary-rgb: 61, 194, 255;
  --ion-color-secondary-contrast: #ffffff;
  --ion-color-secondary-contrast-rgb: 255, 255, 255;
  --ion-color-secondary-shade: #36abe0;
  --ion-color-secondary-tint: #50c8ff;

  // ... lots more variables
}

These CSS variables define your app‘s base visual theme. The default Ionic theme is a pleasant blue, but we want to give users some options!

Let‘s define a few alternate color palettes that users can choose between. Add the following code to the bottom of variables.scss:

/*
 * Dark Theme
 * ----------------------------------------------------------------------------
 */

 .dark-theme {
   --ion-color-primary: #428cff;
   --ion-color-primary-rgb: 66,140,255;
   --ion-color-primary-contrast: #ffffff;
   --ion-color-primary-contrast-rgb: 255,255,255;
   --ion-color-primary-shade: #3a7be0;
   --ion-color-primary-tint: #5598ff;

   --ion-color-secondary: #50c8ff;
   --ion-color-secondary-rgb: 80,200,255;
   --ion-color-secondary-contrast: #ffffff;
   --ion-color-secondary-contrast-rgb: 255,255,255;
   --ion-color-secondary-shade: #46b0e0;
   --ion-color-secondary-tint: #62ceff;

  // ... more dark theme variables
}

/*
 * Purple Theme
 * ----------------------------------------------------------------------------
 */

.purple-theme {
  --ion-color-primary: #a855f7;
  --ion-color-primary-rgb: 168,85,247;
  --ion-color-primary-contrast: #ffffff;
  --ion-color-primary-contrast-rgb: 255,255,255;
  --ion-color-primary-shade: #9446d8;
  --ion-color-primary-tint: #b366f8;

  --ion-color-secondary: #c084fc;
  --ion-color-secondary-rgb: 192,132,252;
  --ion-color-secondary-contrast: #000000;
  --ion-color-secondary-contrast-rgb: 0,0,0;
  --ion-color-secondary-shade: #a974de;
  --ion-color-secondary-tint: #c690fc;

 // ... more purple theme variables
}

Here we‘ve defined two custom themes – a "Dark Mode" theme that uses a deeper blue palette, and a bold "Purple" theme. You can define as many themes as you‘d like, each with their own set of color variables targeting different parts of the UI. I recommend using a tool like Ionic‘s Color Generator to help create cohesive palettes.

The key is that each theme definition is wrapped in a CSS class like .dark-theme or .purple-theme. We‘ll use these classes to dynamically apply the currently selected theme to our app. But first, let‘s set up our UI for allowing users to choose a theme.

Building a Theme Selection Interface

For this example, we‘ll add a simple theme selection dropdown in our app‘s Settings page. First generate a new page using the Ionic CLI:

ionic generate page settings

Then open up the newly generated src/app/settings/settings.page.html file and add a dropdown for switching themes:

<ion-header>
  <ion-toolbar>
    <ion-title>Settings</ion-title>
  </ion-toolbar>
</ion-header>

<ion-content>
  <ion-list>
    <ion-item>
      <ion-label>Select Theme</ion-label>
      <ion-select [(ngModel)]="selectedTheme" (ionChange)="changeTheme(selectedTheme)">
        <ion-select-option value="default">Default</ion-select-option>
        <ion-select-option value="dark">Dark</ion-select-option>  
        <ion-select-option value="purple">Purple</ion-select-option>
      </ion-select>
    </ion-item>
  </ion-list>
</ion-content>

This template sets up a simple dropdown menu with options for "Default", "Dark", and "Purple" themes. The [(ngModel)] binding keeps the selectedTheme component variable in sync with the current dropdown value, and the (ionChange) binding triggers a changeTheme() method whenever a new theme is selected.

Now let‘s implement that changeTheme() method to actually apply the selected theme class to our app. Open up src/app/settings/settings.page.ts and add the following code:

import { Component, OnInit } from ‘@angular/core‘;

@Component({
  selector: ‘app-settings‘,
  templateUrl: ‘./settings.page.html‘,
  styleUrls: [‘./settings.page.scss‘],
})
export class SettingsPage implements OnInit {
  selectedTheme: string;

  constructor() { }

  ngOnInit() {
    // TODO: Get selected theme from storage or use default
    this.selectedTheme = ‘default‘;
  }

  changeTheme(theme) {
    document.body.classList.toggle(‘dark-theme‘, theme === ‘dark‘);
    document.body.classList.toggle(‘purple-theme‘, theme === ‘purple‘);
  }

}

In the changeTheme() method, we use the classList.toggle() method to apply the appropriate theme class to the <body> element based on the selected theme value. This will cause our theme CSS variables to take effect app-wide.

We‘ve hardcoded the initial theme to ‘default‘ in the ngOnInit() lifecycle hook for now. But in a real app, you‘d want to load the user‘s previous theme selection from storage (we‘ll touch on this more later).

Believe it or not, we now have a fully working dynamic theme system! Run ionic serve again, navigate to the Settings page, and try switching themes. You should see your app‘s colors change instantly as you select different themes!

Persisting User Theme Preferences

We have one last piece of the puzzle to add: persisting the user‘s selected theme across app restarts. After all, we don‘t want them to have to re-select their preferred theme every time they open the app.

Fortunately, Ionic provides a convenient Storage API for saving simple key-value data like theme preferences. First, let‘s add the Storage package to our project:

npm install @ionic/storage

Then update src/app/settings/settings.page.ts with the following code:

import { Component, OnInit } from ‘@angular/core‘;
import { Storage } from ‘@ionic/storage‘;

@Component({
  selector: ‘app-settings‘,
  templateUrl: ‘./settings.page.html‘,
  styleUrls: [‘./settings.page.scss‘],
})
export class SettingsPage implements OnInit {
  selectedTheme: string;
  private THEME_KEY = ‘selected-theme‘;

  constructor(private storage: Storage) { }

  async ngOnInit() {
    await this.storage.create();
    this.selectedTheme = await this.storage.get(this.THEME_KEY) || ‘default‘;
    this.changeTheme(this.selectedTheme);
  }

  async changeTheme(theme) {
    document.body.classList.toggle(‘dark-theme‘, theme === ‘dark‘);
    document.body.classList.toggle(‘purple-theme‘, theme === ‘purple‘);
    await this.storage.set(this.THEME_KEY, theme);
  }

}

We‘ve imported and injected the Storage service, which we use in the ngOnInit() hook to load any previously saved theme preference (defaulting to ‘default‘ if none is found). We then immediately call changeTheme() to apply that theme.

We‘ve also updated changeTheme() to save the newly selected theme value to storage whenever it‘s called. Now the user‘s theme choice will be remembered even if they close the app!

Advanced Theming Techniques

We‘ve covered the basics of implementing dynamic themes in Ionic, but there‘s much more you can do to take your theming to the next level:

System Preference Syncing: Many users now expect apps to respect their system theme settings, automatically switching to a dark theme at night for example. The Capacitor DarkMode API makes it easy to detect the user‘s system theme and apply the appropriate theme class.

CSS Custom Properties: You can give users even more control over your app‘s theme by using CSS variables for things like font sizes, padding, and more. Expose controls for adjusting these variables and save the user‘s "custom theme" settings just like we did with the overall theme class.

Themed App Icon & Splash Screen: Take your dynamic themes to the next level by changing your app‘s icon and launch splash screen to match! The Capacitor Splash Screen API makes this surprisingly easy to pull off.

Putting It All Together

Whew, we‘ve covered a lot! Here‘s a quick recap of the steps for adding dynamic theme support to your Ionic apps:

  1. Generate a new Ionic project using the Ionic CLI
  2. Define your custom theme CSS classes with Sass variables in variables.scss
  3. Build a theme selection UI using Ionic components and ngModel
  4. Implement a changeTheme() method to apply the selected theme class to the <body> element
  5. Save the user‘s selected theme preference to @ionic/storage and load it on app start

To dive deeper, check out the complete code for this dynamic theming demo on GitHub. It expands on the concepts covered in this post with more theme options, real-time theme previewing, and more.

I hope this post has shown you how easy and powerful dynamic theming in Ionic can be. The ability to customize your app‘s look and feel is a huge win for user personalization and accessibility. And once you have the basic setup in place, the sky‘s the limit for advanced theming features you can add.

So go forth and let your users choose their own app adventure! If you have any questions or comments, feel free to drop them below. Happy theming!

Similar Posts