ANSI color library for use in terminals, CI environments, and Chromium-based browsers.
Ansis is focused on small size and speed while providing rich functionality and handling edge cases.
// Named imports - for cleaner, more readable code
import { red, cyan, bold, hex, rgb } from 'ansis';
// Clean chained syntax with template literals - no extra parentheses
console.log(bold.bgRed` FAIL `);
// Nested templates - no string concatenation needed
console.log(red`✖ Error: ${cyan`file.js`} not found`);
// Truecolor: hex and rgb
console.log(hex('#FF75D1').bold`Pink`);
console.log(rgb(224, 17, 95).italic`Ruby`);⭐️ Star History
🎨 Colors - 16 · 256 · Truecolor (hex/rgb) · Named colors (orange, pink ...)
✍️ Syntax - Chained · Template literals · Nested templates
⚙️ Works - ESM · CJS · TS · Node 10+ · Bun · Deno · CI · Chromium browsers
🧠 Smart - Auto color detection · Fallback (truecolor → 256 → 16 → b&w) · NO_COLOR · FORCE_COLOR
📦 Tiny - 5.8 kB · Drop-in replacement for Chalk (44 kB)
Ansis is the fastest when using 2 or more styles, which is the common real-world use case.
| Library | 1 style | 2+ styles |
|---|---|---|
ansis |
60M ops/sec | 🏆 60M ops/sec |
picocolors |
🏆 109M ops/sec | 58M ops/sec |
chalk |
55M ops/sec | 47M ops/sec |
util.styleText |
0.5M ops/sec | 0.5M ops/sec |
🎨 Colors & Styles
- ANSI styles:
dimbolditalicunderline...strikethrough - ANSI 16 colors:
redredBrightbgRedbgRedBright... - ANSI 256 colors:
fg(n)bg(n) - Truecolor:
hex('#FF75D1')rgb(224, 17, 95)bgHex()bgRgb() - Named truecolors:
orange()bgPink()... - viaextend()
✍️ Syntax
- Chained styles:
red.bold.underline- no nested calls likered(bold(underline())) - Template literals:
red`text`- no parentheses - Nested templates:
red`Error: ${cyan`file.js`} not found`- no string concatenations
🛠️ Utilities
- Strip ANSI codes:
ansis.strip(red('text'))→ plain'text' - Raw escape codes:
open/close-`${red.open}Error${red.close} file not found`
💻 Environment
- Auto color detection + Fallback: Truecolor → 256 → 16 → b&w
- ENV variables:
NO_COLORFORCE_COLORCOLORTERM - CLI flags:
--no-color--color - CLI testing: force color levels in tests
⚙️ Compatibility
- ESM · CJS · TypeScript · Bun · Deno · Next.js · CI (GitHub and others)
- Chromium browsers: Chrome · Edge · Opera · Brave · Vivaldi
- Drop-in replacement for
chalkansi-colorscoloretteand others
🎯 You might also like
flaget- CLI argument parsing. A smaller (5 kB) and faster alternative toyargs-parser(85 kB)HTML bundler- Plugin for Webpack to generate static sites from templates (html, ejs, hbs, pug, ...)
chalk, picocolors, colorette, kleur, ansi-colors, kolorist, cli-color, colors-cli, colors.js, tinyrainbow
Since Node.js 22 supports ANSI styling natively via util.styleText(), it is recommended for simple use cases where 16 colors are enough and top performance is not critical.
See styleText() limitations.
✅ Compare features 📊 Benchmarks 🧩 Handling edge cases
npm install ansis
For Node.js 10–12+ use special build
npm install ansis@node10
ESM
import ansis, { red, bold, fg, hex, rgb } from 'ansis';CJS
const ansis = require('ansis');
const { red, bold, fg, hex, rgb } = require('ansis');All colors, styles and functions are chainable. Each color or style can be combined in any order.
import { red, bold, hex } from 'ansis';
red.bold`text`;
hex('#FF75D1').bgCyan.bold`text`;
bold.hex('#FF75D1').bgCyan`text`;Omit parentheses to keep your code clean:
import { red, yellow, green } from 'ansis';
red`Error`; // no parentheses
red`Red ${yellow`Yellow ${green`Green`} Yellow`} Red`; // deep nested templatesEscape sequences work exactly as in regular strings:
red`Hello\nWorld`; // two lines in red
red`prev\\next`; // one line: prev\nextdim bold italic underline strikethroughinverse visible hidden reset
There are 16 basic colors: 8 standard and 8 bright variants.
- Foreground:
fg(code)-chalk.ansi256(code)equivalent - Background:
bg(code)-chalk.bgAnsi256(code)equivalent
import { bold, fg, bg } from 'ansis';
fg(96)`Bright Cyan`;
bg(105).fg(96)`Cyan text on magenta background`;
bold.fg(96).underline`Bold underline Bright Cyan`;See ANSI color codes.
If a terminal supports only 16 colors then ANSI 256 colors will be interpolated into base 16 colors.
- Foreground:
hex()rgb() - Background:
bgHex()bgRgb()
import { bold, hex, rgb, bgHex } from 'ansis';
hex('#E0115F').bold`Bold Ruby`;
rgb(224, 17, 95).italic`Italic Ruby`;
bold.hex('#E0115F').bgHex('#96C')`Ruby text on amethyst background`;See also named truecolors.
Ansis automatically interpolates to the best available color level.
Truecolor → 256 colors → 16 colors → no colors (b&w)
Register any hex color as a named style via extend().
Background methods bg* are generated automatically.
import ansis from 'ansis';
const myTheme = {
orange: '#ffa500',
pink: '#ffc0cb',
};
const color = ansis.extend(myTheme);
color.orange.bold`orange bold`; // extended first in chain
color.bgOrange`orange background`; // auto-generated bg
color.pink`pink foreground`;
color.bgPink`pink background`; // auto-generated bg
color.red`built-in red still works`; // built-in remains intactWarning
Put extended colors first in the chain: color.orange.bold ✅ color.bold.orange ❌
Tip
For all CSS named colors use css-color-names package.
Example: extend with CSS color names
import ansis from 'ansis';
import colorNames from 'css-color-names'; // { pink: '#ffc0cb', orange: '#ffa500', ... }
const color = ansis.extend(colorNames);
color.pink('Pink foreground');
color.bgPink('Pink background'); // auto-generated bgTip
Need help picking a color name? Try the Name that Color tool - paste a hex and get its closest color name.
Ansis automatically detects the supported color level:
0– No color1– Basic ANSI (16 colors)2– Extended ANSI (256 colors)3– Truecolor (16 million colors)
Check the detected level at runtime:
import ansis from 'ansis';
console.log(ansis.level); // 0 | 1 | 2 | 3
console.log(ansis.isSupported()); // true -> level >= 1 (at least 16 colors supported)To override the detected level, create an instance of Ansis directly with the desired level:
import { Ansis } from 'ansis';
const noColor = new Ansis(0); // always plain text, no ANSI codes
const basic = new Ansis(1); // 16 colors; hex/rgb fall back to nearest
const auto = new Ansis(); // auto-detect (same as default import)
console.log(noColor.red`foo`); // plain text, no ANSI codes
console.log(basic.hex('#FFAB40')`Orange`); // falls back to yellowBrightExample: disable colors via custom CLI flag, e.g. --save-to-log
import { Ansis } from 'ansis';
/**
* Ansis instance for CLI that can be initialized with no colors mode
* needed for outputs where we don't want to have colors.
*
* @param {boolean} noColors Disable colors
* @return {Ansis} Default or custom instance
*/
function safeAnsis(noColors) {
return noColors
? new Ansis(0) // disable colors
: new Ansis(); // auto detect color support
}
// handle a special CLI flag to disable colors
const ansis = safeAnsis(process.argv.includes('--save-to-log'))Ansis detects color support from the terminal environment automatically:
- Reads
TERMandCOLORTERMenvironment variables - In CI environments, checks
CIand assumes at least 16 colors GitHub Actionsis explicitly detected as truecolor
Supported terminals and CI environments
| Terminal | ANSI 16 colors |
ANSI 256 colors |
True Color |
env. TERM |
env. COLORTERM |
Specifically ENV variables |
|---|---|---|---|---|---|---|
| Azure CI | ✅ | ❌ | ❌ | dumb | TF_BUILD AGENT_NAME |
|
| GitHub CI | ✅ | ✅ | ✅ | dumb | CI, GITHUB_ACTIONS | |
| GitTea CI | ✅ | ✅ | ✅ | dumb | CI, GITEA_ACTIONS | |
| GitLab CI | ✅ | ❌ | ❌ | dumb | CI, GITLAB_CI | |
| Travis CI | ✅ | ❌ | ❌ | dumb | TRAVIS | |
| PM2 not isTTY |
✅[^1] | ✅[^1] | ✅[^1] | dumb | PM2_HOME pm_id |
|
| JetBrains TeamCity >=2020.1.1 |
✅ | ✅ | ❌ | TEAMCITY_VERSION | ||
| JetBrains IDEA | ✅ | ✅ | ✅ | xterm-256color | TERMINAL_EMULATOR='JetBrains-JediTerm' | |
| VS Code | ✅ | ✅ | ✅ | xterm-256color | truecolor | |
| Windows Terminal |
✅ | ✅ | ✅[^2] | |||
| Windows PowerShell |
✅ | ✅ | ✅[^2] | |||
| macOS Terminal | ✅ | ✅ | ❌ | xterm-256color | ||
| iTerm | ✅ | ✅ | ✅ | xterm-256color | truecolor | |
| Kitty | ✅ | ✅ | ✅ | xterm-kitty | truecolor | |
| KDE Konsole | ✅ | ✅ | ✅ | xterm-256color | truecolor |
- ^1 Colors supported depends on actual terminal.
- ^2: The Windows terminal supports true color since Windows 10 revision 14931 (2016-09-21).
See also:
Ansis supports the following environment variables and CLI flags.
Set to any non-empty value (1, true) to disable color output (no-color.org):
NO_COLOR=1 node app.jsForce a specific color level regardless of terminal support (force-color.org):
| Value | Behavior |
|---|---|
0 or false |
Disable colors (level 0) |
1 |
Enable 16 colors (level 1) |
2 |
Enable 256 colors (level 2) |
3 |
Enable truecolor (level 3) |
true or (unset) |
Auto-detect with fallback to 16 colors if nothing detected |
Important
In Node.js FORCE_COLOR=true and FORCE_COLOR=1 both enable 16 colors.
In Ansis, the value 1 means level 1 and strictly set 16 colors, while true triggers auto-detection.
Hint the color level via terminal emulator convention:
| Value | Level |
|---|---|
ansi |
16 colors (level 1) |
ansi256 |
256 colors (level 2) |
truecolor or 24bit |
Truecolor (level 3) |
Pass --no-color or --color directly to your script:
./app.js # auto-detect
./app.js --no-color # disable colors
./app.js --color # force colors (useful when piping output)Note
CLI flags take precedence over environment variables.
node app.js # auto-detect
node app.js > log.txt # no colors (non-TTY)
NO_COLOR=1 node app.js # force off
FORCE_COLOR=0 node app.js # force off
FORCE_COLOR=1 node app.js > log.txt # force 16 colors
FORCE_COLOR=2 node app.js > log.txt # force 256 colors
FORCE_COLOR=3 node app.js > log.txt # force truecolor
node app.js --no-color # disable via flag
node app.js --color > log.txt # enable via flagAnsis and Chalk add a style break at each new line to correctly display multi-line text.
However, Picocolors doesn't handle this case.
ansis.bgRed('\n ERROR \n') + ansis.cyan('The file not found!') // ✅
chalk.bgRed('\n ERROR \n') + chalk.cyan('The file not found!') // ✅
pico.bgRed('\n ERROR \n') + pico.cyan('The file not found!') // ❌Only Ansis handles this very useful use case.
ansis.red`R ${ansis.green`G ${ansis.blue`B`} G`} R` // ✅
chalk.red`R ${chalk.green`G ${chalk.blue`B`} G`} R` // ❌
pico.red`R ${pico.green`G ${pico.blue`B`} G`} R` // ❌Compare how different libraries handle various input arguments in their functions.
ansis.red() // ✅ ''
chalk.red() // ✅ ''
pico.red() // ❌ \e[31mundefined\e[39m
ansis.red(undefined) // ✅ ''
chalk.red(undefined) // ❌ \e[31mundefined\e[39m
pico.red(undefined) // ❌ \e[31mundefined\e[39m
ansis.red(null) // ✅ ''
chalk.red(null) // ❌ \e[31mnull\e[39m
pico.red(null) // ❌ \e[31mnull\e[39m
ansis.red('') // ✅ ''
chalk.red('') // ✅ ''
pico.red('') // ❌ \e[31m\e[39m
ansis.reset() // ✅ \e[0m
chalk.reset() // ❌ ''
pico.reset() // ❌ \e[0mundefined\e[0m| Library | c.reset() |
c.red() |
c.red(undefined) |
c.red(null) |
c.red('') |
|---|---|---|---|---|---|
ansis |
✅\e[0m |
✅'' |
✅'' |
✅'' |
✅'' |
chalk |
❌'' |
✅'' |
❌'undefined' |
❌'null' |
✅'' |
picocolors |
❌undefined |
❌'undefined' |
❌'undefined' |
❌'null' |
❌'ESC' |
tinyrainbow |
❌undefined |
❌'undefined' |
❌'undefined' |
❌'null' |
❌'ESC' |
colorette |
❌'' |
✅'' |
✅'' |
❌'null' |
✅'' |
kleur |
❌[object] |
❌[object] |
❌[object] |
❌'null' |
❌'ESC' |
ansi-colors |
❌'' |
✅'' |
✅'' |
✅'' |
✅'' |
kolorist |
❌undefined |
❌'undefined' |
❌'undefined' |
❌'null' |
❌'ESC' |
colors.js |
❌'' |
✅'' |
❌'undefined' |
❌'null' |
✅'' |
cli-color |
❌- |
❌'ESC' |
❌'ESC' |
❌'ESC' |
❌'ESC' |
colors-cli |
❌- |
❌ Error |
❌'undefined' |
❌'null' |
❌'ESC' |
- ✅
''- Returns an empty string without ANSI escape codes. This is the correct and expected behavior. - ✅
\e[0m- Returns the reset escape code. - ❌
'ESC'- Returns an empty string containing ANSI escape codes, e.g.,\e[31m\e[39m. - ❌
'undefined'- Returns the styled stringundefined. - ❌
'null'- Returns the styled stringnull. - ❌
[object]- Returns an object of the library instance. - ❌
-- The feature is not supported. - ❌
Error- Causes a fatal error.
Other arguments are correctly handled by all libraries:
c.red(0) // '0' in red
c.red(false) // 'false' in red
c.red(true) // 'true' in red
c.red(5/'1px') // 'NaN' in red
c.red(1/0) // 'Infinity' in redSince Node v22, the built-in util.styleText()
has been officially introduced, supporting standard modifiers - the basic 16 colors and styles.
Ansis
✅ Node v10+
✅ Chromium-based browsers and Safari
styleText
✅ Node v22+ (native)
❌ Node only - no browser support
In practical benchmarks, styleText() is dramatically slower, 100x slower than Ansis:
ansis.red('text'); // 59.646.465 ops/sec
styleText('red', 'text'); // 579.832 ops/secSee full benchmarks.
Ansis
- Auto-detects terminal, TTY, CI and browser color support with automatic fallback
- Supports
NO_COLORFORCE_COLORCOLORTERM--no-color--color ansis.levelreturns the detected color level
styleText
- Auto-detects terminal color support
- Supports only
NO_COLORFORCE_COLORNODE_DISABLE_COLORS
import { green } from 'ansis';
import { styleText } from 'node:util';
green`Success!`; // ansis
styleText('green', 'Success!');
green.bold`Success!`; // ansis
styleText(['green', 'bold'], 'Success!');import { red, cyan } from 'ansis';
import { styleText } from 'node:util';
red`Error: ${cyan.bold`file.js`} not found!`; // ansis
styleText('red', `Error: ${styleText(['cyan', 'bold'], 'file.js')} not found!`);Ansis: hex() rgb()
styleText: Limited to 16 ANSI colors.
Check the minimum version of your tool required for compatibility with the latest Ansis.
| Tool | Version | Compatibility | Supports |
|---|---|---|---|
| Node.js | v14+ | ✅ Full support | CJS, ESM |
| Deno | v2.0+ | ✅ Full support | CJS, ESM |
| TypeScript/tsc | v5.0+ | ✅ Full support | CJS, ESM |
| esbuild | v0.8+ | ✅ Full support | CJS, ESM |
| swc | v1.2+ | ✅ Full support | CJS, ESM, FAUX |
| tsup | v4.0+ | ✅ Full support | CJS, ESM, FAUX |
| tsx | v3.0+ | ✅ Full support | CJS, ESM |
| Rollup | v2.0+ | ✅ Full support | CJS, ESM |
| Rolldown | v1.0.0-beta.8+ | ✅ Full support | CJS, ESM |
| Vite | v2.5+ | ✅ Full support | ESM |
| Turbo | v1.0+ | ✅ Full support | CJS, ESM |
| Webpack | v5.0+ | ✅ Full support | CJS, ESM |
Supports:
- CJS: CommonJS module support.
- ESM: ECMAScript module support.
- FAUX: Fake or non-standard approach to module resolution (seen in swc).
| Browser | Version | Colors Supported |
|---|---|---|
| Chrome | v20+ | TrueColor (16M) |
| Safari | v10+ | TrueColor (16M) |
| Edge | v12+ | TrueColor (16M) |
| Opera | v12+ | TrueColor (16M) |
| Brave | v1.0+ | TrueColor (16M) |
| Vivaldi | v1.0+ | TrueColor (16M) |
Warning
Firefox doesn't natively support ANSI codes in the developer console.
If you find this useful, please ⭐️ the repo.




















