The current behaviour seems to be by design, according to this unittest assert from Phobos (std.format#L5779):
assert(format("%8s", "b\u00e9ll\u00f4") == " b\u00e9ll\u00f4");
The length of the tested string is 8 (code points), but it prints 6 glyphs. I can't guess the rationale behind this, since the purpose is formatting.
*** This issue has been marked as a duplicate of issue 7054 ***
Comment #4 by hsteoh — 2018-01-08T15:53:58Z
This is a long-standing issue that has been known for a while now. It's not so easy to fix because the correct behaviour depends on byGrapheme, but the last time I checked, that breaks @safety and CTFE-ability.