如何检测网页中使用了哪种定义的字体?


138

假设我的页面中有以下CSS规则:

body {
  font-family: Calibri, Trebuchet MS, Helvetica, sans-serif;
}

如何检测用户浏览器中使用了哪种定义的字体?

编辑让人不知道为什么要这样做的人:我检测的字体包含其他字体不可用的字形,并且当用户没有该字体时,我要显示一个链接,要求用户下载该字体,以便他们可以以正确的字体使用我的Web应用程序。

当前,我正在为所有用户显示下载字体链接,我只想为未安装正确字体的用户显示此字体。


2
要记住的一件事是,某些浏览器会将某些缺少的字体替换为相似的字体,这是使用JavaScript / CSS技巧无法检测到的。例如,如果未安装Windows浏览器,它将用Arial代替Helvetica。提到的技巧MojoFilter和dragonmatank仍会报告已安装Helvetica,即使未安装。
tlrobinson

13
请注意以下几点:如果要提供下载Calibri的链接,请注意,尽管它与多个Microsoft产品捆绑在一起,但它不是免费字体,并且通过提供下载来侵犯版权。
亚当·赫普顿

Answers:


72

我已经看到它以一种不稳定但相当可靠的方式完成了。基本上,将元素设置为使用特定字体,并为该元素设置字符串。如果为元素设置的字体不存在,则采用父元素的字体。因此,他们要做的是测量渲染字符串的宽度。如果它与所需字体(与派生字体相反)相符,则表示存在。这不适用于等宽字体。

它来自哪里: Javascript / CSS字体检测器(ajaxian.com; 2007年3月12日)


2
用另一种方法measureText来自canvas:元素github.com/Wildhoney/DetectFont
Wildhoney

33

我写了一个简单的JavaScript工具,您可以用它来检查是否安装了字体。
它使用简单的技术,并且在大多数情况下应该是正确的。

GitHub上的 jFont Checker


2
字体检测不能解决问题。您可以使用它来遍历声明的字体并检查有效字体,但是对于给定的div而言,它提供的字体很少甚至没有信息。如果从JS创建div,我们如何知道使用什么字体?
乔恩·伦纳特·阿森登2014年

1
@JonLennartAasenden我相信您可以使用“ computedStyle”属性来获取使用的字体(我忘记了确切的名称,但是那样的话。)
Derek朕会功夫2014年

1
我编写了一个可在所有浏览器中使用的类。它是用Smart Pascal编写的,可以编译为JS,所以我不能在此发布解决方案-简而言之,我必须提取字体系列字符串,然后检查每种字体是否有效,并抓住第一个有效的字体-然后在任何地方都可以使用。我将“字体检测器”移植到了智能帕斯卡,并做了一些调整。
Jon Lennart Aasenden 2014年

1
@JonLennartAasenden听起来您的课程并不简单。浏览器将按给定的优先级检查每种字体(如果已安装),但有时会在列表中选择使用优先级较低的字体,如果优先级较高,则安装的字体缺少与请求的大小不匹配的字符或字形。
布兰登·埃利奥特

10

@pat实际上,Safari不会提供所使用的字体,至少我认为,无论是否安装了Safari,Safari始终会返回堆栈中的第一个字体。

font-family: "my fake font", helvetica, san-serif;

假设已安装/使用过Helvetica,您将获得:

  • Safari(我相信其他Webkit浏览器)中的“我的假字体”。
  • Gecko浏览器和IE中的“我的假字体helvetica,san-serif”。
  • Opera 9中的“ helvetica”,尽管我读到他们正在Opera 10中对其进行更改以匹配Gecko。

我通过了这个问题,并创建了Font Unstack,它测试堆栈中的每种字体并仅返回第一个已安装的字体。它使用@MojoFilter提到的技巧,但是如果安装了多个,则仅返回第一个。尽管它确实遭受了@tlrobinson提到的弱点(Windows将用Arial代替Helvetica并报告已安装Helvetica),但它还是可以正常工作的。


9

一种有效的技术是查看元素的计算样式。Opera和Firefox支持此功能(我在Safari中进行了侦察,但尚未测试)。IE(至少为7)提供了一种获取样式的方法,但似乎是样式表中的内容,而不是计算出的样式。有关quirksmode的更多详细信息:获取样式

这是获取元素中使用的字体的简单函数:

/**
 * Get the font used for a given element
 * @argument {HTMLElement} the element to check font for
 * @returns {string} The name of the used font or null if font could not be detected
 */
