Flutter Advanced Custom Theming: A Beginner-Friendly Guide
FlutterPulseThis article was translated specially for the channel FlutterPulseYou'll find lots of interesting things related to Flutter on this channel. Don't hesitate to subscribe!๐

Master advanced custom theming in Flutter using ThemeExtension for dynamic light and dark modes in one simple guide!
The Ultimate Guide to Advanced Custom Theming in Flutter
Introduction
Theming in Flutter is crucial for maintaining a consistent and scalable UI. In this article, we will learn how to create a custom theme using ThemeExtension to manage colors, text styles, and themes efficiently.
Folder Structure
lib/
โโโ main.dart
โโโ theme/
โ โโโ app_colors.dart
โ โโโ app_color_theme.dart
โ โโโ app_text_theme.dart
โ โโโ app_theme.dart
โ โโโ theme_data_extension.dart
โโโ utilities/
โ โโโ constants.dart
- Defines Colors
This file defines the base colors used throughout the app.
// theme/app_colors.dart
import 'package:flutter/material.dart';
class AppColors {
static const Color white = Color(0xFFFFFFFF);
static const Color green = Color(0xFF6FD87B);
static const Color black = Color(0xFF323232);
static const Color red = Color(0xFFEA3223);
static const Color gray = Color(0xFFC5C5C5);
static const Color lightGray = Color(0xFFC5C5C5);
static const Color orange = Color(0xFFFF8A00);
}
- Centralized color management.
- Easy to update colors for the entire app.
2. Manages Light & Dark Theme Colors
This file extends the theme with color variations for light and dark themes.
// theme/app_color_theme.dart
import 'package:flutter/material.dart';
import 'app_colors.dart';
class AppColorTheme extends ThemeExtension<AppColorTheme> {
final Color white;
final Color green;
final Color black;
final Color red;
final Color gray;
final Color lightGray;
final Color orange;
// Light Theme Colors
AppColorTheme({
this.white = AppColors.white,
this.green = AppColors.green,
this.black = AppColors.black,
this.gray = AppColors.gray,
this.lightGray = AppColors.lightGray,
this.orange = AppColors.orange,
this.red = AppColors.red,
});
// Dark Theme Colors
factory AppColorTheme.dark() {
return AppColorTheme(
white: AppColors.black,
black: AppColors.white,
gray: const Color.fromARGB(255, 46, 21, 21),
lightGray: const Color.fromARGB(255, 79, 64, 64),
);
}
@override
/// To override default color values while using.
ThemeExtension<AppColorTheme> copyWith({
Color? white,
Color? green,
Color? black,
Color? red,
Color? gray,
Color? lightGray,
Color? orange,
}) {
return AppColorTheme(
white: white ?? this.white,
green: green ?? this.green,
black: black ?? this.black,
red: red ?? this.red,
gray: gray ?? this.gray,
lightGray: lightGray ?? this.lightGray,
orange: orange ?? this.orange,
);
}
@override
ThemeExtension<AppColorTheme> lerp(
covariant ThemeExtension<AppColorTheme>? other, double t) {
return this;
}
}
- Supports light and dark themes
- Provides flexibility with
copyWith()for color customization.
3. Manages Text Styles
This file defines text styles (big text, normal text, small text, etc.).
// theme/app_text_theme.dart
import 'package:flutter/material.dart';
import '../utilities/constants.dart';
import 'app_colors.dart';
abstract class AppTextThemeBaseModel {
TextStyle get bigText;
TextStyle get text;
TextStyle get smallText;
TextStyle get verySmallText;
}
class AppTextTheme extends ThemeExtension<AppTextTheme>
implements AppTextThemeBaseModel {
double bigTextFontSize = 18;
double normalTextFontSize = 16;
double smallTextFontSize = 12;
double verySmallTextFontSize = 8;
@override
TextStyle get bigText => TextStyle(
fontSize: bigTextFontSize,
color: AppColors.black,
fontWeight: FontWeight.normal,
fontFamily: Constants.fontFamily,
);
/// Font Size: 16, Font weight: Normal
@override
TextStyle get text => TextStyle(
fontSize: normalTextFontSize,
color: AppColors.black,
fontWeight: FontWeight.normal,
fontFamily: Constants.fontFamily,
);
@override
TextStyle get smallText => TextStyle(
fontSize: smallTextFontSize,
color: AppColors.black,
fontWeight: FontWeight.w500,
fontFamily: Constants.fontFamily,
);
@override
TextStyle get verySmallText => TextStyle(
fontSize: verySmallTextFontSize,
color: AppColors.black,
fontWeight: FontWeight.normal,
fontFamily: Constants.fontFamily,
);
@override
ThemeExtension<AppTextTheme> copyWith({
double? bigTextFontSize,
double? normalTextFontSize,
double? smallTextFontSize,
double? verySmallTextFontSize,
}) {
return AppTextTheme()
..bigTextFontSize = bigTextFontSize ?? this.bigTextFontSize
..normalTextFontSize = normalTextFontSize ?? this.normalTextFontSize
..smallTextFontSize = smallTextFontSize ?? this.smallTextFontSize
..verySmallTextFontSize =
verySmallTextFontSize ?? this.verySmallTextFontSize;
}
@override
ThemeExtension<AppTextTheme> lerp(
covariant ThemeExtension<AppTextTheme>? other, double t) {
return this;
}
}
- Defines custom text styles that are easy to update.
- Keeps typography consistent throughout the app.
4. Combines Colors & Text Styles
This file merges the color and text themes into light and dark themes.
// theme/app_theme.dart
import 'package:flutter/material.dart';
import '../utilities/constants.dart';
import 'app_color_theme.dart';
import 'app_text_theme.dart';
class AppTheme {
static ThemeData lightTheme() => ThemeData(
fontFamily: Constants.fontFamily,
useMaterial3: true,
extensions: [
AppColorTheme(),
AppTextTheme(),
],
);
static ThemeData darkTheme() => ThemeData(
useMaterial3: true,
fontFamily: Constants.fontFamily,
extensions: [
AppColorTheme.dark(),
AppTextTheme(),
],
);
}
- Combines colors and typography into a single theme.
- Provides both light and dark themes.
5. Simplifies Theme Access
This file extendsThemeData and BuildContext for easier theme access.
// theme/theme_data_extension.dart
import 'package:flutter/material.dart';
import 'app_color_theme.dart';
import 'app_text_theme.dart';
extension ThemeDataExtension on ThemeData {
AppColorTheme get appColorTheme =>
extension<AppColorTheme>() ?? AppColorTheme();
AppTextTheme get appTextTheme => extension<AppTextTheme>() ?? AppTextTheme();
}
extension ThemeContext on BuildContext {
AppColorTheme get appColorTheme =>
Theme.of(this).extension<AppColorTheme>() ?? AppColorTheme();
AppTextTheme get appTextTheme =>
Theme.of(this).extension<AppTextTheme>() ?? AppTextTheme();
}
- Allows quick access to colors and text styles using
context.
6. Applies Themes in App
Finally, we apply our custom themes in the MaterialApp.
// main.dart
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: AppTheme.lightTheme(),
darkTheme: AppTheme.darkTheme(),
themeMode: ThemeMode.system,
);
}
}
How to Use in UI?
// Using with Theme class
Text(
"Hello world.",
style: Theme.of(context).appTextTheme.bigText.copyWith(// Access textheme using Theme class
color: Theme.of(context).appColorTheme.black, // Access theme colors using Theme class
),
),
// Using with BuildContext (Easy to access๐)
Text(
"Hello world.",
style: context.appTextTheme.bigText.copyWith( // Access textheme easily using context๐
color: context.appColorTheme.black, // Access theme colors easily using context๐
),
),
๐ Conclusion
- We built a custom theming system for a scalable UI.
- Supports light and dark mode.
- Easy access to colors and typography.
๐ Now your Flutter app has an advanced theme setup!
If you found this article useful, please give it a clap ๐ and leave a comment ๐จ๏ธ to encourage me to write more!
Happy coding ๐!