Typographie réactive et thèmes des composants
Mettez le texte à l’échelle et personnalisez les thèmes des composants pour assurer une identité cohérente sur tous les appareils.
Typographie réactive et thèmes des composants est une leçon Flutter Mobile Development gratuite sur CoddyKit. Ceci est la leçon 4 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage Flutter Mobile Development, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours Flutter Mobile Development comprend 4 leçons au total.
Certaines parties de cette leçon n'ont pas encore été traduites et s'affichent en anglais.
Why Typography Scales
A design system keeps your app's look consistent across phones, foldables, and tablets. Two pillars hold it together: typography (how text looks at every size) and component theming (how buttons, cards, and inputs are styled once and reused everywhere).
In Material 3, both live inside ThemeData. Instead of styling each widget by hand, you define the rules centrally and let widgets inherit them. This lesson shows how to scale text responsively and customize component themes for consistent cross-device branding.
- TextTheme carries the type scale (display, headline, title, body, label).
- Component themes (e.g.
ElevatedButtonThemeData) shape each widget family.
The Material 3 Type Scale
Material 3 defines a type scale of 15 named styles grouped into 5 roles. Each role has Large, Medium, and Small variants:
displayLarge/Medium/Small— big, expressive hero text.headlineLarge/Medium/Small— section headers.titleLarge/Medium/Small— list and dialog titles.bodyLarge/Medium/Small— paragraphs and main content.labelLarge/Medium/Small— buttons, captions, chips.
You read these from context anywhere in your widget tree, so a heading always matches the same scale no matter where it appears.
Widget build(BuildContext context) {
final textTheme = Theme.of(context).textTheme;
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Welcome', style: textTheme.displaySmall),
Text('Your daily summary', style: textTheme.titleMedium),
Text('Here is what happened today.', style: textTheme.bodyMedium),
],
);
}Customizing the TextTheme
To brand your typography, override the textTheme on ThemeData. A clean approach is to start from a base text theme and copyWith only the styles you want to change. This keeps the rest of the Material defaults intact.
Notice how each style is a TextStyle with explicit fontSize, fontWeight, and letterSpacing. Defining them in one place guarantees consistency across every screen.
final ThemeData appTheme = ThemeData(
useMaterial3: true,
textTheme: const TextTheme(
displaySmall: TextStyle(
fontSize: 36,
fontWeight: FontWeight.w700,
letterSpacing: -0.5,
),
titleMedium: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
),
bodyMedium: TextStyle(
fontSize: 14,
height: 1.4,
),
),
);Responsive Sizing with MediaQuery
Hard-coded font sizes look great on one device but cramped or oversized on another. Use MediaQuery to read the screen width and pick a scale factor. A common pattern: clamp a base size between a minimum and a maximum so text never gets absurdly small or large.
Here we compute a responsive headline size from the available width, then apply it on top of the theme's style with copyWith.
Widget build(BuildContext context) {
final width = MediaQuery.of(context).size.width;
// Scale headline between 24 and 40 based on width.
final headlineSize = (width / 14).clamp(24.0, 40.0);
final base = Theme.of(context).textTheme.headlineMedium;
return Text(
'Cross-device branding',
style: base?.copyWith(fontSize: headlineSize),
);
}Respecting the User's Text Scale
Accessibility matters: users can enlarge system text. In modern Flutter, read this via MediaQuery.textScalerOf(context), which returns a TextScaler. Avoid disabling it outright; instead clamp it so very large settings don't break your layout while still honoring the user's preference.
Wrap a subtree in MediaQuery with a clamped scaler to bound the growth.
Widget build(BuildContext context) {
final scaler = MediaQuery.textScalerOf(context)
.clamp(minScaleFactor: 1.0, maxScaleFactor: 1.6);
return MediaQuery(
data: MediaQuery.of(context).copyWith(textScaler: scaler),
child: const Text('Readable yet bounded'),
);
}A Pure-Dart Responsive Helper
The scaling logic itself is plain Dart and easy to unit-test in isolation, no Flutter needed. Below is a small function that maps a screen width to a font size with a linear ramp between two breakpoints, then clamps the result. Testing this pure logic separately keeps your widgets thin.
double responsiveFontSize(
double width, {
double minWidth = 320,
double maxWidth = 840,
double minSize = 14,
double maxSize = 22,
}) {
if (width <= minWidth) return minSize;
if (width >= maxWidth) return maxSize;
final t = (width - minWidth) / (maxWidth - minWidth);
return minSize + t * (maxSize - minSize);
}
void main() {
print(responsiveFontSize(300)); // 14.0 (clamped)
print(responsiveFontSize(580)); // ~17.0
print(responsiveFontSize(900)); // 22.0 (clamped)
}Introducing Component Themes
Beyond text, Material 3 lets you theme entire widget families centrally. Each has a dedicated *ThemeData slot on ThemeData:
elevatedButtonTheme,filledButtonTheme,textButtonThemecardTheme,chipTheme,appBarThemeinputDecorationThemefor text fields
Set them once and every matching widget inherits the styling. This is the heart of a design system: change the brand in one file, see it everywhere.
Theming Elevated Buttons
Use ElevatedButtonThemeData with a ButtonStyle to standardize padding, shape, and text style for every ElevatedButton in the app. Tying the button's label style back to labelLarge keeps it aligned with your type scale.
Because the theme supplies these defaults, individual buttons stay clean: ElevatedButton(onPressed: ..., child: Text('Save')) with no inline styling.
final elevatedButtonTheme = ElevatedButtonThemeData(
style: ElevatedButton.styleFrom(
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 14),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
textStyle: const TextStyle(
fontSize: 15,
fontWeight: FontWeight.w600,
),
),
);Theming Cards and Inputs
Cards and text fields are everywhere in mobile UIs, so theming them pays off fast. CardThemeData controls elevation, shape, and margin; InputDecorationTheme standardizes borders, fills, and label behavior for every TextField.
With these in place, a form looks consistent across the app without repeating decoration code on each field.
final cardTheme = CardThemeData(
elevation: 1,
margin: const EdgeInsets.all(8),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16),
),
);
final inputDecorationTheme = InputDecorationTheme(
filled: true,
contentPadding: const EdgeInsets.all(16),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
borderSide: BorderSide.none,
),
);Assembling the Full ThemeData
Now combine typography and component themes into a single ThemeData. Pairing it with a ColorScheme.fromSeed gives you a coherent Material 3 palette. Pass this theme to MaterialApp(theme: ...) and the whole app picks it up.
This one object is your design system's source of truth: brand colors, type scale, and component styling, all together.
ThemeData buildBrandTheme() {
return ThemeData(
useMaterial3: true,
colorScheme: ColorScheme.fromSeed(seedColor: const Color(0xFF6750A4)),
textTheme: const TextTheme(
titleMedium: TextStyle(fontSize: 16, fontWeight: FontWeight.w600),
bodyMedium: TextStyle(fontSize: 14, height: 1.4),
),
elevatedButtonTheme: ElevatedButtonThemeData(
style: ElevatedButton.styleFrom(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
),
),
cardTheme: CardThemeData(
elevation: 1,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16),
),
),
);
}Reading the Theme in Widgets
Once the theme is set, widgets should pull styling from it rather than hard-coding values. Use Theme.of(context) to access the textTheme, colorScheme, and any component theme.
This makes your widgets theme-agnostic: switch to a dark theme or rebrand, and they update automatically because they never assumed a specific color or size.
Widget build(BuildContext context) {
final theme = Theme.of(context);
return Card(
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Account', style: theme.textTheme.titleMedium),
const SizedBox(height: 8),
Text(
'Manage your profile and settings.',
style: theme.textTheme.bodyMedium?.copyWith(
color: theme.colorScheme.onSurfaceVariant,
),
),
],
),
),
);
}Quick Check
You want every TextField in your app to share the same rounded, filled border without repeating decoration code on each field. Which approach fits a Material 3 design system best?
Recap
You built the typography and component foundation of a Material 3 design system:
- Type scale: the 15 named styles (display, headline, title, body, label) read via
Theme.of(context).textTheme. - Custom TextTheme: override fonts and sizes centrally with
copyWith. - Responsive sizing: derive sizes from
MediaQuerywidth andclampthem, and respect (but bound) the user'stextScalerfor accessibility. - Component themes:
ElevatedButtonThemeData,CardThemeData, andInputDecorationThemestyle entire widget families once. - Single source of truth: assemble everything into one
ThemeDatawithColorScheme.fromSeed, then read it in theme-agnostic widgets.
The result is consistent cross-device branding that adapts to screen size and user preferences without per-widget styling.
Questions Fréquemment Posées
La leçon « Typographie réactive et thèmes des composants » est-elle gratuite ?
Oui — le texte complet de « Typographie réactive et thèmes des composants » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours Flutter Mobile Development, passe à CoddyKit PRO. Le cours Flutter Mobile Development comprend 4 leçons au total.
Qu'est-ce que j'apprendrai dans « Typographie réactive et thèmes des composants » ?
Mettez le texte à l’échelle et personnalisez les thèmes des composants pour assurer une identité cohérente sur tous les appareils. Tu pratiques Flutter Mobile Development avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.
Dois-je avoir de l'expérience pour commencer Flutter Mobile Development ?
Aucune expérience préalable n'est requise. Flutter Mobile Development sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 4 sur 4.
Combien de temps prend la leçon « Typographie réactive et thèmes des composants » ?
La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.
Peux-tu écrire et exécuter du code dans cette leçon Flutter Mobile Development ?
Oui. Chaque leçon Flutter Mobile Development inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.
Toutes les leçons de ce cours
- Palettes de couleurs Material 3 et couleurs initiales
- Couleur dynamique et thèmes clair/sombre adaptatifs
- ThemeExtension personnalisé pour les tokens de marque
- Typographie réactive et thèmes des composants