Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a CSS workaround for Firefox' bug: inline-block + first-letter with changed size

Tags:

css

firefox

It's better to see a bug for yourself in Firefox: http://jsfiddle.net/kizu/btdVd/

The picture, showing the bug:

enter image description here

And the bug filled in 2007 on bugzilla.

The bug appears when you're adding ::first-letter pseudo-element with display: inline-block, and then change the font-size of this first-letter.

More letters in a word after the first: more extra space added (or subtracted — if the font-size is lesser than block's).

Adding float: left to the first-letter inverts the bug: with bigger font-size the width of inline-block shrinks.

So, the question: is there any CSS-only workaround for this bug? It's somewhat killing me.

like image 620
kizu Avatar asked Sep 25 '11 20:09

kizu


2 Answers

I've found that triggering reflow on the whole page (or any block with a problem) fixes the problem, so I've found a way to trigger it on every such block with one-time CSS animation: http://jsfiddle.net/kizu/btdVd/23/

Still, while this fix have no downsides in rendering, it have some other ones:

  • it would work only for Fx5+ (that supports animations);
  • it still flashes the original bug for a few ms, so it's maybe somewhat blinky.

So, it's not an ideal solution, but would somewhat help when Fx4- would be outdated. Of course, you can trigger such fix onload with JS, but it's not that nice.

like image 177
kizu Avatar answered Oct 29 '22 11:10

kizu


I don't think there's a good solution.

I have come up with a flaky solution for you though:

.test:first-letter {
    font-size: 2em;
    letter-spacing: -0.225em;
}

Add the letter-spacing style to the :first-letter selector in your Fiddle, and you'll find the blocks go back to roughly the right size.

Explanation:

Basically, the bug is being caused by the whole block taking its size from the font specified in the first-letter.

What I'm doing here with the letter-spacing is trying to adjust the size of this font, without affecting it's physical appearance. Adjusting the letter spacing in this way in normal text would result in the letters overlapping each other by .225 of a character width on either side.

I was initially hoping that a value of -0.25 would be sufficient -- ie a quarter of a character on each side would reduce the width of each character by half, which would be what we want because the first letter is font-size:2em, so it's twice as big.

However, the calculation isn't quite as clean as that, because the first and last characters in the string would only be overlapped on one side each, and because the first letter does in fact want to be double width, even if the rest of the characters don't.

All of this means that the exact letter-spacing value required to counter-act the bug will vary depending on how long the text, as well as the font sizes of the original text and the first letter. This is why I had to experiment a bit with the value of the letter spacing to get it working, and also explains why I couldn't get quite a perfect fit on all the text rows in your Fiddle. I would have needed a slightly different value for each block.

The value of -0.225 seems to be about the closest I can get to it being right for all your examples, but in practice you'll need to adjust it to suit your site.

Don't forget also that this is a Firefox bug, and therefore you'll need to write it in as a browser-specific hack of some sort. And be careful to keep an eye on the Firefox bug report you linked; when it does get fixed, you'll need to work out a way to keep your hack in place for users of old versions, but remove it for users with the fix.

[EDIT]

The only other working solution I've come up with is simply not to use the features which trigger the bug. ie drop the :first-letter selector, and use a separate <span> for the first letter of your text if you want to style it differently.

This is the obvious answer really, and would of course solve the problem (and would also mean that your styled first letter works in older browsers), but it would not be ideal from a semantic perspective, and more importantly doesn't actually answer the question, which is why I didn't offer it as a solution in my original answer.

I have been trying to find alternative work around for the bug as well, but the options are limited, and nothing I've tried has given as good results as my initial suggestion.

I tried a hack of making the :first-letter invisible, and using :before to display the big leading capital letter. However, this didn't work for me. I didn't linger on it too long so you may be able to get it working, but there is a problem with it in that you'd have to define the leading letter in your CSS, which wouldn't be ideal.

Another possible solution is to use the CSS font-stretch: condensed; property on the :first-letter. This would reduce the width of the first letter back to 1em, and thus resolve the width issue of the rest of the text. The down sides of this, however, are that firstly it would make the leading letter look squashed, which is probably not what you want, and secondly this style only works for fonts which support the condensed property. It turns out that this isn't well supported by the standard fonts, so may not be workable for you.

In the end, the original letter-spacing solution is still the only way I've found to really work around the bug.

like image 23
Spudley Avatar answered Oct 29 '22 10:10

Spudley