top of page

A Complete Guide: How to add a theme to your Flutter project

  • Writer: Alex Leigh
    Alex Leigh
  • Jan 13
  • 8 min read

Adding a 'theme.dart' file to your Flutter project is powerful way to get full control over the look and feel of your app. From here, you can:

  • Define all the colours used throughout your app

  • Define text themes which include fonts, text sizes and text styles

  • Customise the look and feel of your app bar

  • Add that all-important dark theme

and more!


This tutorial will get you familiar with the 'theme.dart' file, including how to use it, best practices, and how to reference your theme throughout your app.


A note before we start: I am English and unfortunately that means "colour" and "color" have to be used interchangeably! I typically use "color" in my code as required, and then "colour" in my writing and sometimes my code comments. Sorry for the confusion!


Contents


The structure of 'theme.dart'

The below code snippet works for most projects as a 'theme.dart' starter template. Feel free to copy and paste it and customise it however you like (perhaps guided by some of the tips in this tutorial!).


This template does not contain code for a dark theme, but when you're ready for that, take a look at How do I add a dark theme?

import 'package:flutter/material.dart';

// COLOUR SCHEME
// -------------------------------------
// If you have custom business colours you could define them here.

const Color myFirstColor = Color(0xFFA34834);
const Color mySecondColor = Color(0xFF04DEF4);
// Add more colours here!
// -------------------------------------

// LIGHT THEME
// -------------------------------------
ThemeData lightTheme = ThemeData(
  colorScheme: const ColorScheme(
    
    primary: myFirstColor,
    onPrimary: myFirstColor,
    primaryContainer: myFirstColor,
    onPrimaryContainer: myFirstColor,

    secondary: myFirstColor,
    onSecondary: myFirstColor,
    secondaryContainer: myFirstColor,
    onSecondaryContainer: myFirstColor,
    
    tertiary: myFirstColor,
    tertiaryFixedDim: myFirstColor,
    onTertiary: myFirstColor,
    tertiaryContainer: myFirstColor,
    onTertiaryContainer: myFirstColor,
    
    inverseSurface: myFirstColor,
    inversePrimary: myFirstColor,
    onInverseSurface: myFirstColor,
    surface: myFirstColor,
    onSurface: myFirstColor,
    surfaceContainerHighest: myFirstColor,
    onSurfaceVariant: myFirstColor,
    surfaceTint: myFirstColor,
    surfaceDim: myFirstColor,
    
    outline: myFirstColor,
    outlineVariant: myFirstColor,
    scrim: myFirstColor,
    shadow: myFirstColor, 

    error: Colors.red,
    onError: Colors.white,
    errorContainer: myFirstColor,
    onErrorContainer: myFirstColor,
  ),

  appBarTheme: const AppBarTheme(
    color: myFirstColor,
    elevation: 10,
    titleTextStyle: TextStyle(
      color: myFirstColor,
      fontSize: 22,
      fontWeight: FontWeight.bold,
      fontFamily: "exampleFont"
    )
  ),

  textTheme: TextTheme(
    displayLarge: exampleFont(fontSize: 57, fontWeight: FontWeight.bold,),
    displayMedium: exampleFont(fontSize: 45, fontWeight: FontWeight.bold),
    displaySmall: exampleFont(fontSize: 36, fontWeight: FontWeight.bold),
    headlineLarge: exampleFont(fontSize: 32, fontWeight: FontWeight.bold),
    headlineMedium: exampleFont(fontSize: 28, fontWeight: FontWeight.bold),
    headlineSmall: exampleFont(fontSize: 24, fontWeight: FontWeight.bold),
    titleLarge: exampleFont(fontSize: 20,  fontWeight: FontWeight.bold),
    titleMedium: exampleFont(fontSize: 16,),
    titleSmall: exampleFont(fontSize: 14,),
    labelLarge: exampleFont(fontSize: 14, fontWeight: FontWeight.bold),
    labelMedium: exampleFont(fontSize: 12, fontWeight: FontWeight.bold),
    labelSmall: exampleFont(fontSize: 11, fontWeight: FontWeight.bold),
    bodyLarge: exampleFont(fontSize: 16,),
    bodyMedium: exampleFont(fontSize: 14,),
    bodySmall: exampleFont(fontSize: 12,),
  ),

  brightness: Brightness.light,
  useMaterial3: true,
);
// -------------------------------------

How do I design an app colour scheme?

Picking your app colours can be either an exciting task or an incredibly boring one, depending on what kind of app developer you are! Of course, this is a whole job in itself and bigger companies would hire a graphic designer or marketing expert to do this, but for a small indie team or solo developer this is definitely something you can have a first go at yourself. Here are the absolute basics you need to know on choosing a colour scheme for your app.


Choose colours that fit the purpose of the app

