mb_strwidth
Returns the display width of a string, counting fullwidth characters as two columns.
mb_strwidth(string $string, ?string $encoding = null): int- Added in PHP 4.0.6
Parameters
| Parameter | Type | Description |
|---|---|---|
$string | string | The string being measured. |
$encodingoptional | ?string= null | Character encoding of the string. Falls back to the internal encoding when null. |
Return value
intThe width of the string, where fullwidth characters count as 2 and all others count as 1.
Errors
Throws a ValueError if encoding names an unknown character encoding.
Changelog
- PHP 8.0.0encoding is nullable now.
PHP gives you three different answers to "how long is this string". strlen() counts bytes, mb_strlen() counts characters, and mb_strwidth() counts display columns in a monospaced font. CJK ideographs, kana, Hangul syllables and fullwidth punctuation occupy two columns each; everything else occupies one.
When to reach for it
Reach for it whenever you are aligning text in a fixed-width context: CLI tables, log output, fixed-pitch reports, ASCII-art boxes, plain-text emails. str_pad() and printf()'s %-10s pad by bytes, so a UTF-8 name will always come out short by however many extra bytes it uses. Compute the padding yourself from mb_strwidth(), or use mb_str_pad().
What trips people up
Width is decided by a fixed table of Unicode ranges baked into mbstring, not by the font you are actually rendering with. Combining marks are counted as one column even though they render on top of the previous character, and emoji outside the listed ranges count as one column even though most terminals draw them two wide. Do not treat the result as a pixel measurement for proportional fonts — it is meaningless there.
To truncate to a column budget rather than measure it, use mb_strimwidth(), which understands the same width model.
Example
When to use it
- Align a CLI table whose rows mix Japanese and Latin labels.
- Truncate a headline to fit a fixed number of terminal columns.
- Pad fixed-width report fields that may contain Chinese product names.
- Decide whether a log line will wrap in an 80-column terminal.
Frequently asked questions
What is the difference between mb_strlen and mb_strwidth?
mb_strlen counts characters, mb_strwidth counts display columns in a monospaced font. They differ whenever the string contains fullwidth characters such as CJK ideographs or kana, which count as one character but two columns.
Does mb_strwidth handle emoji correctly?
Only partly. Width comes from a fixed table of Unicode ranges, and most emoji fall outside those ranges, so they are counted as one column even though terminals usually draw them two wide.
How do I pad a UTF-8 string to a fixed width?
Use mb_str_pad() to pad by characters, or compute the padding yourself as str_repeat(' ', $target - mb_strwidth($s)) to pad by display columns. str_pad() pads by bytes and will always be wrong for multibyte text.
More examples
Truncating to a column budget
mb_strimwidth cuts the title so the result including the ellipsis fits in 10 columns — it prints 9 because the next ideograph would have pushed it to 11. The last two lines show halfwidth katakana counting as 1 column each while fullwidth katakana count as 2, and that plain accented Latin text is width 4 for 4 characters.
<?php
$title = "東京都の天気予報";
echo mb_strimwidth($title, 0, 10, "…"), "\n";
echo mb_strwidth(mb_strimwidth($title, 0, 10, "…")), "\n";
echo mb_strwidth("アイウ"), " vs ", mb_strwidth("アイウ"), "\n";
echo mb_strwidth("café"), "\n";Why str_pad gets it wrong
str_pad pads to 8 bytes and "寿司" already uses 6, so it adds only two spaces and the column breaks. mb_str_pad pads to 8 characters instead. The final line shows all three measurements — 6 bytes, 2 characters, 4 display columns — which is why you must pick the right one for the job.
<?php
$name = "寿司";
echo "[", str_pad($name, 8), "]\n";
echo "[", mb_str_pad($name, 8), "]\n";
echo strlen($name), " ", mb_strlen($name), " ", mb_strwidth($name), "\n";
Discussion