在 IE CSS font-face 仅在通过内部链接导航时有效

Posted

技术标签:

【中文标题】在 IE CSS font-face 仅在通过内部链接导航时有效【英文标题】:On IE CSS font-face works only when navigating through inner links 【发布时间】:2012-11-05 02:08:00 【问题描述】:

我们的网页设计师创建了一个具有以下字体的 CSS:

@font-face 
    font-family: 'oxygenregular';
    src: url('oxygen-regular-webfont.eot');
    src: url('oxygen-regular-webfont.eot?#iefix') format('embedded-opentype'),
         url('oxygen-regular-webfont.woff') format('woff'),
         url('oxygen-regular-webfont.ttf') format('truetype'),
         url('oxygen-regular-webfont.svg#oxygenregular') format('svg');
    font-weight: normal;
    font-style: normal;

它在 IE 和 Firefix 上运行良好。但是有一个问题:在 IE 上,只有当我使用内部网页链接导航页面时,字体才会正确呈现。如果我点击 Refresh 或 Back 按钮,字体将被默认字体(Times New Roman)替换。

目前该网站使用的是 HTTPS,但在使用 HTTP 时发现了同样的问题。

当我使用内部网站链接导航时,在 IE 开发者工具 (Shift - F12) 的“网络”选项卡中,我看到以下内容:

/Content/oxygen-regular-webfont.eot?    GET 200 application/vnd.ms-fontobject

当我使用刷新/返回按钮时,其他字体还有两个条目:

/Content/oxygen-regular-webfont.woff    GET 200 application/x-font-woff
/Content/oxygen-regular-webfont.ttf GET 200 application/octet-stream

CSS 文件本身正在以下列方式加载:

/Content/site.css   GET 200 text/css

我试图同时删除 woff 和 ttf 所以我有以下内容:

@font-face 
    font-family: 'oxygenregular';
    src: url('oxygen-regular-webfont.eot');
    src: url('oxygen-regular-webfont.eot?#iefix') format('embedded-opentype');
    font-weight: normal;
    font-style: normal;

但 IE 的行为仍然相同(除了它不再下载 woff 和 ttf 之外):在通过 Back/Refresh 导航时显示不正确的后备字体。

如何让 IE 在刷新/返回操作时加载正确的字体?

【问题讨论】:

【参考方案1】:

不要将 Vary Request Header 设置为 https

不加载字体

Vary:Accept-Encoding,https

作品

Vary:Accept-Encoding

avoid delayed font loading需要设置缓存头。

【讨论】:

【参考方案2】:

我找到了解决此问题的替代解决方案。

我已将字体直接嵌入到样式表中,而不是作为单独的字体文件加载。这在包括 Windows、Mac、iosandroid 等在内的所有浏览器中都可以正常工作,并有助于减少网页中的 HTTP 请求数量。

这不需要对标头 Cache-Control 进行任何更改。

@font-face font-family: '<FONT NAME>'; src: url(data:application/x-font-woff;charset=utf-8;base64,<BASE64_ENCODED>) format('woff'), url(data:application/x-font-ttf;charset=utf-8;base64,,<BASE64_ENCODED>) format('truetype'); font-weight: normal; font-style: normal;

您可以在 OS X 或 Linux 中使用内置的 base64 命令进行字体编码。

【讨论】:

【参考方案3】:

我刚刚遇到了同样的错误,对于那些想要一个纯粹的解决方案(非精确技术相关)的人:您需要确保您发送的字体标题不是no-cache。除了之前写的内容之外,实际上还有两个标题可以做到这一点:

"cache-control: no-cache"

"pragma: no-cache"

这两个都说浏览器是一样的,第一个是 HTTP1.1 的一部分,第二个是旧的(HTTP1.0)。

现在,解决方案:

如果您真的想提供字体(和其他文件?) 客户端缓存,设置"cache-control" to "max-age=0";您可以删除 pragma 标头,它已过时(或将其设置为 "pragma: cache")。 如果你真的想要缓存:删除 no-cache 值,并设置适当的 max-age(例如 "cache-control: max-age=3600" - 一小时缓存)。 Pragma 可以设置为"pragma: cache" 或完全删除。

【讨论】:

【参考方案4】:

我找到了一个解决方案,但我看不出它起作用的原因(嗯,只有一个原因 - 它是 IE :D)。