Different colours are associated with different things in peoples' subconscious and so you might want to choose colours which reflect what your app does, or how you'd like it to feel. For example, a nature app might choose greens and sky blues. A dating app might choose red which symbolises love. Blue is associated with trust and so is often used by banking apps.


A great resource for learning more about the psychology of colour can be found here.


Make sure you have good contrast between lots of different colours

Your app will need a very light colour for backgrounds, a darker colour for text, and some bright, fun colours to give the app personality. However, you don't want your colours to be too similar otherwise people won't be able to read text easily or distinguish between shapes. From an accessibility point of view, you should aim to meet WCAG standards (Web Content Accessibility Guidelines) so that as many people as possible can understand your app. You can use this tool recommended by the UK Government to check the contrast between all your colours and learn more.


I used this Figma template to see how the colours of my app, EcoTweaks, worked together - you can be the judge of how "successful" of a colour palette it is! On reflection, I thought I had lots of high-contrast combinations but when it came to implementing this colour scheme in the app I found that my choice was quite limited, so I think I have room for improvement.


A Figma graphic showing how the eight colours of EcoTweaks all overlap and contrast with each other.

Don't choose too many colours!

It can be very fun choosing colours for your app and it's easy to get carried away. But, try not to pick too many colours as it can make your app look busy and unprofessional. Try to stick to:

  • One light background colour

  • One dark text colour

  • Three or four other colours, ensuring some are lighter, some are darker, and most colour combinations pass the contrast check!


How do I assign my colours to the Flutter theme?

Now you have your beautiful colour scheme picked out, you'll want to put it into 'theme.dart'. First, assign your colours easy-to-understand names at the start of the file:

const Color myFirstColor = Color(0xFFA34834);
const Color mySecondColor = Color(0xFF04DEF4);

I like descriptive names like 'lightBlueColor', 'veryDarkGreenColor' and 'sandColor'.


The next step is to assign these colours to your ColorScheme. This Flutter class has many properties like 'primary', 'secondary' and 'onSecondary' which you can customise. You can refer to the docs to understand what each of these properties is used for in the UI, here. For example, 'primary' is "The color displayed most frequently across your app’s screens and components.", and tertiary is "A color used as a contrasting accent that can balance primary and secondary colors or bring heightened attention to an element, such as an input field.", etc.


I created this graphic using the EcoTweaks colours to show how each property is used in relation to others as I prefer to learn visually! I hope it helps you too.


A Figma graphic showing the EcoTweaks colours assigned to properties of the Flutter colour scheme class.

How do I pick my custom fonts?

You may want to add a custom font to your app. This is not required as the defaults are very readable and slick, and are used happily by many production apps. But, maybe you want to add a bit of flair and stand out from the crowd! Adding one or more custom fonts can be a great way to do this.


Google fonts have many free fonts to choose from so I recommend starting there. Bear in mind that some fonts are less accessible than others so try not to shut users out of your app by choosing a very fiddly font. Generally speaking, sans serif fonts (like Ariel) are more accessible than serif (like Times New Roman).


How do I add my custom fonts to the Flutter theme?

If you've chosen a custom font, you now need to get it into your Flutter project. I'm using a free Google font in this example.


After making sure the font is free to use by checking the license, download the font using the "Get font" button.


A screenshot of the Google font webpage for the font 'quicksand' with the 'license' and 'Get font' buttons highlighted.

Then, choose "Download all".


A screenshot of the download options for the font quicksand, including 'Get embedded code' and 'Download all'.

Once you extract the files from the downloaded zip file, you'll see a folder that look like this:


A screenshot of the contents of the zip file of the downloaded font.

We will need the static filed in the "static" folder. They should look something like this. You font may have more or fewer font options. What matters is that you are seeing .ttf files.


A screenshot of the five static files included int he downloaded font zip file.

Drag these files into your assets folder structure. I like to have a google_fonts folder in my lib/assets. You can put the .ttf files directly into google_fonts, or put them in a sub-folder. Personally, I'll put this font in a sub-folder named after the font. This structure keeps things organised if we add more fonts in the future.


A screenshot of the folder structure in VSCode which shows fonts inside quicksand, inside google_fonts, inside assets.

Next, we want to add our new assets to pubspec.yaml:

assets:
    - lib/assets/google_fonts/quicksand/

We will need the google_fonts package to bring this all together. The docs for this package can be found here. Add it to your project by typing

flutter pub add google_fonts

into the terminal.


Now, we have the font saved as assets in the project, and we have the google_fonts package installed. We can now add the custom font to our theme! Have fun with different TextStyle properties for full customisation.

