23

Is there a way to make a variable width font act like a fixed width font in HTML?

For example, if I have the sentence, "The quick grey fox jumped over the lazy dog" displayed in "Courier New", a fixed width font, it would be wider overall than if it was in a variable width font like, "Arial". I would like to use "Arial" instead of "Courier New" but have the characters fixed width.

Example of variable width:
The quick grey fox jumped over the lazy dog.

Example of fixed width:

The quick grey fox jumped over the lazy dog

Notice how close the characters are to each other in the word "quick" and "grey" in each example.

RIAstar
  • 11,912
  • 20
  • 37
1.21 gigawatts
  • 16,517
  • 32
  • 123
  • 231
  • HTML or TLF? Which one do you want? Those are two completely different rendering technologies which require different solutions. – RIAstar Jan 05 '13 at 23:24
  • That's true. What I'm starting with is a list of text. I can choose either technology to use in this case. But I can create a new question. – 1.21 gigawatts Jan 05 '13 at 23:32
  • You seem to be getting a lot of HTML answers and I can't think of a quick fix for TLF. So maybe you can base your choice of technology on that. – RIAstar Jan 05 '13 at 23:40
  • It's looking that way. I've created a separate question for TLF since someone visiting this post in the future may find answers for two different technologies confusing. – 1.21 gigawatts Jan 05 '13 at 23:43
  • The HTML approach may work for TLF as well. I would have to create span elements, and set the width and text alignment of each. Unfortunately, the HTML import in TLF is very very slow (TLF 2.0). – 1.21 gigawatts Jan 08 '13 at 05:59

5 Answers5

14

Not with just CSS. I would recommend you use the popular Lettering.js (you'll need jQuery for it) to generate span tags around each character, then set an width across all the characters.

.monospace > span {
  display: inline-block; /* Enable widths */
  width: 1em;            /* Set width across all characters */
  text-align: center;    /* Even out spacing */
}

Test Case

1.21 gigawatts
  • 16,517
  • 32
  • 123
  • 231
JoeJ
  • 920
  • 1
  • 6
  • 17
  • Could I remove the requirement by adding span tags before hand? What does the body { font: 16px/1.5 Arial, sans-serif } do? – 1.21 gigawatts Jan 05 '13 at 23:55
  • If you want to hand code the `span` tags into the document, that would work also. You do not then need Lettering.js. The `font` declaration sets a base `font-size` of 16px, a base `line-height` of 1.5em (or 24px) and a `font-family` of Arial, with a backup of sans-serif, on the entire document. It is the shorthand of using all of these properties separately. – JoeJ Jan 06 '13 at 00:03
  • 1
    @JoeJ, down voting this because I could not get this to work and the test case no longer exists. – Eric Aug 01 '15 at 20:23
3

The only thing I can think of is to put each letter in an HTML element, and style that element something along the lines of:

width: 8px;         /* Whatever fixed width you want here */
display: block;     /* Force the width to be respected. See also: inline-block */
float: left;        /* So it won't be 1-per-line. Not needed for inline-block */
text-align: center; /* So the character appears in the middle of the block */

I'm not familiar with Flex, but if I were to implement this approach, I would put together some Javascript that would generate all the elements for me.

Ashley Ross
  • 2,345
  • 2
  • 23
  • 43
  • Each character is already in it's own span tags so I think this just might work. :) – 1.21 gigawatts Jan 05 '13 at 23:19
  • 2
    This does what the question asks for, but this means that letters do not *look* like evenly spaced; e.g., in “World”, the first two letters seem to be much closer to each other than the rest. The point is that to create monospace impression, you need a real monospace font. – Jukka K. Korpela Jan 05 '13 at 23:52
  • @AshleyRoss You could use inline-block and get rid of the float. Inline block lets you set a size on an element but displays it inline (no new line). – 1.21 gigawatts Jan 18 '17 at 01:23
  • @JukkaK.Korpela If the letters are centered and manually set to a width it should look like monospaced. I'd have to see an example. – 1.21 gigawatts Jan 18 '17 at 01:24
1

It's an old question, but I would suggest looking for a suitable fixed-width font that can be used as a webfont that has the features you want. I'm a pretty big fan of Inconsolata, for example.

I'd start with Google Fonts and unselect all categories leaving only Monospace.

Tracker1
  • 19,103
  • 12
  • 80
  • 106
0

You might be able to use the letter-spacing CSS property to get what you want. By definition, monospace fonts have the same character width unlike serif or sans-serif. Using letter-spacing is your best bet W3C Reference

djthoms
  • 3,026
  • 2
  • 31
  • 56
  • Isn't the letter-spacing value just added to the default kerning for a given font? While it would increase or decrease the spacing between each letter, it won't make the spacing uniform, correct? But if this meets 1.21 gigawatts' needs, it's definitely a better option than my suggestion. :) – Ashley Ross Jan 05 '13 at 23:15
  • I think Ashley's right. I think it adds or subtracts to the values in the font's kerning table. – 1.21 gigawatts Jan 05 '13 at 23:20
  • The `letter-spacing` value specifies added spacing between characters (kerning is something completely different), so it would not make the spacing uniform at all. – Jukka K. Korpela Jan 05 '13 at 23:46
  • I think this is a good point to add, and although not exactly "fixed-width", it might help with a main problem where a fixed-width is desired only because the text is too hard to read bunched up. So good to mention the `letter-spacing` as a factor to consider – Guy Park Nov 01 '19 at 03:54
0

The result should be crappy as proportional fonts aren't made for that.

Nonetheless, you can achieve that with individual span around characters: http://jsfiddle.net/rvYES/

body {
  font: normal 100%/1.5 Arial;
}

span {
  outline: 1px dotted darkred;
}
span:nth-of-type(even) {
  outline-color: blue;
}

.w-fixed span {
  display: inline-block;
  min-width: 1em;
}

I added visual clues (outline) to see what's going on and used min-width just in case, not width.
This method will cause a huge problem of accessibility with screen readers, for blind and partially sighted people using these assistive technologies. Letters being into individual span will be spelled / read out
o
n
e

b
y

o
n
e

w
h
i
l
e

a

n
o
r
m
a
l

p
a
r
a
g
r
a
p
h

w
o
u
l
d

b
e

r
e
a
d

a
s

a

s
e
n
t
e
n
c
e
,

a
s

u
s
u
a
l
.

P
r
e
t
t
y

a
n
n
o
y
i
n
g

e
h
?

pun intended

FelipeAls
  • 21,711
  • 8
  • 54
  • 74
  • 1
    Typographically the result would be crappy, but there is no reason why screen readers would spell out each letter. (Poor screen readers might do odd things, though.) – Jukka K. Korpela Jan 05 '13 at 23:44
  • :) What is the CSS in the body tag doing? I've seen it in more than a few places now. – 1.21 gigawatts Jan 05 '13 at 23:46
  • @JukkaK.Korpela If you were developing an AT, you could've reasons to behave differently when seeing letters in individual `span` rather than in a normal sentence, though I don't have the test cases from real world that led them to this decision. And if you want to style the first letter from a paragraph, well at least CSS has `:first-letter` – FelipeAls Jan 05 '13 at 23:55
  • @1.21gigawatts `font` is the shorthand property for a bunch of `font-something` properties and also `line-height`. Using percentages for `font-size` is due to using `em` unit (not pixels) and a bug of most versions of IE with `em` unit on this particular element http://clagnut.com/blog/348/ (IE is fine with `em`s on any other element...). `/1.5` is the `line-height` value (*unitless*) that will be inherited in the whole document. – FelipeAls Jan 06 '13 at 00:01