Get the visual width of a string - the number of columns required to display it in terminals
npx @tessl/cli install tessl/npm-string-width@8.1.00
# String Width
1
2
String Width is a JavaScript utility library that calculates the visual width of strings in terminal applications. It accurately accounts for Unicode characters that display at different widths, including fullwidth CJK characters, ANSI escape codes, and emoji sequences, making it essential for CLI tools and terminal applications that need proper text alignment.
3
4
## Package Information
5
6
- **Package Name**: string-width
7
- **Package Type**: npm
8
- **Language**: JavaScript (ES modules) with TypeScript definitions
9
- **Installation**: `npm install string-width`
10
11
## Core Imports
12
13
```javascript
14
import stringWidth from 'string-width';
15
```
16
17
For TypeScript with type imports:
18
19
```typescript
20
import stringWidth, { type Options } from 'string-width';
21
```
22
23
## Basic Usage
24
25
```javascript
26
import stringWidth from 'string-width';
27
28
// Basic ASCII string
29
stringWidth('hello world');
30
//=> 11
31
32
// Fullwidth CJK characters (display as 2 columns each)
33
stringWidth('古');
34
//=> 2
35
36
// Mixed content
37
stringWidth('hello世界');
38
//=> 9 (hello=5, 世=2, 界=2)
39
40
// ANSI escape codes are stripped by default
41
stringWidth('\u001B[1m古\u001B[22m');
42
//=> 2
43
44
// With options
45
stringWidth('±', { ambiguousIsNarrow: false });
46
//=> 2 (ambiguous character treated as wide)
47
```
48
49
## Capabilities
50
51
### Visual Width Calculation
52
53
Calculates the visual width of a string - the number of columns required to display it in a terminal.
54
55
```javascript { .api }
56
/**
57
* Get the visual width of a string - the number of columns required to display it
58
* @param string - The string to measure
59
* @param options - Configuration options
60
* @returns The visual width in columns
61
*/
62
function stringWidth(string: string, options?: Options): number;
63
```
64
65
The function handles:
66
- **ASCII characters**: Standard single-width characters (width = 1)
67
- **Fullwidth characters**: CJK characters, fullwidth forms (width = 2)
68
- **Zero-width characters**: Control characters, marks, default ignorable (width = 0)
69
- **Emoji sequences**: RGI emoji clusters (width = 2)
70
- **ANSI escape codes**: Stripped by default unless configured otherwise
71
- **Ambiguous characters**: Configurable treatment as narrow (1) or wide (2)
72
- **Grapheme clusters**: Proper segmentation using Intl.Segmenter
73
- **Halfwidth forms**: Correct handling of Japanese dakuten/handakuten marks
74
75
**Usage Examples:**
76
77
```javascript
78
import stringWidth from 'string-width';
79
80
// Edge cases and special characters
81
stringWidth(''); // => 0 (empty string)
82
stringWidth('\t'); // => 0 (tab ignored by design)
83
stringWidth('a\tb'); // => 2 (tab doesn't count)
84
stringWidth('\n'); // => 0 (newline is control char)
85
stringWidth('你好'); // => 4 (2 chars × 2 width each)
86
stringWidth('バ'); // => 2 (halfwidth + dakuten)
87
stringWidth('👨👩👧👦'); // => 2 (family emoji sequence)
88
stringWidth('🇺🇸'); // => 2 (flag emoji sequence)
89
stringWidth('👋🏽'); // => 2 (emoji with skin tone)
90
91
// Zero-width and combining characters
92
stringWidth('e\u0301'); // => 1 (combining diacritical mark)
93
stringWidth('\u200B'); // => 0 (zero-width space)
94
stringWidth('\u200C'); // => 0 (zero-width non-joiner)
95
stringWidth('\u200D'); // => 0 (zero-width joiner)
96
97
// Non-string inputs return 0
98
stringWidth(123); // => 0
99
stringWidth(null); // => 0
100
stringWidth(undefined); // => 0
101
102
// ANSI escape codes
103
const redText = '\u001B[31mRed\u001B[0m';
104
stringWidth(redText); // => 3 (ANSI codes stripped)
105
stringWidth(redText, { countAnsiEscapeCodes: true }); // => 11 (codes counted)
106
107
// Ambiguous characters
108
stringWidth('±§©®'); // => 4 (treated as narrow by default)
109
stringWidth('±§©®', { ambiguousIsNarrow: false }); // => 8 (treated as wide)
110
```
111
112
## Options
113
114
Configuration options for controlling width calculation behavior.
115
116
```typescript { .api }
117
interface Options {
118
/**
119
* Count ambiguous width characters as having narrow width (count of 1)
120
* instead of wide width (count of 2).
121
*
122
* Ambiguous characters behave like wide or narrow characters depending
123
* on context. If context cannot be established reliably, they should
124
* be treated as narrow characters by default.
125
*
126
* @default true
127
*/
128
readonly ambiguousIsNarrow?: boolean;
129
130
/**
131
* Whether ANSI escape codes should be counted towards the width.
132
* By default, ANSI codes are stripped and don't affect width calculation.
133
*
134
* @default false
135
*/
136
readonly countAnsiEscapeCodes?: boolean;
137
}
138
```
139
140
**Option Examples:**
141
142
```javascript
143
import stringWidth from 'string-width';
144
145
// Ambiguous character handling
146
const ambiguous = '±';
147
stringWidth(ambiguous); // => 1 (narrow)
148
stringWidth(ambiguous, { ambiguousIsNarrow: false }); // => 2 (wide)
149
150
// ANSI escape code handling
151
const colored = '\u001B[31mHello\u001B[0m';
152
stringWidth(colored); // => 5 (codes stripped)
153
stringWidth(colored, { countAnsiEscapeCodes: true }); // => 13 (codes counted)
154
155
// Combined options
156
stringWidth('±\u001B[31mTest\u001B[0m', {
157
ambiguousIsNarrow: false,
158
countAnsiEscapeCodes: true
159
}); // => 14 (± as wide + ANSI codes counted + Test)
160
```