我所做的是将同一个站点放在 Apache 上并再次测试。在 Apache 上,即使使用刷新按钮,字体也能正常工作。然后在网络检查器中,我看到 Apache 为 eot 文件返回 304 而不是 200,它击中了我 - 所以这是缓存问题。我去了我的 ASP.NET 应用程序,果然 - 出于安全原因(同时也是为了避免缓存 AJAX 请求)有人禁用了您可以想象的所有缓存:

        // prevent caching for security reasons
        HttpContext.Current.Response.Cache.SetAllowResponseInBrowserHistory(false);
        HttpContext.Current.Response.Cache.SetExpires(DateTime.UtcNow.AddDays(-1));
        HttpContext.Current.Response.Cache.SetValidUntilExpires(false);
        HttpContext.Current.Response.Cache.SetRevalidation(HttpCacheRevalidation.AllCaches);
        HttpContext.Current.Response.Cache.SetNoServerCaching();

        // do not use any of the following two - they break CSS fonts on IE
        HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.NoCache);
        HttpContext.Current.Response.Cache.SetNoStore();

当我注释掉最后两行代码时,字体突然开始在 IE 上正常工作。所以我猜答案是:如果没有缓存,IE 无法加载字体。不过,我不知道为什么只有在刷新/导航回来时才会出现问题。

编辑 - 替代解决方案

而不是评论最后两行

    // do not use any of the following two - they break CSS fonts on IE
    HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.NoCache);
    HttpContext.Current.Response.Cache.SetNoStore();

SetAllowResponseInBrowserHistory改为true

HttpContext.Current.Response.Cache.SetAllowResponseInBrowserHistory(true);

据我所知,这应该仍然允许无缓存,除了向后和向前导航。 MSDN - SetAllowResponseInBrowserHistory Method

【讨论】:

【参考方案5】:

JustAMartin 的answer 让我们找到了不同的解决方案:

而不是评论最后两行

    // do not use any of the following two - they break CSS fonts on IE
    HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.NoCache);
    HttpContext.Current.Response.Cache.SetNoStore();

我们添加了以下行:

HttpContext.Current.Response.Cache.SetAllowResponseInBrowserHistory(true);

据我所知,这应该仍然允许无缓存,除了向后和向前导航。 MSDN - SetAllowResponseInBrowserHistory Method

【讨论】:

【参考方案6】:

删除全局响应 NoCache 和 NoStore 设置将修复字体,但如果您需要这些设置,那么显然这不是答案。

我的理解是,仅将缓存设置为过期不会一直阻止缓存页面的显示;它会强制检查服务器,但如果页面未修改(304 响应)可能(通常?)仍显示缓存版本。

(实际上,现在阅读本文时,我突然想到将客户端缓存设置为立即过期并结合 SetNoServerCaching 可能会强制客户端页面始终更新?似乎它可能会对性能产生影响。)

我发现在 ASP.NET MVC 中使用控制器上的 OutputCacheAttribute 属性来禁用缓存不会破坏 IE 字体。

[OutputCacheAttribute(VaryByParam = "*", Duration = 0, NoStore = true)]
public class FooController : Controller

    ...
    

我意识到 NoStore 与 SetCacheability(HttpCacheability.NoCache) 不同,但它似乎适用于此目的。

您可以创建一个具有要继承的属性的基本控制器,以使代码更简洁。

【讨论】:

【参考方案7】:

我也遇到过同样的问题。

如果 .eot 文件的头部包含 Cache-Control: no-cache 值,IE9 不能正确加载字体. 开发工具显示 Result - 200,但列 Received 显示 400B,同时 Content-长度为70Kb。 我使用了以下值 Cache-Control: max-age=0 来解决问题。

【讨论】:

我使用了 Fiddler 工具的自动回复功能。 如果我能给你更多+1,我会的。这正是我们看到的问题 - ie9 在获取字体标题后断开连接。在字体文件夹中添加了一个缓存指令,它现在对我们有用。【参考方案8】:

确保这不是路径问题,即您的 CSS 文件与字体所在的位置相关。在您的情况下,您需要将 CSS 文件与字体文件放在同一文件夹中。

【讨论】:

好点。我编辑了我的帖子以显示 IE 如何加载 CSS 文件,它似乎总是来自同一个 /Contents 文件夹。

以上是关于在 IE CSS font-face 仅在通过内部链接导航时有效的主要内容,如果未能解决你的问题,请参考以下文章

在 IE 中使用 @font-face 显示未设置样式的内容

在 CSS 中加载 @font-face 时如何删除浏览器中的默认字体? “FOUT”

CSS 菜单仅在 IE (SWFObject) 中隐藏在 flash 后面

IE7 仅在来自生产服务器的页面上忽略 CSS 属性选择器

css 仅在IE上应用Style

@font-face 仅在 chrome 中无法在 ff/opera 中使用