function getFontForElement(ele) {
    if (ele.currentStyle) { // sort of, but not really, works in IE
        return ele.currentStyle["fontFamily"];
    } else if (document.defaultView) { // works in Opera and FF
        return document.defaultView.getComputedStyle(ele,null).getPropertyValue("font-family");
    } else {
        return null;
    }
}

如果CSS规则是:

#fonttester {
    font-family: sans-serif, arial, helvetica;
}

然后,如果已安装helvetica,则应返回helvetica,否则返回arial,最后返回系统默认的sans-serif字体的名称。请注意,CSS声明中的字体顺序很重要。

您也可以尝试的一个有趣的技巧是使用许多不同的字体创建许多隐藏的元素,以尝试检测计算机上安装了哪些字体。我确信有人可以用这种技术制作一个漂亮的字体统计信息收集页面。


6
这将返回css的完整字符串,例如“ Helvetica,Arial,sans-serif”。它不返回实际使用的字体。
Tom Kincaid 2013年

8

简化形式为:

function getFont() {
    return document.getElementById('header').style.font;
}

如果您需要更完整的内容,请查看此内容


8

有一个简单的解决方案-只需使用element.style.font

function getUserBrowsersFont() {
    var browserHeader = document.getElementById('header');
    return browserHeader.style.font;
}

此功能将完全满足您的要求。执行时,它将返回用户/浏览器的字体类型。希望这会有所帮助。


我正在Safari上肯定使用Arial字体的元素上尝试此操作,并且将字体设置为“”。有什么想法吗?
Alessandro Vermeulen

最可能的原因是,这仅检查设置的字体,并且如果未设置字体,则可能使用Arial作为字体。
约西亚

1
@AlessandroVermeulen,这是因为element.style仅返回在样式属性中设置的值,而不会从其他地方返回任何值(即,将不会返回样式元素,外部css或用户代理默认值)。应删除此答案,因为它会误导/不正确。真是令人难以置信的赏金!
brennanyoung

很抱歉,但是我认为这不是正确的答案。虽然这会打印出该CSS属性的值,但不会返回浏览器正在使用的实际渲染字体。
gojun

7

另一种解决方案是自动安装字体,通过@font-face它可能不需要检测。

@font-face { 
font-family: "Calibri"; 
src: url("http://www.yourwebsite.com/fonts/Calibri.eot"); 
src: local("Calibri"), url("http://www.yourwebsite.com/fonts/Calibri.ttf") format("truetype");
}

当然,它不会解决任何版权问题,但是您始终可以使用免费字体,甚至可以制作自己的字体。您将同时需要.eot.ttf文件才能最佳工作。


3

Calibri是Microsoft拥有的字体,不应免费分发。另外,要求用户下载特定字体也不是很友好。

我建议购买字体的许可证并将其嵌入到您的应用程序中。


3
+1用于字体嵌入。这样可以解决问题,而无需检测任何内容。
Andrew Grothe

1
我建议您在购买任何东西之前先检查Google字体中是否有类似的东西。
OJFord 2014年

除此之外,如果用户在Windows计算机上,则可以查看Calibri。这是后备列表的全部内容。
dudewad 2015年

1
您的答案与问题无关,应为评论。
dudewad 2015年



1

您可以将Adobe Blank放到要查看的字体之后的字体系列中,然后将不呈现该字体中没有的任何字形。

例如:

font-family: Arial, 'Adobe Blank';

据我所知,还没有JS方法可以判断元素中哪些字形是由该元素的字体堆栈中的哪种字体呈现的。

浏览器具有衬线/无衬线/等宽字体的用户设置,并且它们也具有自己的硬编码后备字体,如果在字体中的任何字体中都找不到字形,则将使用它们,这使情况变得复杂。字体栈。因此,浏览器可能会使用不在字体堆栈或用户浏览器字体设置中的字体来渲染某些字形。 Chrome开发工具会为您显示所选元素中字形的每种渲染字体。因此,在您的计算机上,您可以看到它在做什么,但是无法分辨用户计算机上正在发生的事情。

用户系统也可能在其中发挥作用,例如Window在字形级别上执行Font Substitution

所以...

对于您感兴趣的字形,即使它们没有您指定的字体,也无法知道它们是否将由用户的浏览器/系统后备呈现。

如果要在JS中进行测试,则可以使用包括Adobe Blank的字体系列渲染单个字形,并测量其宽度以查看其是否为零,您必须遍历每个字形和要测试的每种字体,但是,尽管您可以知道元素字体堆栈中的字体,但无法知道用户浏览器配置为使用哪种字体,因此对于至少某些用户而言,您要遍历的字体列表将是不完整的。(如果新字体问世并开始使用,这也不是未来的证明。)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.