无法理解防弹@font-face CSS规则

7
在将此标记为重复之前,请仔细阅读我的疑问。我在网上(特别是stackoverflow)进行了彻底的搜索,但无法澄清疑点。这个问题可能一眼看去很长,但它包含了其他人也想知道的关键问题。
我正在尝试获得有关防弹字体规则@font-face的略微深入的知识,但外界的人们让我感到困惑。请向我提供建议。
因此,这里是最新的防弹代码,由Font-Spring(http://blog.fontspring.com/2011/02/further-hardening-of-the-bulletproof-syntax/)建议,同时解决了IE9兼容性模式问题:
@font-face {
font-family: 'MyWebFont';
src: url('webfont.eot'); /* IE9 Compat Modes */
src: url('webfont.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
     url('webfont.woff') format('woff'), /* Modern Browsers */
     url('webfont.ttf')  format('truetype'), /* Safari, Android, iOS */
     url('webfont.svg#svgFontName') format('svg'); /* Legacy iOS */
}

没有IE9兼容模式修复程序的那个,也是由Font-Spring(http://blog.fontspring.com/2011/02/the-new-bulletproof-font-face-syntax/)提供的,看起来像这样:

@font-face {
font-family: 'MyFontFamily';
src: url('myfont-webfont.eot?#iefix') format('embedded-opentype'), 
     url('myfont-webfont.woff') format('woff'), 
     url('myfont-webfont.ttf')  format('truetype'),
     url('myfont-webfont.svg#svgFontName') format('svg');
}

目前,我正在阅读Peter Gasston的《CSS3之书》。它遵循Font-Spring所述的“弹性规则”,并带有IE9兼容模式修复。他说,在第二个src属性中带有查询字符串?的规则负责IE9 Compat. Mode fix。但是,font-spring认为第一个src属性负责IE9 Compat. Mode fix。如果不完全理解该语法,我将无法学习。

我的严重问题相对较小。首先,我想知道是否只有?#iefix可以防止解析错误,还是像?iefix(没有#)或?xyz?#abc之类的东西也可以?必须写?#iefix吗?

其次,

  • 我无法感受到这个@font-face规则是如何解析的,IE8如何决定使用哪个src属性来使用eot字体。如果IE9在兼容模式下没有解析问题,那么它将如何决定使用哪种字体格式?IE9在兼容模式下会因为查询字符串字体url而出错吗?如果不会,那么为什么不会?
  • 有人能告诉我,如果我看整个防弹规则声明,IE8、IE9在兼容模式下、正常模式下和其他浏览器将如何解析它?如果浏览器支持多种字体,它将如何决定使用哪一种?浏览器查找url值和src属性的顺序是什么?
  • 一个独立的src属性,没有任何local()format()值,并且具有正确的eot格式,是否会被IE8接受,并且不会进一步下载定义了其他格式的下一个src属性?还是它仍然会转到下一个src属性并从那里下载字体?
  • 如果下一个src属性中有查询字符串(?),IE8(考虑到IE9在兼容模式下)会下载两次eot字体吗?如果没有查询字符串,那么它是否会从第一个属性接受eot字体而不会出错?还是它会出错,并且不适用任何自定义定义的字体,即使是来自第一个src属性?
此外,IE9正常模式支持eot格式吗?如果我完全删除查询字符串声明,那么弹性语法还能起作用吗?
@font-face {
font-family: 'MyWebFont';
src: url('webfont.eot'); /* IE6-IE8 as well as IE9 Compat. Mode */
src: url('webfont.woff') format('woff'), /* Modern Browsers */
     url('webfont.ttf')  format('truetype'), /* Safari, Android, iOS */
     url('webfont.svg#svgFontName') format('svg'); /* Legacy iOS */
}

以上的规则在所有情况下都适用吗?IE6-8将使用第一个src,IE9兼容模式和其他浏览器将遵循其余规则。

如果使用以下local()值,我建议的规则是否仍然适用:

@font-face {
font-family: 'MyWebFont';
src: url('webfont.eot'); /* IE6-IE8 & IE9 Compat. Mode */
src: local('MyWebFont'), /* To fix IE6-IE8 and IE9 Compat. Mode */
     url('webfont.woff') format('woff'), /* Modern Browsers */
     url('webfont.ttf')  format('truetype'), /* Safari, Android, iOS */
     url('webfont.svg#svgFontName') format('svg'); /* Legacy iOS */
}

无论是在IE8还是IE9兼容模式下,local()值都会使它们消失。在正常模式下,IE9会使用上述规则中的eotwoff吗?如果它使用eot,我们可以对第一个src属性进行微小更改,像这样:
src: url('webfont.eot?#iefix') format('eot');

IE9将忽略这个属性,因为它包含eot,然后继续使用woff,我是对的吗?另外,如果我再次像这样更改规则本身:

src: url('webfont.eot?#iefix') format('embedded-opentype');

IE9现在会使用eot格式还是继续使用woff

这就是我想知道的,是的,我认为这些问题肯定需要一个答案。


我强烈地想编辑你的问题并添加“[需要引用]”。 - Mr Lister
1个回答

5
@font-face {
  font-family: 'MyWebFont';
  src: url('webfont.eot'); /* IE9 Compat Modes */
  src: url('webfont.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
       url('webfont.woff') format('woff'), /* Modern Browsers */
       url('webfont.ttf')  format('truetype'), /* Safari, Android, iOS */
       url('webfont.svg#svgFontName') format('svg'); /* Legacy iOS */
}

这只是一种把不同版本的IE浏览器兼容问题解决的技巧。第一个src标签会满足IE9,所以如果你的网页访问者使用这个浏览器,他们将会看到这个字体。第二个src标签不会覆盖第一个标签,因为IE9不能解析“webfont.eot?#iefix”字符串。
关于第二个标签:它是“老式”的抗锯齿语法,你已经很熟悉了。请注意,在Fontspring有关硬化规则的博客文章中提到,Microsoft在使用IE7和IE8渲染模式时修复了IE9的错误,但实际上并没有修复IE7和IE8,所以对于这些浏览器,您仍然需要使用此技巧。
关于“local()”的说明:这告诉浏览器使用某个本地可用的字体(即页面查看者的电脑上),如果你的查看者没有安装它,则无法看到正确的字体。有关更多信息,请参见以下内容:http://www.paulirish.com/2009/bulletproof-font-face-implementation-syntax/#smiley

首先感谢您回答我这个荒谬的问题。我仍然有一点疑问,我们是否真的需要包含“?#iefix...”这一行,因为我认为不需要,在兼容模式下IE9会采用第一个src,所以IE6-IE8也是如此...是吗?第一个src属性不包括任何format()或local()结构,这些结构在IE6-IE8中无法识别,因此这一行应该可以在两种情况下工作。你怎么看? - GauravRockr
欢迎 @GauravRockr。如果您使用的是IE9,则仅第二个src将无法工作(因为IE6-IE8修复),因此您需要第一个。但是,实际上我认为最好的答案是... - kaosmos
抱歉,我在结束评论之前发布了它,现在无法修改,这是正确的:@GauravRockr,欢迎您,如果您使用的是IE9,则仅第二个src将无法工作(因为IE6-IE8修复程序在IE9上不起作用),因此您也需要第一个。但是第一个仅适用于IE9,因此您需要两者才能满足每个IE(当然,如果您不必支持旧版IE,则可以跳过?#iefix)。无论如何,理解这一点的最佳方法就是尝试一下。使用不同的IE版本进行一些虚拟机,并查看其工作方式 :) - kaosmos
我知道?iefix在IE9兼容模式下不起作用,但是由于第一个属性src: url('webfont.eot')没有包含多个字体以及local()format()结构,它本身难道不应该也适用于IE6-8吗? - GauravRockr
不,实际上并不是这样。IE6-IE8需要修复(因为存在一个错误,它并非预期行为),而IE9则无法理解它,因此,如果您想支持所有IE版本,则需要同时使用src属性。 - kaosmos

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接