How many variants of a character can you put in a OTF/TTF (web)font?

I'm trying to figure out a way to get multiple variants of a character in one single font file. Or, to put it another way: can I put multiple font families (or weights) in one OTF/TTF file?

My goal is to reduce the number of requests a site has to make in order to retrieve all the used fonts. I'd only need about 40 to 50 glyphs: the alphabet, the digits and the basic punctuation marks. I'm also willing to just use uppercase, so lowercase could be used for a different family.

This is specifically for web use.

To illustrate, I would like to apply one font familty to this container, and have each line show up in a different typeface:

HELLO, USER 123!
HELLO, USER 123!
HELLO, USER 123!
HELLO, USER 123!

I think it's not possible, but before I give up on this idea I wanted to check with you guys.

I thought about and experimented with the following ideas:

Give each line one of the basic styles with CSS (normal, bold, italic, bolditalic) and instead of bold, italic or bolditalic glyphs, just use normal glyps of three other fonts. Can't be done because these have to be four separate font files.

Modify the text so a different character inside the same font is used. Basically, the idea of uppercase and lowercase. This can easily be done in CSS and would work for A to Z, but not for numerals or puncutation. Also, it would be limited to two variants.

Expand on that idea by somehow transforming everything to accented letters, so I'd have a, A, ä and Ä. I guess this only works for valid characters (a, but not m for instance). Also, this isn't triggerable from CSS, you can't say "text-transform: umlaut"

I've also brainstormed about a way to merge these files into one with other tricks. I.e. use the same binary container but somehow only use part of the data. Kinda like mulit-part MIME, but for binary. But I guess a stable, cross-browser way to do this is impossible.

The best solution I have now is to simply use four different font files, but BASE64-ing them and sticking them inside one CSS file. This actually works very well and caches nicely, the only disadvantage is the BASE64 overhead.

I’m not sure if this is helpful and what you want, but you could use sequences of visible characters + zero-width characters (U+200B, U+200C, U+200D, U+FEFF) and define substitution tables with different glyphs in each case.

@LiliCharlie: That's a very interesting idea, using :lang. I'll have to dig into browser support for this. Am I correct to think it works like this: < element lang="fr">abc< / element> will ask the render engine to get the glyphs for a, b and c, and the rasterizer/OTF will request these from the font, passing along the information that these should be the French version of these characters? If so: pretty cool.

@Theunis de Jong: Very recent browsers are starting to support things like ligatures, alternates and swashes, but for now these are too experimental to rely on. But that would be a perfect solution for me. So this means you could technically put a normal and a bold version in one OTF file, and use bold by saying those are the historical forms, for instance?

(Ab)using the Historical Forms for Bold is certainly an option, and there must be a few other "common" features that you might use this way. Most OTF features should allow combining with each other -- say, Oldstyle Numerals combined with Swash would use a total different glyph set than each on their own.

But the Stylistic Sets I was alluding to are a feature all on their own; twenty of them, in fact. They are unimaginatively named ss01 to ss20 (a fairly new option is a designer can give useful names to each) and they are specially defined for all "whatever you can think of" glyphs and glyph combinations.

Suppose you made 20 weights of your font, then you could assign one to each set.

That'd be absolutely perfect for the web. You could use ss01 et al for different families and still have one single font file. More about how this would work in browsers. Unfortunately it's still in the recommendation stage.

That'd be even cleaner. I found this recent discussion on the W3C mailing list and it looks like it's not supported yet. Also, it looks like there's a little support for fragmented identifiers for SVG — images at least. That could allow us to merge font files into one SVG-file and pick the appropriate one in our font-face declaration by adding #1 for the first font, #2 for the second, etc.

Unfortunately, the conclusion seems to be that there's no reliable cross-browser way of doing this, so BASE64'ing into one CSS file still seems to be the best option.