Bug 13139

Summary: Font not inherited when font-family does not match a font.
Product: WebKit Reporter: Elliott Sprehn <esprehn@chromium.org>
Component: CSSAssignee: Nobody <webkit-unassigned@lists.webkit.org>
Status: NEW    
Severity: Normal CC: eric@webkit.org, jason@thinkoomph.com, mitz@webkit.org, nickshanks@nickshanks.com, phiw@l-c-n.com
Priority: P2 Keywords: HasReduction
Version: 523.x (Safari 3)   
Hardware: Macintosh   
OS: Mac OS X 10.4   
Attachments:
Description Flags
Test Case
none
Special Font Handling Test Case none

Description From 2007-03-20 19:10:12 PST
If a font-family is specified with fonts that are not available and no generic font is specified at the end of the list Webkit uses "serif" (which resolves to Times) and does not inherit the parent element's font as it should.

This is a new issue, previous versions of Safari did not exhibit this behavior.

Reproducible in the latest nightly: (Wed Mar 21 1:27:44 GMT 2007).
------- Comment #1 From 2007-03-20 19:15:55 PST -------
Created an attachment (id=13731) [details]
Test Case

In the test case both paragraphs should render with the same font (sans-serif), however as the fake font on the first paragraph cannot be found Webkit chooses serif (Times) instead of the parent element's font-family.

Look in Firefox or Safari 2.0 for correct behavior.
------- Comment #2 From 2007-03-20 19:35:59 PST -------
I do not believe this is a bug.  

There is nothing wrong with the font family declaration that contains a font name that is not on the system.  You don't just magically discard the entire font-family rule because the font does not exist on the system.  You try to find the closest match you can.  In Safari 3 we now favor serif as the best match case for invalid font names.
------- Comment #3 From 2007-03-20 19:43:00 PST -------
Or put another way, there's no reason to assume that the invalid named font in the font-family declaration has the same generic family as the parent.
------- Comment #4 From 2007-03-20 19:50:09 PST -------
The technical reason for this change had to do with fixing another bug, namely preventing intermediate font-family declarations that get subsequently overridden by a later rule from affecting the choice of generic family for the font.

For example if you have the following:

.foo {
  font-family: Courier, monospace;
}

#bar {
  font-family: 'Invalid Font';
}

and then an element <div class="foo" id="bar">...</div>

Safari 2 actually sets the generic family of the div to be monospace because it applies declarations in a forward order.  This forced us to reset the generic family at each rule application in order to avoid accidentally mutating the generic family.

Gecko matches in backwards order (which is harder for us to do) and so is immune from this problem.  Therefore they didn't have to reset the generic family to work around the above issue.

I suppose we could save off a copy of the generic family somewhere to compare against and implicitly inherit it down the chain, but it's not clear to me that this is supposed to be done.

Since technically the generic family is named as part of the font-family property, and the subsequent rule overrides it completely, it's not clear that the generic family is immune from being overridden and should somehow continue to inherit.  That does not seem to follow given the way CSS works.
------- Comment #5 From 2007-03-20 19:58:31 PST -------
Seems reasonable to me to assume that if the font can't be found the generic family of the parent should be inherited.

Put differently, if I specify that the entire page should be sans-serif by adding a font-family to the body then a unmatched font family on child element should not assume a "random" font. I say random because the default font in my browser is not serif, but rather sans-serif (Helvetica Neue).

Why should Safari choose a font that is not my default browser font if it can't match one? If not taking the parent element's font then the default browser font from the preferences should be used.

Also the behavior as it stands now is inconsistent with every other major browser (Opera, IE, Firefox) and old versions of Safari which is going to lead to Safari being the odd one out on many websites in terms of font rendering.
------- Comment #6 From 2007-03-20 20:09:07 PST -------
I'm not sure i get what you mean by forward or backward order.

I wasn't meaning to say the generic family of the parent should get special treatment though, instead I think we should inherit the entire font-family from the parent element as if the font-family on the child element which matches nothing didn't exist.

This appears to be what all the other browsers are doing.

