# Why theming in Flutter is confusing (to me) Part 2

In my [previous article](https://fluttergamedev.com/why-theming-in-flutter-is-confusing-to-me), I tried to explain why theming in Flutter confuses me.  
I ended the article by saying the way `ThemeData` is implemented doesn't make sense to me.

A few weeks have passed and I've been playing with this in my head, and within my pet project. I had some new insights that I would like to share with you in this article.

# But first, we need to make things clear

During the discussion, people were saying to me that *Material Design* is a good design system and it's not confusing to them.

And I agree that Material Design is a good system. It's well-documented and covers all varieties of devices and screen sizes.

So just to be clear, this article is not about criticizing Material Design. It's about how theming is implemented in Flutter.

The other thing that has been mentioned is that `ThemeData` is capable of implementing any design. This is also not something that I'm claiming Flutter is not capable of. But what we have to do to achieve it, is confusing to me.

# New insights

In the last couple of weeks I've played around with theming in my pet project and I also started a new project at work.

Thinking about theming in both of these projects led me to new thoughts that might explain why it is confusing me.

## Property overload (part 2)

In the previous article, I also talked about [property overload](https://fluttergamedev.com/why-theming-in-flutter-is-confusing-to-me#heading-property-overload). I talked about all these properties you have available to you in the `ThemeData` object, even though you might only need 1% of them.

People commented that why this is even a problem since I could "just not use them".

So I started thinking about this, and why it bothers me as much as it does. And I found the reason, which I will explain to you here.

### Abstractions

First, we will have to talk about *abstractions*. Using abstractions is a common practice for us software developers.

We often use abstractions to make other people's code more our own and more specific to our needs.

Let's say we're building an app for our local swimming pool and they wish to show the weather forecast for the upcoming week.

We might want to use some 3rd party service like [https://openweathermap.org/](https://openweathermap.org/).

OpenWeather gives us a wide variety of endpoints and options to get weather data. But, for our use case, we only need the forecast for the upcoming week. So therefore we can make an abstraction of this service.

We could end up with a `WeatherRepository`. This repository only needs a single function, `getWeekForecast()`. It will call the OpenWeather endpoint for a forecast. The location can be hardcoded since it's always for the same location, which is the one of the swimming pool.

We have now made an abstraction of the OpenWeather API which is easy for us to use in our application.

### Always ThemeData

In the example above I've described a common practice in software development about using abstractions to make other people's code our own.

So if we do it for other things, why not for theming?

Well, because you can't. Theming in Flutter is implemented in such a way that when you grab the `Theme` from `context`, it will always return a `ThemeData` object. And as we know, `ThemeData` contains all these fields, even though we don't need and use them.

In the previous article, I used the counter app as an example. Wouldn't it make the theme more clear if we could abstract away all the properties we don't use, and maybe give our texts a more describing name than *bodyMedium* and *titleMedium* in the process?

## Why ThemeData

I've also thought about the existence of `ThemeData`. Why would they use it like this, and what is its purpose?

### Global Theming

I realized that this is the only way to globally style the Material Widgets without wrapping them in a custom widget.

For example, it prevents us from having to put the same `InputDecoration` on every `TextField`.

### Limitations

`ThemeData` is designed against the Material Design specifications.

And even though this can come across as flexible, it also is limited by it. You will especially experience this when you have to implement UI that is not (fully) based on Material Design.

An example. Material Design defines two *types* of text fields:

![Side by side view two types of text fields, filled and outlined](https://lh3.googleusercontent.com/FK0BIH5f5k-uZK8M6FF0Y8XDRKoOLHlOZQwkdmOHF9g9j73SkbCCLHL1WAlJqw79qZdSBKQSAJM_n41bKnyS0Fe_NljhSm3sG3QFXfFr6peSCg=s0 align="left")

The first is called *Filled*, and the second is called *Outlined*.

So what if we have the following design:

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1682250251541/0d885007-b86f-4658-a5c2-7ccb0b26e245.png align="center")

With `ThemeData` you can go a long way, but to get that label above the `TextField`, you will have to create a custom widget to make it easily reusable since we don't want to place the `Text` widget above every `TextField` manually, right?

Earlier, I mentioned that `ThemeData` was necessary to globally style Material Widgets without having to wrap them. But since we just created a custom component, let's call it `MyTextField`, we've just created a wrapper.

So now we could also define the styling directly in the component. And because we reuse the component, we are globally theming our app at the same time. There is no need for an external way of defining a style for this component anymore.

### Dark and light mode

Okay, the above statement was not completely true. Most modern applications support both dark and light modes. So `MyTextField` should change according to the active mode.

To support dark and light modes in Flutter you define two `ThemeData` objects. So technically, you would be able to create two completely different Themes that don't even look like the same app because it gives you access to every material property.

In practice, this is hardly the case. More often it's just a difference in colors. A white background becomes dark grey and the black text becomes white.

So what we need is a theme that just holds the values that change between themes, nothing more.

### Theme vs component properties

So what if we would style our `MyTextField` directly inside the class? This makes it easier to maintain because you don't have to deal with two different `ThemeData` classes. When the design changes, it most likely should be changed in both light and dark themes anyway.

Now we only have to find a way to allow `MyTextField` to adapt to light and dark mode changes.

After taking another quick look at the design, the only properties that need to change are:

1. The color of the label
    
2. The color of the Input Text
    
3. The background color of the text field
    

So what if we could have a theme that just contains these kinds of properties?

> NOTE: We could also check for the mode in the component but this is a bit ... mehh, IMO.
> 
> It would also limit to only dark and light modes while you might also want to support a special theme for people suffering from colorblindness later on.

# Explicit theming

In the conclusion of the previous article, I dropped the term 'explicit theming'.

This is something I'm currently experimenting with in my pet project. It applies the things I mentioned in this article.

What I'm currently doing is breaking my app up into custom reusable components. These will ensure consistency across the app because they will contain most of the styling.

For the dark/light mode configurations, I'm creating a custom Theme class that only holds the properties that change when switching modes. In a sense, it is an abstraction of `ThemeData` that only gives me access to properties I use.

I'm still playing around with this but so far I like where it is going. If I'm a bit further with the development of my pet project and I'm still happy with it, I will dedicate an article to it.

# Conclusion

I have a bit more understanding of why Theming in Flutter is confusing to me. I also have a better understanding of why ThemeData is 'needed'.

I'm still looking for a way of theming that fits me better and therefore I'm experimenting with something I'd like to call: 'explicit theming'.
