在JavaScript中检测浏览器字符支持?

28

我正在开发一个音乐相关的网站,经常使用 HTML 特殊字符 ♯ 和 ♭ 来使页面更美观,例如:

♯
♭

然而,我注意到在一些浏览器(如IE6和Safari for PC)中,这些字符不被支持。我创建了一个条件性的javascript,在特殊字符上提供普通、受支持的字符(例如用G#代替G♯和Bb代替B♭),但我很难弄清楚如何检测哪些浏览器缺少这些字符。

我知道我可以测试浏览器(例如ie6),但我希望正确地测试字符支持本身。

有没有人知道使用javascript、jQuery或rails进行这样的好方法?(该页面由rails应用程序提供,因此请求对象和任何其他Rails魔法都是可用的。)


我最终选择了Mike Samuel的出色解决方案,尽管我认为那些指出格式问题的人可能有一些道理——我尝试了所有的解决方案,但这并不意味着我没有漏掉任何东西。任何遇到类似问题的人都应该像其他人建议的那样:1.确保他们的页面具有正确的字符编码,2.查看Matt Ball引用的链接答案。我有一种隐隐的感觉,99%的时间他的解决方案可能比javascript hack更好。 - Chris Ladd
我怀疑这是字体问题。所选的字体不包含您想要的代码点的基本符号。许多现代浏览器可以通过使用字体替换来补救这个问题(从其他字体中选择基本符号)。Mike Samuel的解决方案很聪明,但如果涉及到固定宽度字体,则可能无法正常工作。不幸的是,我没有更好的解决方案。 - McDowell
@McDowell - 嗯...我查看了这个字体列表,没有看到任何可能存在于ie6系统上的网页安全字体。所以我尝试了'sans serif'但没有成功。我有什么遗漏的吗?有什么好的选择? - Chris Ladd
微软似乎声称Arial Unicode MS有效,但对我来说并不起作用(或者可能是我的Windows XP版本没有包含它)。 - Paul D. Waite
4个回答

25
如果你创建了两个 SPAN,其中一个包含你想要的字符,另一个包含一个无法打印的字符 U+FFFD(� 是一个好的选择),那么你可以测试它们是否具有相同的宽度。

<div style="visibility:hidden">
  <span id="char-to-check">&#9839;</span>
  <span id="not-renderable">&#xfffd;</span>
</div>
<script>
  alert(document.getElementById('char-to-check').offsetWidth ===
        document.getElementById('not-renderable').offsetWidth
        ? 'not supported' : 'supported');
</script>

您应该确保该 DIV 没有使用固定字体样式。


1
@Pirripli,感谢您。在标记为已接受之前,请确保它实际上可以在您担心的浏览器上正常工作。可能马特·鲍尔是正确的。 - Mike Samuel
6
这种方法的问题在于,某些字符显示时具有相同的宽度,比如 "█",但其他有效字符也具有这样的宽度。 - Tom Kincaid
@TomKincaid,是的。它不是百分之百可靠的。但对于人类语言文本而言,除了查询字体或将文本混合到画布中,这是一个相当可靠的方法。 - Mike Samuel
@MikeSamuel 在某些系统上,这根本不起作用,因为FFFD是一个“定义”的字符,其宽度与“缺失字符”符号不同。对此有什么想法吗?我应该选择哪个字符保证未定义?或者我应该提出一个新问题吗? - Mr Lister
6
这种方法基于一个默认假设,认为字体中缺失的字符将以与U+FFFD相同的方式呈现。这种方法不够可靠,浏览器可能会使用其他渲染方式。 - Jukka K. Korpela
显示剩余8条评论

1

与其在JavaScript上瞎折腾,你应该使用CSS的unicode-range

@font-face {
  font-family: 'MyWebFont'; /* Define the custom font name */
  src:  local("Segoe UI Symbol"),
        local("Symbola"),
        url('myfont.woff2') format('woff2'),
        url('myfont.woff') format('woff'); /* Define where the font can be downloaded */
  unicode-range: U+266F, U+266D; /* Define the available characters */
}

body {
  font-family: 'MyWebFont', Arial;
}
&#9839;
&#9837;
Normal text

local块中定义那些可能已经本地安装并包含所需符号(例如Windows的Segoe UI Symbol)的字体。然后定义一个包含所需符号的网络字体(我建议使用Symbola)。 unicode-range指令告诉支持的浏览器(IE9及以上版本)仅当页面上存在指定的符号时才下载字体(可以通过搜索Unicode-Tables找到它们的Unicode编号)。
如果用户已经拥有该字体,则不会下载。如果页面上不存在所需符号且浏览器不是古老的版本,则不会下载该字体。它只会在需要时被下载。
如果你仍然想支持旧版IE,请使用fontsquirrel生成初始的@font-face语句,然后自己添加localunicode-range部分。

0
“浏览器支持”不是问题所在。您应该将文件作为UTF-8*进行服务,并使用适当的字符而不是HTML实体。
  • Unicode升降号:♯(U+266F)
  • Unicode降号:♭(U+266D)

您还应确保以UTF-8格式保存文件(而不是ASCII或ISO-8859-1等格式)。

另请参阅:必须提到的Joel on Software:每个软件开发人员绝对必须了解的有关Unicode和字符集的绝对最低限度(无任何借口!)


我不是Rails的专家,但我认为它默认会这样做。


2
嗯...我相信我已经做到了这一点。我有一个元标记:<meta charset="utf-8">。除了将实际符号复制并粘贴到我的标记中,我还需要做些什么特别的事情吗?我刚刚这样做了,在ie6上进行了测试,发现出现了小方框。你知道ie6是否支持这两个符号吗? - Chris Ladd
1
非常有趣,绝对值得一读,但我无法将此页面的见解转化为尖锐符号... 我首先尝试更改相关div的类别以使用Arial,然后只是普通的sans-serif,但都没有成功。很可能我在这里漏掉了什么,但目前,我想我会使用Mike Samuel的建议。如果我后来成功了,我会告诉你的,但现在我认为仍在ie6上的用户类型不介意看到#代替♯。 ;) - Chris Ladd
1
@Pirripli:很好,你理解JS方法更像是一种hack。在我看来,最好的解决方案是简单地停止 支持 IE6。话虽如此 - 你提到Safari在Windows上也有问题... - Matt Ball
哈!我喜欢ie6nomore.com,会考虑使用他们的代码来引导用户朝着正确的方向。然而,我发现即使每天都与ie6搏斗(它是任何设计项目中我最不喜欢的部分),但试图让ie6工作往往会让我编写更好的代码,依赖更简单的HTML,更少的盒模型 hack(例如负边距等),并且让我更全面地思考页面,而不仅仅是一堆DIV和CSS。别误会,我仍然讨厌它。但我把它想象成一个半血统的径赛教练。 - Chris Ladd
有些字体可能没有某些字符。有些电脑可能没有某些字体。为什么不在这种情况下优雅地降级,而不是显示方框呢? - LB--
显示剩余4条评论

-3
将此添加到您的HTML中。
<head>

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> 

</head>

并检查IE和Safari是否正确呈现页面。


没有,没有运气。我已经有<meta charset="utf-8">了,但是我尝试添加您的属性却没有用...谢谢您的想法!不过我希望那就是问题所在... ;) - Chris Ladd

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