← Back to Articles

Flutter Text Styling and Rich Text: Creating Beautiful Typography

Flutter Text Styling and Rich Text: Creating Beautiful Typography

Flutter Text Styling and Rich Text: Creating Beautiful Typography

Typography is one of the most fundamental aspects of user interface design. In Flutter, text isn't just about displaying words—it's about creating visual hierarchy, conveying meaning, and making your app feel polished and professional. Whether you're building a simple label or a complex document with multiple styles, Flutter provides powerful tools to style your text exactly how you want it.

In this article, we'll explore how to style text in Flutter, from basic formatting to creating rich, multi-style text blocks. You'll learn about the Text widget, TextStyle, RichText, TextSpan, and how to combine them to create beautiful typography in your Flutter apps.

Understanding the Text Widget

The Text widget is your starting point for displaying text in Flutter. At its simplest, it just displays a string:

Text Widget Structure Text Widget TextStyle data: String style: TextStyle

Text('Hello, Flutter!')

But the Text widget accepts a style parameter that opens up a world of customization possibilities. Let's look at how to use TextStyle to control the appearance of your text.

Basic Text Styling with TextStyle

TextStyle is a class that defines how text should be rendered. You can control almost every aspect of text appearance, from size and color to weight and decoration. Here's a basic example:


Text(
  'Styled Text',
  style: TextStyle(
    fontSize: 24,
    fontWeight: FontWeight.bold,
    color: Colors.blue,
    letterSpacing: 1.2,
  ),
)
TextStyle Properties TextStyle fontSize fontWeight color decoration letterSpacing height fontStyle fontFamily

Let's break down the most commonly used TextStyle properties:

  • fontSize: Controls the size of the text (in logical pixels)
  • fontWeight: Sets how bold the text appears (FontWeight.normal, FontWeight.bold, FontWeight.w100 through FontWeight.w900)
  • color: Sets the text color
  • letterSpacing: Adds space between individual characters
  • wordSpacing: Adds space between words
  • height: Controls the line height as a multiplier of fontSize
  • decoration: Adds decorations like underline, overline, or line-through
  • decorationColor: Sets the color of text decorations
  • decorationStyle: Sets the style of decorations (solid, double, dotted, dashed, wavy)
  • fontStyle: Sets italic or normal
  • fontFamily: Specifies a custom font family

Here's a more comprehensive example showing various text styles:


Column(
  crossAxisAlignment: CrossAxisAlignment.start,
  children: [
    Text(
      'Bold and Large',
      style: TextStyle(
        fontSize: 32,
        fontWeight: FontWeight.bold,
        color: Colors.deepPurple,
      ),
    ),
    SizedBox(height: 16),
    Text(
      'Italic with Underline',
      style: TextStyle(
        fontSize: 18,
        fontStyle: FontStyle.italic,
        decoration: TextDecoration.underline,
        decorationColor: Colors.orange,
        decorationStyle: TextDecorationStyle.wavy,
      ),
    ),
    SizedBox(height: 16),
    Text(
      'Custom Letter Spacing',
      style: TextStyle(
        fontSize: 20,
        letterSpacing: 3.0,
        color: Colors.teal,
      ),
    ),
    SizedBox(height: 16),
    Text(
      'Line Height Control',
      style: TextStyle(
        fontSize: 16,
        height: 2.0,
        color: Colors.grey[700],
      ),
    ),
  ],
)

Working with Rich Text

Sometimes you need different styles within a single text block. For example, you might want one word to be bold while the rest is normal, or you might want to mix colors within a sentence. This is where RichText and TextSpan come in.

RichText with TextSpan Hierarchy RichText TextSpan (default style) TextSpan (bold style) TextSpan (italic style)

RichText allows you to create text with multiple styles by using TextSpan widgets. Each TextSpan can have its own TextStyle, and you can nest spans to create complex formatting:


RichText(
  text: TextSpan(
    style: TextStyle(
      fontSize: 16,
      color: Colors.black,
    ),
    children: [
      TextSpan(text: 'This is '),
      TextSpan(
        text: 'bold',
        style: TextStyle(
          fontWeight: FontWeight.bold,
          color: Colors.blue,
        ),
      ),
      TextSpan(text: ' and this is '),
      TextSpan(
        text: 'italic',
        style: TextStyle(
          fontStyle: FontStyle.italic,
          color: Colors.red,
        ),
      ),
      TextSpan(text: '.'),
    ],
  ),
)