textTheme: TextTheme(
    displayLarge: GoogleFonts.quicksand(fontSize: 57, fontWeight: FontWeight.bold,),
    displayMedium: GoogleFonts.quicksand(fontSize: 45, fontWeight: FontWeight.bold),
    displaySmall: GoogleFonts.quicksand(fontSize: 36, fontWeight: FontWeight.bold),
    headlineLarge: GoogleFonts.quicksand(fontSize: 32, fontWeight: FontWeight.bold),
    headlineMedium: GoogleFonts.quicksand(fontSize: 28, fontWeight: FontWeight.bold),
    headlineSmall: GoogleFonts.quicksand(fontSize: 24, fontWeight: FontWeight.bold),
    titleLarge: GoogleFonts.quicksand(fontSize: 20,  fontWeight: FontWeight.bold),
    titleMedium: GoogleFonts.quicksand(fontSize: 16,),
    titleSmall: GoogleFonts.quicksand(fontSize: 14,),
    labelLarge: GoogleFonts.quicksand(fontSize: 14, fontWeight: FontWeight.bold),
    labelMedium: GoogleFonts.quicksand(fontSize: 12, fontWeight: FontWeight.bold),
    labelSmall: GoogleFonts.quicksand(fontSize: 11, fontWeight: FontWeight.bold),
    bodyLarge: GoogleFonts.quicksand(fontSize: 16,),
    bodyMedium: GoogleFonts.quicksand(fontSize: 14,),
    bodySmall: GoogleFonts.quicksand(fontSize: 12,),
  ),

A note on offline functionality: we have downloaded the font and added it as an asset so that the font can be used when the app is offline. The google_fonts package will automatically use the asset if it can rather than fetching via HTTP, but will fall back on HTTP fetching if it needs to. In production, you might want to disable HTTP fetching so there is no chance of error if the app is offline. To do this, add

GoogleFonts.config.allowRuntimeFetching = false;

into your app's main method.


Finally, I like to test this whole setup by running my app both online and offline to check that my font is displaying properly.


If at any point you run into errors, you might want to try typing

flutter clean
flutter pub get

into the terminal. Since we've added packages and assets, things can sometimes get muddled and this usually clears things up.


How do I reference my theme throughout my app?

You can refer to the official docs for more information on how to apply a theme throughout your app, here, but in a nutshell, you can use

Theme.of(context)

wherever context is available to access your theme. For example, I have fully customised this Text widget in my app:

return Center(
  child: Column(
    mainAxisAlignment: MainAxisAlignment.center,
     children: [
       Text(
         'Some sample text',
         style: Theme.of(context).textTheme.headlineMedium!.copyWith(
           color: Theme.of(context).colorScheme.tertiary,
         ),
       ),
       Text(
         'Some more sample text',
         style: Theme.of(context).textTheme.titleSmall,
       ),
     ],
   ),
 );

Notice that I have accessed the textTheme in both cases, and in the first case, I've used copyWith to take all the formatting of the headlineMedium text but override only the colour with the tertiary colour from my colorScheme. This is the result:


A screenshot of the output of the code above: just two lines of text with different sizes and colours.

How do I add a dark theme?

If you want to add a dark theme to your 'theme.dart' file, repeat the light theme code structure but change your colours accordingly. You can copy and paste the dark theme template below. The only difference is the line of code that changes from

brightness: Brightness.light

to

brightness: Brightness.dark,
// DARK THEME
// -------------------------------------
ThemeData darkTheme = ThemeData(
  colorScheme: const ColorScheme(
    // Add all your colour information here
  ),

  appBarTheme: const AppBarTheme(
      // Add all your app bar customisation here
    )
  ),


  textTheme: TextTheme(
    // Add all your text theme information here
  ),


  brightness: Brightness.dark,
  useMaterial3: true,
);
// -------------------------------------

Automatically switch between dark and light mode

Once you've set up your lightTheme and darkTheme, setting your app to choose the right theme based on your user's phone settings couldn't be easier.


In your MaterialApp in 'main.dart', make sure you have these three lines of code:

theme: lightTheme,
darkTheme: darkTheme,
themeMode: ThemeMode.system,

Now, your app will automatically choose the right theme for your user. Go ahead and test it by switching to dark or light mode in your phone or emulator settings!


And that's it!

You have successfully:

  1. Chosen a colour scheme for your app, with accessibility in mind

  2. Chosen a custom font for your app

  3. Created a light theme and a dark theme using your custom colours and font

  4. Referenced your theme throughout your application

  5. Connected your light and dark themes with the user's phone settings so that these toggle automatically


Now that your theme is defined in one place, as you iterate and improve your app design, any changes made in 'theme.dart' will filter through to your entire app with minimal changes.


I hope that this was useful for you. Please do get in touch if you have any questions on this tutorial, and I look forward to seeing you in the next one.

EcoTweaks

Out now on iOS and Android

Copyright © 2025 Cozy Mae Studios Ltd

Cozy Mae Studies Ltd is a company registered in England and Wales (Company No. 15859459)

3rd Floor, 86-90 Paul Street, London, EC2A 4NE

bottom of page