Flutter Mobile Development · Pelajaran

Tipografi Responsif dan Tema Komponen

Skalakan teks dan sesuaikan tema komponen untuk menjaga konsistensi merek di berbagai perangkat.

Pelajaran 4 dari 413 langkah

Tipografi Responsif dan Tema Komponen adalah pelajaran Flutter Mobile Development gratis di CoddyKit. Ini adalah pelajaran 4 dari 4. Kamu bisa membaca pelajaran lengkapnya di bawah secara gratis — lalu praktikkan langsung di browser dengan editor kode bawaan dan tutor AI 24/7. Ini adalah bagian dari jalur belajar Flutter Mobile Development, dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus Flutter Mobile Development mencakup 4 pelajaran total.

Bagian dari pelajaran ini belum diterjemahkan dan ditampilkan dalam bahasa Inggris.

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, textButtonTheme
  • cardTheme, chipTheme, appBarTheme
  • inputDecorationTheme for 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 MediaQuery width and clamp them, and respect (but bound) the user's textScaler for accessibility.
  • Component themes: ElevatedButtonThemeData, CardThemeData, and InputDecorationTheme style entire widget families once.
  • Single source of truth: assemble everything into one ThemeData with ColorScheme.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.

Gratis untuk memulai

Belajar Dart dengan tutor AI — gratis

Tulis dan jalankan kode asli di browser kamu, dapatkan bantuan instan dari tutor AI 24/7, dan lanjutkan di mana kamu tinggalkan di web atau aplikasi.

Kursus
22
Pelajaran
88

Pertanyaan yang Sering Diajukan

Apakah pelajaran “Tipografi Responsif dan Tema Komponen” gratis?

Ya — teks lengkap “Tipografi Responsif dan Tema Komponen” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus Flutter Mobile Development, upgrade ke CoddyKit PRO. Kursus Flutter Mobile Development mencakup 4 pelajaran total.

Apa yang akan aku pelajari di “Tipografi Responsif dan Tema Komponen”?

Skalakan teks dan sesuaikan tema komponen untuk menjaga konsistensi merek di berbagai perangkat. Kamu berlatih Flutter Mobile Development dengan kode praktik yang langsung kamu jalankan di browser, dan tutor AI 24/7 menjawab pertanyaanmu saat kamu mengerjakan pelajaran ini.

Apakah aku perlu pengalaman untuk memulai Flutter Mobile Development?

Tidak diperlukan pengalaman sebelumnya. Flutter Mobile Development di CoddyKit dirancang untuk pemula hingga pelajar tingkat lanjut, jadi kamu bisa memulai di sini atau dari awal dan belajar sesuai kecepatan kamu sendiri. Ini adalah pelajaran 4 dari 4.

Berapa lama pelajaran “Tipografi Responsif dan Tema Komponen” memakan waktu?

Sebagian besar pelajaran CoddyKit memakan waktu sekitar 5–10 menit. Setiap pelajaran ringkas dan interaktif, jadi kamu membuat kemajuan stabil dan melanjutkan dari tempat kamu tinggalkan di web dan aplikasi.

Bisakah aku menulis dan menjalankan kode dalam pelajaran Flutter Mobile Development ini?

Ya. Setiap pelajaran Flutter Mobile Development menyertakan editor kode bawaan, jadi kamu menulis dan menjalankan kode nyata langsung di browser dan mendapatkan umpan balik AI instan — tidak diperlukan penyiapan lokal.

Semua pelajaran dalam kursus ini

  1. Skema Warna Material 3 dan Warna Seed
  2. Warna Dinamis dan Tema Terang atau Gelap Adaptif
  3. ThemeExtension Khusus untuk Token Merek
  4. Tipografi Responsif dan Tema Komponen
← Kembali ke Flutter Mobile Development