Notice that the first TextSpan defines a default style that applies to all children unless overridden. This is a common pattern that keeps your code DRY (Don't Repeat Yourself).

Text Widget with TextSpan

The Text widget actually has a convenient constructor that accepts TextSpan directly, making it even easier to create rich text:


Text.rich(
  TextSpan(
    children: [
      TextSpan(
        text: 'Price: ',
        style: TextStyle(fontSize: 16),
      ),
      TextSpan(
        text: '\$99.99',
        style: TextStyle(
          fontSize: 24,
          fontWeight: FontWeight.bold,
          color: Colors.green,
        ),
      ),
    ],
  ),
)

This approach is cleaner when you're already using a Text widget and want to add rich formatting without switching to RichText.

Creating Reusable Text Styles

In a real application, you'll want to maintain consistency across your app. Instead of defining TextStyle everywhere, create reusable text styles. The best way to do this is through your app's theme:


MaterialApp(
  theme: ThemeData(
    textTheme: TextTheme(
      displayLarge: TextStyle(
        fontSize: 32,
        fontWeight: FontWeight.bold,
        color: Colors.black87,
      ),
      displayMedium: TextStyle(
        fontSize: 28,
        fontWeight: FontWeight.bold,
        color: Colors.black87,
      ),
      headlineMedium: TextStyle(
        fontSize: 24,
        fontWeight: FontWeight.w600,
        color: Colors.black87,
      ),
      bodyLarge: TextStyle(
        fontSize: 16,
        color: Colors.black87,
      ),
      bodyMedium: TextStyle(
        fontSize: 14,
        color: Colors.black87,
      ),
      labelLarge: TextStyle(
        fontSize: 14,
        fontWeight: FontWeight.w500,
        color: Colors.blue,
      ),
    ),
  ),
  home: MyHomePage(),
)

Then you can use these styles throughout your app:


Text(
  'Heading',
  style: Theme.of(context).textTheme.headlineMedium,
)

Text(
  'Body text',
  style: Theme.of(context).textTheme.bodyLarge,
)

This approach ensures consistency and makes it easy to update your app's typography globally.

Advanced Text Styling Techniques

Text Overflow and Ellipsis

When text is too long to fit in its container, you can control how it's displayed:


Text(
  'This is a very long text that might overflow',
  overflow: TextOverflow.ellipsis,
  maxLines: 2,
  style: TextStyle(fontSize: 16),
)

The TextOverflow enum provides several options:

  • ellipsis: Truncates text with "..."
  • clip: Cuts off text at the edge
  • fade: Fades out text at the edge
  • visible: Allows text to overflow (default)

Text Alignment

You can align text within its container using the textAlign property:


Text(
  'Centered text',
  textAlign: TextAlign.center,
  style: TextStyle(fontSize: 16),
)

Available alignment options include: TextAlign.left, TextAlign.right, TextAlign.center, TextAlign.justify, and TextAlign.start/end (which respect text direction).

Text Direction

For internationalization, you can control text direction:


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

Custom Fonts

To use custom fonts in your Flutter app, you need to:

  1. Add font files to your project (typically in a fonts/ directory)
  2. Declare them in your pubspec.yaml
  3. Reference them in your TextStyle

First, add fonts to pubspec.yaml:


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

Then use it in your TextStyle:


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

Text Selection and Interaction

By default, Text widgets are not selectable. To make text selectable, use SelectableText:


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

SelectableText also supports rich text with TextSpan:


SelectableText.rich(
  TextSpan(
    children: [
      TextSpan(
        text: 'Selectable ',
        style: TextStyle(color: Colors.black),
      ),
      TextSpan(
        text: 'rich text',
        style: TextStyle(
          fontWeight: FontWeight.bold,
          color: Colors.blue,
        ),
      ),
    ],
  ),
)

Practical Example: Styled Article Preview

Let's put it all together with a practical example—a styled article preview card:


Card(
  child: Padding(
    padding: EdgeInsets.all(16),
    child: Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Text(
          'Flutter Text Styling Guide',
          style: TextStyle(
            fontSize: 24,
            fontWeight: FontWeight.bold,
            color: Colors.black87,
          ),
        ),
        SizedBox(height: 8),
        Text.rich(
          TextSpan(
            children: [
              TextSpan(
                text: 'Published on ',
                style: TextStyle(
                  fontSize: 14,
                  color: Colors.grey[600],
                ),
              ),
              TextSpan(
                text: 'March 15, 2024',
                style: TextStyle(
                  fontSize: 14,
                  fontWeight: FontWeight.w500,
                  color: Colors.grey[800],
                ),
              ),
            ],
          ),
        ),
        SizedBox(height: 12),
        Text(
          'Learn how to create beautiful typography in your Flutter apps using Text widgets, TextStyle, and RichText...',
          style: TextStyle(
            fontSize: 16,
            height: 1.5,
            color: Colors.black87,
          ),
          maxLines: 3,
          overflow: TextOverflow.ellipsis,
        ),
        SizedBox(height: 12),
        Wrap(
          spacing: 8,
          children: [
            Chip(
              label: Text(
                'Flutter',
                style: TextStyle(fontSize: 12),
              ),
            ),
            Chip(
              label: Text(
                'Typography',
                style: TextStyle(fontSize: 12),
              ),
            ),
          ],
        ),
      ],
    ),
  ),
)

Best Practices

Here are some tips for working with text styling in Flutter:

  • Use theme-based styles: Define your text styles in your theme for consistency and easy maintenance
  • Consider accessibility: Ensure sufficient contrast between text and background colors
  • Respect platform conventions: Use Material or Cupertino text styles that match the platform
  • Optimize performance: Reuse TextStyle objects rather than creating new ones repeatedly
  • Test with long text: Always test your text widgets with long strings to ensure proper overflow handling
  • Consider internationalization: Use textDirection and ensure your layouts work with RTL languages

Common Pitfalls to Avoid

When styling text in Flutter, watch out for these common mistakes:

  • Forgetting default styles: When using RichText, remember to set a default TextStyle in the parent TextSpan
  • Hardcoding colors: Use theme colors instead of hardcoded values for better theming support
  • Ignoring overflow: Always consider what happens when text is too long for its container
  • Inconsistent spacing: Use consistent fontSize, height, and spacing values throughout your app
  • Overcomplicating: Sometimes a simple Text widget is better than complex RichText structures

Conclusion

Text styling in Flutter is both powerful and flexible. Whether you need simple formatted text or complex multi-style content, Flutter provides the tools you need. By understanding TextStyle, RichText, and TextSpan, you can create beautiful typography that enhances your app's user experience.

Remember to leverage your app's theme for consistency, test with various text lengths, and always consider accessibility. With these tools and best practices, you'll be able to create text that's not just readable, but visually appealing and professional.

Start experimenting with different text styles in your Flutter apps. Try creating a style guide for your app, implement rich text formatting in your content, and see how proper typography can transform the look and feel of your user interface.