skip_ink_underline

pub package CI License: MIT

A Flutter package that provides text underlines that intelligently skip descender letters (g, j, p, q, y), just like CSS text-decoration-skip: ink. Create beautiful, professional typography with a simple API and perfect auto defaults.


✨ Features

  • 🎨 Intelligent skip ink - Automatically skips descender letters.
  • Simple API - Drop-in replacement for the Text widget.
  • 🎯 Professional defaults - Beautiful results without configuration.
  • 🔧 Complete control - Fine-tune every aspect when needed.
  • 📱 Cross-platform - Works on iOS, Android, Web, Windows, macOS, and Linux.
  • 🎨 Per-character control - Customize skip ratios for each descender.
  • 📏 Distance & thickness control - Perfect spacing and appearance.

🚀 Installation

Add the following to your package's pubspec.yaml file:

dependencies:
    skip_ink_underline: ^1.0.0

Then run:

flutter pub get

💡 Quick Start

import 'package:skip_ink_underline/skip_ink_underline.dart';

// Instead of Text widget with underline:
Text(
    'Typography with g, j, p, q, y',
    style: TextStyle(decoration: TextDecoration.underline),
)

// Use SkipInkText:
SkipInkText(
    'Typography with g, j, p, q, y',
    style: TextStyle(decoration: TextDecoration.underline),
)

That's it! The package uses professional auto defaults that work perfectly out of the box.


Advanced Usage

SkipInkText(
    'Custom typography control',
    style: TextStyle(
        fontSize: 20,
        decoration: TextDecoration.underline,
        color: Colors.purple,
    ),
    // Distance control
    distance: 12, // Custom distance from baseline
    autoDistance: false, // Disable auto calculation

    // Thickness control
    thickness: 2.5, // Custom thickness
    autoThickness: false, // Disable auto calculation

    // Skip padding control
    leftSkip: 4, // Left gap around descenders
    rightSkip: 6, // Right gap around descenders
    autoSkipPadding: false, // Disable auto calculation

    // Per-character control
    gSkip: [0.1, 0.9], // Custom g skip ratios
    pSkip: [0.0, 0.4], // Partial underline for p
    ySkip: [0.25, 0.75], // Custom y skip ratios

    // Additional options
    underlineColor: Colors.purple,
    minSegmentLength: 3,
)

📖 API Reference

Parameters

Parameter Type Default Description
text String required The text to display.
style TextStyle required Text styling (decoration will be handled).
skipInk bool true Enable skip ink behavior.
distance double? null Manual distance from baseline.
autoDistance bool true Use automatic distance calculation.
thickness double? null Manual underline thickness.
autoThickness bool true Use automatic thickness calculation.
leftSkip double? null Left gap around descenders.
rightSkip double? null Right gap around descenders.
autoSkipPadding bool true Use automatic skip padding calculation.
gSkip List<double>? null Custom skip ratios for 'g' left%, right%.
jSkip List<double>? null Custom skip ratios for 'j' left%, right%.
pSkip List<double>? null Custom skip ratios for 'p' left%, right%.
qSkip List<double>? null Custom skip ratios for 'q' left%, right%.
ySkip List<double>? null Custom skip ratios for 'y' left%, right%.
underlineColor Color? null Custom underline color (default: text color).

🎨 Examples

Comparison

// Standard Flutter underline
Text(
    'Typography with g, j, p, q, y',
    style: TextStyle(decoration: TextDecoration.underline),
)

// Skip ink underline
SkipInkText(
    'Typography with g, j, p, q, y',
    style: TextStyle(decoration: TextDecoration.underline),
)

Custom Styling

// Purple thick underline with custom spacing
SkipInkText(
    'Beautiful purple typography',
    style: TextStyle(
        fontSize: 24,
        color: Colors.purple,
        decoration: TextDecoration.underline,
    ),
    underlineColor: Colors.purple,
    thickness: 3,
    distance: 10,
    autoThickness: false,
    autoDistance: false,
)

Per-Character Control

// Custom skip ratios for each descender
SkipInkText(
    'Custom skips for g, j, p, q, y',
    style: TextStyle(decoration: TextDecoration.underline),
    gSkip: [0.1, 0.9], // Almost full underline for g
    pSkip: [0.0, 0.4], // Partial underline for p
    ySkip: [0.25, 0.75], // Centered skip for y
)

🏗️ How It Works

The package uses Flutter's CustomPainter to draw intelligent underlines that:

  1. Analyze font metrics - Measures actual descender depths.
  2. Calculate skip zones - Determines where to break the underline.
  3. Render segments - Draws continuous underline segments between gaps.
  4. Optimize performance - Caches calculations and minimizes repaints.

🎯 Typography Best Practices

  1. Use auto mode for consistent, professional results.
  2. Enable skip ink for better readability.
  3. Match colors to your design system.
  4. Test on multiple sizes and orientations.
  5. Consider context - Headers vs. body text may need different settings.

🤝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

  1. Fork the repository.
  2. Create your feature branch (git checkout -b feature/amazing-feature).
  3. Commit your changes (git commit -m 'Add amazing feature').
  4. Push to the branch (git push origin feature/amazing-feature).
  5. Open a Pull Request.

📄 License

This project is licensed under the MIT License - see the LICENSE file for details.


🙏 Credits

Inspired by CSS text-decoration-skip: ink and modern typography best practices.


Made with ❤️ by MNBLabs

Libraries

skip_ink_underline
Skip ink underline for Flutter - like CSS text-decoration-skip: ink