🎨 nanocolor
A minimal, zero-dependency terminal color and text styling crate for Rust.

Part of the nano crate family — minimal, zero-dependency building blocks for CLI apps in Rust:
- nanocolor — terminal colors and styles
- nanospinner — terminal spinners
- nanoprogress — progress bars
ANSI 16-color support and common text styles through a chainable trait-based API — no heavy crates, no transitive dependencies, under 300 lines of code.
Motivation
Most Rust color crates (like colored, owo-colors, or yansi) are feature-rich but can pull in dependencies or offer more than you need. If all you want is simple foreground/background colors and a few text styles, those crates are overkill.
nanocolor solves this by providing the essentials and nothing more:
- Zero external dependencies (only
std) - Tiny footprint (< 300 LOC)
- Chainable trait-based API on
&strandString - Style any
Displaytype — integers, floats, booleans, chars - Conditional styling and decorative masking
- Automatic TTY detection
- Respects the NO_COLOR standard
Comparison
nanocolor is intentionally minimal. If you need 256-color, RGB, no_std, or advanced features like conditional closures and nested style wrapping, use yansi or owo-colors — they're great crates.
nanocolor is for when you just want colors and don't want to think about it.
| Feature | nanocolor |
yansi |
owo-colors |
colored |
|---|---|---|---|---|
| Zero dependencies | ✓ | ✓ | ✓ | ✗ |
| 16 ANSI colors | ✓ | ✓ | ✓ | ✓ |
| 256 / RGB colors | ✗ | opt-in | ✓ | ✓ |
| Text styles (10) | ✓ | ✓ | ✓ | ✓ (5) |
Style any Display type |
✓ | ✓ | ✓ | ✗ |
| Conditional per-value styling | ✓ | ✓ | ✗ | ✗ |
| Decorative masking | ✓ | ✓ | ✗ | ✗ |
| Global enable/disable | ✓ | ✓ | ✗ | ✓ |
| Auto TTY detection | ✓ | opt-in | ✗ | ✓ |
NO_COLOR support |
✓ | opt-in | ✗ | ✓ |
no_std support |
✗ | ✓ | ✓ | ✗ |
| Conditional closures | ✗ | ✓ | ✗ | ✗ |
| Wrap / linger quirks | ✗ | ✓ | ✗ | ✗ |
| Const style builders | ✗ | ✓ | ✗ | ✗ |
| Single file | ✓ | ✗ | ✗ | ✗ |
| Source lines of code | ~300 | ~1,200 | ~2,400 | ~1,100 |
Features
- 16 foreground colors (8 standard + 8 bright)
- 16 background colors (8 standard + 8 bright)
- 5 text styles: bold, dim, italic, underline, strikethrough + 5 more (blink, reverse, hidden, overline, rapid blink)
- Chainable API — combine colors and styles freely
- Works with
&str,String, and all primitive types (i32,f64,bool,char, etc.) style()helper for customDisplaytypes- Seamless
Displayintegration — use inprintln!,format!,write! - Conditional styling with
.whenever(bool)— disable styling per-value - Decorative masking with
.mask()— hide values when colors are off - Automatic TTY detection — ANSI codes are skipped when output is piped
- Global
enable()/disable()to override auto-detection from code NO_COLORenvironment variable support
Quick Start
Add nanocolor to your Cargo.toml:
[]
= "0.1.0"
use Colorize;
Usage
Foreground colors
use Colorize;
println!;
println!;
Background colors
println!;
println!;
Text styles
println!;
println!;
println!;
Chaining
Colors and styles can be chained in any order:
let styled = "important".red.on_white.bold.underline;
println!;
Works with String
let msg = Stringfrom;
println!;
Piped / non-TTY output
When stdout isn't a terminal (e.g. piped to a file or another program), nanocolor automatically skips ANSI codes and outputs plain text. No configuration needed.
You can also force colors off by setting the NO_COLOR environment variable:
NO_COLOR=1
Style any Display type
Integers, floats, booleans, and chars all support the same chainable API:
use Colorize;
println!;
println!;
println!;
println!;
For custom types that implement Display, use the style() helper:
use ;
;
println!;
Conditional styling with .whenever()
Disable styling on a per-value basis, independent of the global TTY/NO_COLOR state:
use Colorize;
let is_tty = true; // your own condition
println!;
// .whenever(false) always strips ANSI codes
println!; // prints "plain"
If .whenever() is called multiple times, the last call wins.
Decorative masking with .mask()
Mark decorative values (emoji, symbols) so they disappear when colors are off — keeping piped output clean:
use Colorize;
// When colors are on: "✓ passed"
// When colors are off: " passed" (the checkmark is hidden)
print!;
println!;
.mask() and .whenever() compose naturally:
use Colorize;
// Always hidden (whenever(false) forces styling off)
println!; // prints ""
// Shown only when colors are active
println!;
Global enable / disable
Override auto-detection from code — useful for CLI apps with a --no-color flag:
You can also force colors on with nanocolor::enable().
Available Colors
| Standard | Bright |
|---|---|
black() |
bright_black() |
red() |
bright_red() |
green() |
bright_green() |
yellow() |
bright_yellow() |
blue() |
bright_blue() |
magenta() |
bright_magenta() |
cyan() |
bright_cyan() |
white() |
bright_white() |
All colors have background variants with the on_ prefix (e.g. on_red(), on_bright_cyan()).
Available Styles
| Method | Effect |
|---|---|
bold() |
Bold text |
dim() |
Dimmed text |
italic() |
Italic text |
underline() |
Underlined text |
blink() |
Blinking text (terminal support varies) |
rapid_blink() |
Rapid blinking text (rarely supported) |
reverse() |
Swap foreground and background |
hidden() |
Invisible text (still takes space) |
strikethrough() |
Strikethrough text |
overline() |
Line above text (newer terminals) |
Contributing
Contributions are welcome. To get started:
- Fork the repository
- Create a feature branch (
git checkout -b my-feature) - Make your changes
- Run the tests:
cargo test - Submit a pull request
Please keep changes minimal and focused. This crate's goal is to stay small and dependency-free.
License
This project is licensed under the MIT License.