27

I'm working on a music related website, and frequently use the HTML special characters for sharps (♯) and flats(♭) to keep things pretty, e.g.:

♯
♭

However, I've noticed that in some browsers (IE6, Safari for PC) those characters aren't supported. I've created a conditional javascript that serves up plain, supported characters in place of the special ones ( G# for G♯ and Bb for B♭ ). But I'm having a hard time figuring out how to detect which browsers lack those characters.

I know I could test for the browser (e.g. ie6), but I was hoping to do things right and test for character support itself.

Does anyone know of a good way to do this using either javascript, jQuery, or rails? (The page is served by a rails app, so the request object and any other Rails magic is on the the table.

Chris Ladd
  • 2,795
  • 1
  • 29
  • 22
  • I ended up going with Mike Samuel's excellent solution, though I think those indicating formatting issues may have something there -- I did attempt all solutions, but that doesn't mean I haven't missed anything. Anyone undergoing a similar issue should, as the others have suggested: 1. ensure their page has proper character encoding, 2. see the linked answer referenced by Matt Ball. I have a sneaking suspicion 99% of the time his might be the better solution than a javascript hack. – Chris Ladd Jan 08 '11 at 20:04
  • I suspect that this is a font issue. The chosen font does not contain the graphemes for the code points you want. Many modern browsers can compensate for this using font substitution (picking the grapheme out of another font). Mike Samuel's solution is clever, but might not work if fixed-width fonts get involved. Unfortunately, I don't have any better solutions. – McDowell Jan 09 '11 at 10:56
  • @McDowell - Hm... I looked over [this list of fonts](http://www.fileformat.info/info/unicode/char/266F/fontsupport.htm) and didn't see any web-safe fonts that might be on systems with ie6. So I simply tried 'sans serif' without success. Am I missing something here? What's a good choice? – Chris Ladd Jan 09 '11 at 18:28
  • [Microsoft seems to claim that Arial Unicode MS works](http://office.microsoft.com/en-us/visio-help/install-the-universal-font-for-unicode-HP005255840.aspx), but it doesn’t for me (or possibly my version of Windows XP doesn’t include it). – Paul D. Waite Jun 08 '11 at 13:31

4 Answers4

25

If you create two SPANs, one containing the character you want, and the other containing an unprintable character U+FFFD (�) is a good one, then you can test whether they have the same width.

<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>

You should make sure that the DIV is not styled using a fixed font.

Mike Samuel
  • 118,113
  • 30
  • 216
  • 245
  • very clever! and so fast that I have to wait four more minutes to mark your answer as accepted, which I will. – Chris Ladd Jan 08 '11 at 19:35
  • I had previously tried adding the special character as a class on a throwaway div, and then testing for the class, but without any luck. This is a very elegant piece of code -- thank you! – Chris Ladd Jan 08 '11 at 19:36
  • 1
    @Pirripli, thanks. I'd make sure it actually works on the browsers you're worried about before marking it accepted. Matt Ball may be right. – Mike Samuel Jan 08 '11 at 19:40
  • Works for me on ie6, and I'll check Safari in a bit. However, I'll wait a bit. Certainly, Matt Ball is right -- if it's possible to render those characters correctly on those browsers, that's preferable to this workaround. Still, I think your answer is the best for my *question*: how to detect character support, while his may indeed be a better solution to my *problem*: how to display sharps and flats. Up votes all around! – Chris Ladd Jan 08 '11 at 19:44
  • Explicitly set the font. Test in target browser(s). Realize that under certain conditions it may over-detect or under-detect just based on character widths. Happy coding. (I would test all the "narrow" characters at once vs a same-length string of the ugly diamonds.) –  Jan 08 '11 at 22:07
  • This solution doesn’t seem to work for me — the unicode characters I’m trying to use seem to get measured as being the same size as the unprintable character, possibly because they’re not kerned in the font in question. At this point, I’m thinking some sort of web-font solution might be better, as I can’t see how to reliably detect support. – Paul D. Waite Jun 08 '11 at 19:00
  • 6
    The problem with this method is that � displays with a width and other valid characters have that same width such as █ – Tom Kincaid Oct 02 '13 at 16:55
  • @TomKincaid, Yep. It's not bulletproof. It's a reasonably reliable way for human language text short of a way to query a font, or blitting text into a canvas though. – Mike Samuel Oct 02 '13 at 18:02
  • @MikeSamuel On some systems, this doesn't work at all, since the FFFD is a "defined" character with a different width than the "missing character" glyph. Any ideas about this? Which character should I choose as guaranteed to be undefined? Or should I ask a new question? – Mr Lister Feb 17 '14 at 19:59
  • @MrLister, This is all heuristic, and I'm afraid I don't know of anything that's guaranteed to be undefined except maybe U+FFFE which is the endianness-counterpart of the BOM. [Code page FF00](http://www.unicode.org/charts/PDF/UFFF0.pdf) says "**Noncharacters** / ... / * FFFE - may be used to detect byte order by contrast with FEFF" – Mike Samuel Feb 18 '14 at 15:10
  • @MikeSamuel Thanks, but that doesn't work in my situation either. I asked a new question, [here](http://stackoverflow.com/q/21892798/1016716) which I hope will explain the situation a little better. – Mr Lister Feb 19 '14 at 21:28
  • 5
    This method is based on the implicit assumption that a character that is missing in fonts is rendered the same as U+FFFD. This is not reliable, and browsers are known to use other renderings. – Jukka K. Korpela Feb 19 '14 at 22:19
  • @JukkaKKorpela, agreed. – Mike Samuel Feb 19 '14 at 22:23
1

"Browser support" is not the problem here. You should be serving your files as UTF-8*, and use the appropriate characters rather than the HTML entities.

  • Unicode sharp symbol: ♯ (U+266F)
  • Unicode flat symbol: ♭ (U+266D)

You should also make sure to save your files in UTF-8 (and not, say, ASCII or ISO-8859-1).

See also: the must-be-mentioned Joel on Software: The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!).


*I'm not a Rails guy, but I think it does this by default.

Matt Ball
  • 354,903
  • 100
  • 647
  • 710
  • 2
    Hm... I believe I'm already doing this. I have a meta tag: . Is there something special I should be doing other than copying and pasting the actual symbol into my markup? I've just done this, tested it on ie6, and found little square boxes. Do you know that ie6 supports those two symbols? – Chris Ladd Jan 08 '11 at 19:40
  • @Pirripli: see [this answer](http://stackoverflow.com/questions/2702447/which-of-the-following-unicode-characters-should-be-used-in-html/2702573#2702573). It may just be a font problem, but inserting the symbol into the markup is definitely the way to go. Are you sure you're saving the file as UTF-8? – Matt Ball Jan 08 '11 at 19:42
  • 1
    Very interesting, definitely worth a read, but I wasn't able to turn [this page's insights into sharp symbols](http://www.fileformat.info/info/unicode/char/266F/fontsupport.htm)... I first tried changing the class of the div in question to use Arial, then just plain sans-serif, without success. It's very possible I'm missing something here, but for the moment, I think I'm going to use Mike Samuel's suggestion. I'll let you know if I have success later, but at this point I think the types of users still on ie6 won't mind seeing # for ♯. ;) – Chris Ladd Jan 08 '11 at 20:00
  • 1
    @Pirripli: it's good that you understand that the JS approach is more of a hack. IMO, the best solution is to simply [stop](http://ie6update.com/) [supporting](http://www.ie6-must-die.com/) [IE6](http://www.ie6nomore.com/). That said - you did mention that Safari on Windows also had issues... – Matt Ball Jan 08 '11 at 20:08
  • HA! I love ie6nomore.com and will consider using their code to prompt users in the right direction. I have noticed, however, even as I wrestle daily with ie6 (it's my least favorite part of any design project) I find that attempting to make things work for ie6 often makes me code better, relying on simpler HTML, fewer box model hacks (e.g. negative margins, etc...) and makes me generally think about pages more holistically rather than just a collection of DIVs and CSS. Don't get me wrong, I still hate it. But I think of it more as a bastard track coach. – Chris Ladd Jan 08 '11 at 20:49
  • @Matt: I believe this is a Windows XP issue. Out-of-the-box, Windows XP doesn’t seem to render a lot of Unicode characters when used in web pages. (Maddeningly, I can’t find a good reference for this.) – Paul D. Waite Jun 08 '11 at 13:02
  • @Paul that could be caused by something as simple as needing a font with more Unicode glyphs. – Matt Ball Jun 08 '11 at 13:33
  • @Matt: sure, I think Windows XP just doesn’t (or rather didn’t, it is 10 years old after all) ship with such a font, so you can’t safely use unicode glyphs on a public-facing website without some sort of hack like Mike’s. – Paul D. Waite Jun 08 '11 at 13:43
  • Some fonts just don't have certain characters. Some computers just don't have some fonts. Why not try to gracefully degrade in this case instead of displaying boxes? – LB-- Apr 24 '15 at 02:55
1

Rather than mucking around with JavaScript, what you should be doing instead is using css's 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

In the local blocks, define fonts that people might have installed locally and contain the symbols you want (like Window's Segoe UI Symbol). Then define a web font (I suggest Symbola) containing the symbol you want to show.

The unicode-range directive tells supporting browsers (IE9 and up) not to download the font unless the specified symbols are present on the page (You can find their unicode number by searching Unicode-Tables.)

If they have the font already, they won't download it. If the symbol(s) aren't present on the page and your browser isn't older than dirt, the font won't be downloaded. It'll only be downloaded when it is needed.

(If you still want to support old IE, use fontsquirrel to generate your initial @font-face statement, then add the local and unicode-range parts yourself.

Sora2455
  • 744
  • 7
  • 25
-3

Add this to your HTML

<head>

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

</head>

And check to see if IE and Safari render the page right.

Mark
  • 3,609
  • 1
  • 22
  • 33
Nerian
  • 15,901
  • 13
  • 66
  • 96
  • Nope, no luck. I already had , but I tried adding your attributes to no avail... thanks for the idea, though! I wish that were it... ;) – Chris Ladd Jan 08 '11 at 19:31