# Why theming in Flutter is confusing (to me)

About two weeks ago I posted the following tweet:

%[https://twitter.com/SEGVeenstra/status/1639904262837739520] 

Reactions to this tweet were pretty divided. Some people agreed with me, and some people thought the theming in Flutter was just fine.

In this article, I will try to explain exactly why I think theming in Flutter is confusing.

# What is a 'theme'?

If I look up the definition online, this is one of the first I find:

> A design theme is simply **the overall look and feel of a website**. The purpose of a design theme is to create unity across web pages through the consistent use of a color palette, fonts, and layout patterns
> 
> \- Uizard Technologies

Using a 'Theme' in your app creates unity and consistency across your application. When an application uses the same theme across its different screens, it lets the user know they are still inside the same application.

# Theming your Flutter app

Flutter allows you to 'style' elements in your app through the use of `ThemeData` objects which are provided by the `Theme` widget. All the Material Widgets in Flutter reference the `ThemeData` to cherry-pick its properties to be used as their *default* styling.

I say *default* because the Material Widgets also allow you to *override* the style of the component themselves.

## What style is used where?

How `ThemeData` is used by the Material Widgets is the first thing that confuses me. Material Widgets sometimes access different properties from `ThemeData`, depending on whether they have been supplied or not.

Let's take the `AppBar` Widget as an example.  
If we want to change the text style of the title, we have several options.

1. We can set the `titleTextStyle` property on the widget itself.
    
2. If that is `null`, it will try to get the style from `ThemeData.appBarTheme.titleTextstyle`.
    
3. If that is also `null`, it will get a more generic text style from `ThemeData`, `ThemeData.textStyles.titleLarge`.  
    But, instead of using that style's color, it will use the `AppBar.foregroundColor` property.
    
4. If the `AppBar.foregroundColor` property is `null`, it will try to use the `ThemeData.appBarTheme.foregroundColor`.
    
5. However, if that is also `null`, it will use `ThemeData.colorScheme.onPrimary` for the color. Unless the theme's `Brightness` is set to `Brightness.dark`, because then it will use `ThemeData.colorScheme.onSurface`.
    

This is just for styling one part (the title) of one component (the AppBar).

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1680963077142/88277e00-a641-4f83-a55b-e54fc4078b90.png align="center")

## Which style to use?

The next things that confuse me are the more generic style properties in `ThemeData`.

`ThemeData` contains a set of generic `TextStyle`s located in `ThemeData.textTheme`. It contains a bunch of old and new Material Design-defined styles for texts. If we ignore the deprecated styles and focus on the ones defined in the latest Material Design version, we have the following set of styles:

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1680963594301/9f50981c-36b0-4715-a994-131dd58f0912.png align="center")

Now I ask you, do these definitions make any sense to you? Where should they be used for?

Take a look at the image below. It's the well-known counter app...

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1680964210927/0ab84ac4-c363-4dbd-89c2-3833569b375d.png align="center")

Can you tell me which `TextStyle`s have been used for the number and the text above it, without looking into the code. I bet you cannot.

It turns out the number is using `ThemeData.textTheme.headlineMedium`, and the text above it uses `ThemeData.textTheme.bodyMedium`. But why? Why these properties, why are these 'medium' sized? Why aren't they 'small' or 'large'? Why is the number a headline?

`ColorScheme` is very similar and has the same issues, so I won't cover them here.

## 'Theming' in multiple places

If theming is about having a consistent design across your app, then we have two options for achieving that in Flutter.

I've always had the feeling that Flutter pushed us toward using `ThemeData`. But sometimes we also make reusable components when `ThemeData` just isn't enough, like a type of ProductCard we use on both a Search and Favorites page.

By using reusable components, you technically are also 'theming'. The final result is often a mix of the component's configuration and the current `Theme`.

I always have to think about where which configuration should go, it just isn't clear to me.

## ThemeData's rigid structure

The `ThemeData` class is rigid. It is not easy to add properties by *extending* the class for example. That's because when you want to use the `Theme` in your UI, the `Theme.of()` static function will return a `Theme`, meaning you will only see the properties `Theme` originally has.

There are some ways to work around this but they are a pain in the butt.

`ThemeData` also has a way to add `ThemeExtension`s ([docs](https://api.flutter.dev/flutter/material/ThemeExtension-class.html)). This is just a list of classes that extend the `ThemeExtension` class which can be accessed by calling `.extension<MyThemeType>()` on a `ThemeData` instance.

My issue with this is, that if I just want to add a single `TextStyle`, let's say `titleExtraLarge`, I will have to add it as an extension. So, they will not be located in the same location as the other `TextStyles`, which again makes it confusing to work with.

## Property overload

`ThemeData` by default gives you access to all these properties:

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1680966244180/786e3152-82a2-443d-8954-aa9000977856.png align="center")

These are just the root-level properties, I even left out the deprecated properties that are still in there.

Let's do an extreme example. Let's think about the counter app again. Why would we need all these properties? If we want to add a dark theme, only a few of these properties will have to change.

# Conclusion

I've tried to explain to you why I find theming in Flutter confusing. The way it's implemented and used across the Material Widgets doesn't make any sense to me.

I got a bunch of reactions with good suggestions on the tweet, and I also discussed this internally with my colleagues at [Pinch](https://pinch.nl) on how to improve theming.

Both gave me ideas on how I want to try and handle theming differently. I'm currently running with an idea that I'd like to call "explicit theming" inside my [pet project](https://fluttergamedev.com/series/local-explorer-devblog).

But it's too early to write something about it, so I'll let you know how that turns out.

Until next time!