My fault for not being more clear.
------- Comment #7 From 2007-03-20 20:37:50 PST -------
From the CSS 2.1 specification (http://www.w3.org/TR/CSS21/fonts.html#algorithm):

"If there is no font within the family selected in 2, then use a UA-dependent default 'font-family' and repeat step 2, using the best match that can be obtained within the default font."

So if no font is matched, the browser is supposed to simply pick a default font to try. The spec doesn't seem to suggest that the value should be inherited from the parent. And if you think about it, if the webpage author is trying to change a font for a given element, there isn't really a reason to assume that the parent font is any better a match for the intended new font than some generic default font.

That said, the spec leaves this "default" up to the browser and doesn't seem to put any restrictions on how the browser may choose that default font. Since the spec allows the UA to pick whatever font it feels like in the worst case scenario, I'm not sure that inheriting the parent would be considered incorrect either.
------- Comment #8 From 2007-03-20 22:48:50 PST -------
A couple of examples to illustrate how complicated this problem is:

<div style="font-family: sans-serif">
<div style="font-family: Monaco">
...
</div>
</div>

Clearly the author's intent with Monaco is to use a monospace font.  Using the parent's family isn't going to yield the result the author intended, nor is using "serif."  If the author leaves off a generic family, it's really up to the browser to try to infer the intent of the author.  

Using the parent is just a heuristic and a poor one at that.  We choose "serif" on the assumption that a majority of the fonts specified on the Web are "serif", and so that maximizes the probability that we will be right.

Here's another case to mull over:

<div style="font-family:sans-serif">
<tt style="font-family:Invalid>
</tt>
</div>

Using the parent here seems clearly wrong.  If anything <tt> and <pre> should default to monospace instead, implying that the generic family specified in the user agent stylesheet should also play a role.

That said, your argument that other browsers all seem to employ the same heuristic is a compelling one.  I'd like to see an investigation of some of the test cases in all major browsers (IE6, IE7, Opera, Firefox) in order to figure out how to proceed.
------- Comment #9 From 2007-03-20 23:35:25 PST -------
BTW Safari 2 doesn't match other browsers already.  It just used Helvetica as the last resort fallback font instead of Times.
------- Comment #10 From 2007-03-20 23:36:01 PST -------
I actually think using the user's preferred default font might be the best behavior here.
------- Comment #11 From 2007-03-20 23:47:35 PST -------
I'm taking regression off and lowering this to P2, since we didn't Inherit before.  We just used "helvetica" instead of "times."  It just coincidentally looked like inheritance to the bug reported because it happened to be sans-serif.
------- Comment #12 From 2007-03-21 00:23:52 PST -------
Seems something like checking for fonts in the order:

element style, special UA style for element, parent element

That way the element gets it first if applicable which is expected, then if that cannot match and its an element with special font preference like <pre> which solves the special case there and then finally take the parent element's font as with other browsers.

This appears to be what Opera and IE7 do as well, though Gecko is less smart about it and would make the <pre> sans-serif if the parent element was sans-serif despite the fact that the pre generally is rendered with special font consideration.

So as it stands:

Gecko:           element => parent element
Presto & IE7:    element => special font for element in UA sheet => parent element
Safari:          element => Default font

Not sure what's right here, though Safari seems to be the only one ignoring the parent element entirely. Presto and IE7's way seems pretty logical, though I can see an argument for using the user defined default font in the preferences instead.

Either way, at the very least I think using the one from the preferences makes more sense than some hard coded value.

On a side note: What's the reason the fallback font was changed to Times?
------- Comment #13 From 2007-03-21 00:43:36 PST -------
Created an attachment (id=13733) [details]
Special Font Handling Test Case

View in Opera or IE7 to see special case font handling for the <pre> element.

Odd behavior in Gecko though, it appears that by adding to the font-family (body here) on the parent element something besides a generic family that the parent style is ignored when the font-family on the child doesn't match. That is:

body { font-family: fantasy, sans-serif; }
.child { font-family: foo-bar; } 

actually gets you "serif" which is the browser default. However:

body { font-family: monospace; }
.child { font-family: foo-bar; } 

Gets .child to be "monospace" which seems like an odd way to handle this.

The more I look into this the more complicated the "logic" behind what the browsers are really doing gets...
------- Comment #14 From 2008-09-12 10:47:29 PST -------
(In reply to comment #8)

Sorry for getting tangential. 

> Clearly the author's intent with Monaco is to use a monospace font.  Using the
> parent's family isn't going to yield the result the author intended, nor is
> using "serif."  If the author leaves off a generic family, it's really up to
> the browser to try to infer the intent of the author.  

> Using the parent is just a heuristic and a poor one at that.  We choose "serif"
> on the assumption that a majority of the fonts specified on the Web are
> "serif", and so that maximizes the probability that we will be right.

As for 'serif' being the majority, it's not the case everywhere. CJK users prefer sans-serif to serif. I filed bug 20797 about adding a preference/UI to control this. 
------- Comment #15 From 2008-09-17 10:09:55 PST -------
(In reply to comment #10)
> I actually think using the user's preferred default font might be the best
> behavior here.

Which is what TOT does (I do not remember if that is already the case in Safari 3.1, but I think it is).
------- Comment #16 From 2009-08-06 14:18:39 PST -------
I expect this is related to bug 19161, but I don't understand this bug well enough to tell if it's "fixed" by it.
------- Comment #17 From 2011-04-14 09:50:04 PST -------
Found this page while looking for documentation on this odd rendering behavior. I have a case where the Italic version of a common sans-serif font is being asked for, and not found, so subsequently I see non-italic (and serif!) Times being used instead. Yet another layer to this complicated thread. 

I worked up an example page here: http://www.oomphdev.com/designcomps/webkit/

Oddly, this renders correctly in Safari 5.0.4 but not Chrome (latest) 10.0.648.204