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('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,
),
)
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 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:
- Add font files to your project (typically in a fonts/ directory)
- Declare them in your pubspec.yaml
- 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.