← Back to Articles

Flutter Text Rendering and Typography: Mastering Text Styling, Custom Fonts, and Rich Text

Flutter Text Rendering and Typography: Mastering Text Styling, Custom Fonts, and Rich Text

Flutter Text Rendering and Typography: Mastering Text Styling, Custom Fonts, and Rich Text

Text is the foundation of most user interfaces. Whether you're displaying a simple label, a paragraph of content, or complex formatted text, Flutter provides powerful tools to make your text look exactly how you want it. In this article, we'll explore Flutter's text rendering capabilities, from basic styling to custom fonts and rich text formatting.

Understanding the Text Widget

The Text widget is Flutter's primary way to display strings. At its simplest, it's just a string wrapped in a widget:


Text('Hello, Flutter!')

But the Text widget accepts a style parameter that opens up a world of customization possibilities through the TextStyle class.

Text Widget Structure Text Widget TextStyle

Basic Text Styling with TextStyle

TextStyle allows you to control virtually every aspect of how your text appears. Let's look at the most commonly used properties:


Text(
  'Styled Text Example',
  style: TextStyle(
    fontSize: 24.0,
    fontWeight: FontWeight.bold,
    color: Colors.blue,
    letterSpacing: 1.2,
    wordSpacing: 2.0,
    height: 1.5,
  ),
)

Here's what each property does:

  • fontSize: Controls the size of the text in logical pixels
  • fontWeight: Sets the thickness (normal, bold, w100-w900)
  • color: The text color
  • letterSpacing: Space between individual characters
  • wordSpacing: Space between words
  • height: Line height multiplier (1.0 is normal, 1.5 adds 50% extra space)
TextStyle Properties fontSize fontWeight color letterSpacing wordSpacing height

Working with Font Families

By default, Flutter uses the system font (Roboto on Android, San Francisco on iOS). You can change this by specifying a fontFamily:


Text(
  'Custom Font',
  style: TextStyle(
    fontFamily: 'Georgia',
    fontSize: 20.0,
  ),
)

However, to use custom fonts, you need to add them to your project. Here's how:

Adding Custom Fonts to Your Project

First, create a fonts folder in your project root and add your font files (typically .ttf or .otf files). Then, update your pubspec.yaml:


flutter:
  fonts:
    - family: CustomFont
      fonts:
        - asset: fonts/CustomFont-Regular.ttf
        - asset: fonts/CustomFont-Bold.ttf
          weight: 700
        - asset: fonts/CustomFont-Italic.ttf
          style: italic

After adding fonts, run flutter pub get and restart your app. Then you can use your custom font:


Text(
  'Using Custom Font',
  style: TextStyle(
    fontFamily: 'CustomFont',
    fontSize: 18.0,
    fontWeight: FontWeight.bold,
  ),
)

Text Alignment and Overflow

When text doesn't fit in its container, Flutter provides several ways to handle it:


Text(
  'This is a very long text that might overflow its container',
  maxLines: 2,
  overflow: TextOverflow.ellipsis,
  textAlign: TextAlign.center,
)

The overflow property offers several options:

  • TextOverflow.clip: Cuts off the text (default)
  • TextOverflow.ellipsis: Shows "..." at the end
  • TextOverflow.fade: Fades out the text
  • TextOverflow.visible: Allows text to overflow (may cause layout issues)
Text Overflow Handling Long text that exceeds container width... Long text that exceeds... ...

Rich Text and TextSpan

Sometimes you need different styles within a single text widget. That's where TextSpan and RichText come in:

RichText with TextSpan Structure RichText TextSpan TextSpan Normal TextSpan Bold

RichText(
  text: TextSpan(
    style: TextStyle(
      fontSize: 16.0,
      color: Colors.black,
    ),
    children: [
      TextSpan(
        text: 'Hello ',
        style: TextStyle(fontWeight: FontWeight.normal),
      ),
      TextSpan(
        text: 'Flutter',
        style: TextStyle(
          fontWeight: FontWeight.bold,
          color: Colors.blue,
        ),
      ),
      TextSpan(
        text: '!',
        style: TextStyle(fontStyle: FontStyle.italic),
      ),
    ],
  ),
)

You can also make parts of the text interactive by wrapping TextSpan with a GestureRecognizer:


RichText(
  text: TextSpan(
    children: [
      TextSpan(text: 'Visit '),
      TextSpan(
        text: 'flutter.dev',
        style: TextStyle(
          color: Colors.blue,
          decoration: TextDecoration.underline,
        ),
        recognizer: TapGestureRecognizer()
          ..onTap = () {
            // Handle tap
          },
      ),
    ],
  ),
)

Text Themes and Consistent Styling

For consistent styling across your app, Flutter provides text themes. You can define them in your app's theme:


MaterialApp(
  theme: ThemeData(
    textTheme: TextTheme(
      displayLarge: TextStyle(
        fontSize: 32.0,
        fontWeight: FontWeight.bold,
      ),
      bodyLarge: TextStyle(
        fontSize: 16.0,
        height: 1.5,
      ),
      labelSmall: TextStyle(
        fontSize: 12.0,
        color: Colors.grey,
      ),
    ),
  ),
  home: MyHomePage(),
)

Then use the theme styles in your widgets:


Text(
  'Themed Text',
  style: Theme.of(context).textTheme.displayLarge,
)

Advanced Typography: TextPainter and Custom Rendering

For advanced use cases, you might need to measure text or render it manually. TextPainter provides this capability:


final textPainter = TextPainter(
  text: TextSpan(
    text: 'Measure this text',
    style: TextStyle(fontSize: 16.0),
  ),
  textDirection: TextDirection.ltr,
);

textPainter.layout();

final width = textPainter.width;
final height = textPainter.height;

This is useful when you need to know text dimensions before rendering, or when building custom text layouts.

Text Selection and Copying

By default, Text widgets don't allow selection. To enable text selection, use SelectableText:


SelectableText(
  'This text can be selected and copied',
  style: TextStyle(fontSize: 16.0),
)

For more control, you can use TextField with readOnly: true or implement custom selection behavior.

Internationalization and RTL Support

Flutter handles right-to-left (RTL) languages automatically when you set the text direction:


Text(
  'مرحبا',
  textDirection: TextDirection.rtl,
  style: TextStyle(fontSize: 18.0),
)

For proper internationalization, use Flutter's intl package and Localizations widget, which automatically handles text direction based on the locale.

Performance Considerations

When working with large amounts of text or frequently updating text widgets, keep these tips in mind:

  • Use const constructors for static text to avoid unnecessary rebuilds
  • Consider using Text.rich instead of multiple Text widgets when possible
  • For very long texts, use ListView with text items rather than a single large text widget
  • Cache TextStyle objects if you're reusing them frequently

// Good: const constructor
const Text('Static text')

// Good: cached TextStyle
class AppStyles {
  static const TextStyle heading = TextStyle(
    fontSize: 24.0,
    fontWeight: FontWeight.bold,
  );
}

Text('Heading', style: AppStyles.heading)

Common Text Rendering Issues and Solutions

Here are some common problems you might encounter and how to solve them:

Text Not Wrapping

If your text isn't wrapping, make sure the parent widget has a bounded width:


SizedBox(
  width: 200,
  child: Text(
    'This text will wrap within 200 pixels',
    softWrap: true,
  ),
)

Font Not Loading

If your custom font isn't appearing:

  • Check that the font file path in pubspec.yaml is correct
  • Run flutter clean and flutter pub get
  • Restart your app completely (hot reload won't pick up new fonts)
  • Verify the font family name matches exactly

Text Clipping

If text is being clipped unexpectedly, check your widget constraints and consider using FittedBox:


FittedBox(
  fit: BoxFit.scaleDown,
  child: Text(
    'Very long text that needs to fit',
    style: TextStyle(fontSize: 24.0),
  ),
)

Conclusion

Flutter's text rendering system is both powerful and flexible. From simple styled text to complex rich text with custom fonts, Flutter provides the tools you need to create beautiful, readable text in your applications. Remember to use text themes for consistency, leverage RichText for mixed styling, and always consider performance when working with large amounts of text.

As you build more Flutter apps, you'll find that understanding text rendering helps you create more polished and professional user interfaces. Don't hesitate to experiment with different styles, fonts, and layouts to find what works best for your specific use case.