├── README.md ├── demo.html └── fontdetect.js /README.md: -------------------------------------------------------------------------------- 1 | # FontDetect 2 | 3 | Detect if the specific fonts are installed, and add classes to the `html` element. 4 | 5 | Inspired by: 6 | 7 | - http://jsdo.it/mayuki/qAvH 8 | - https://plus.google.com/113463921353776506005/posts/Yf1xtgKchFm 9 | 10 | ## Usage 11 | 12 | 13 | 14 | 30 | 31 | Result: 32 | 33 | 34 | 35 | ## Browser support 36 | 37 | - Does not support IE 8 and below 38 | -------------------------------------------------------------------------------- /demo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | FontDetect 7 | 15 | 16 | 17 | 18 | 19 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /fontdetect.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * FontDetect v0.1.1 3 | * https://github.com/terkel/fontdetect 4 | * 5 | * Copyright (c) 2014 Takeru Suzuki - http://terkel.jp/ 6 | * Licensed under the MIT license - http://opensource.org/licenses/MIT 7 | */ 8 | var FontDetect = FontDetect || (function () { 9 | 10 | 'use strict'; 11 | 12 | var style = document.createElement('style'), 13 | fontDataWOFF2 = 'data:application/font-woff2;base64,d09GMgABAAAAAAKIAA8AAAAABgQAAAIuAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP0ZGVE0cGiAGYACCUggEEQgKVHIBNgIkAxALCgAEIAWDXAc5P3dlYmYGGxAFyB6SVKCABKlAERUgUKUFz8uavn8wALxOFwfMqjRmYaemieJZWGDH8c2EJh7+u//9PjPTxSiKf9/lf07jhKMIQiqi73sYTwj/zzX9IkXvk5wfSuS6NCpso4nuDQeUmGE6AJq5td1rDz+KiZhJDRHZY0iIlwECPJQcPgO81LyeyN/1D+YgEAYJABQhZKE0t0DNvtigK2k99QNN+Ak5kxlmgM4/1HPsa6VcqEM2ar4b1efGhIJag4AabSlyppkq2lLNCgSEdAJ0Zmstc1J/VS0hDU+fJPMjXqD44yrqNaU1QGpdvFYDCPgJCICgnAbWgSa0EqyHar3Xi0GmW+Dm07juv7YCnArL9Zm/xn/mqZ/+ddOqEuZU/UL05Jm/n/w4i7j7BIS95Yp3V3jxT3r24czUPGiCTNImtlouqK+an9zojN9SWotJTJC7LDi06d0KiIByVuwLcqWKEggyUEOhsAxI2gaQTWRD0eGElot5aHR8w504f9wDe8S89Z7pRjUDZsxaM2/MiFGLDFNkLITVY6aNqGDXaahsXjLJY56DlR2tRXo06dMKcWSahcU3n5HpNWRe2ZjhSUMp066LUUeEzKgZiyYT05aHI1Z5XDnFY8JQf9Uwq0ljvDLJkhOXz5clU4G1yj5DvIZVyUVbi6lImwEhYsiVSx0KZcpMlqyVLJkWE9lqZw91mbNkzLx5QybPdeH/pUz+NA1JotJrRibXZkcd/kvTY3YqryanzPMr', 14 | fontDataWOFF = 'data:application/font-woff;base64,d09GRgABAAAAAAREAA8AAAAABgQAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAABGRlRNAAABWAAAABwAAAAcbNveqkdERUYAAAF0AAAAHQAAACAAMQAET1MvMgAAAZQAAABDAAAAYGVJZyBjbWFwAAAB2AAAAEcAAAFSACIEFmN2dCAAAAIgAAAABAAAAAQAIQJ5Z2FzcAAAAiQAAAAIAAAACP//AANnbHlmAAACLAAAAFQAAABUPaWWPmhlYWQAAAKAAAAAMAAAADYBLgvpaGhlYQAAArAAAAAcAAAAJAUUAyVobXR4AAACzAAAABAAAAAQCTwAIWxvY2EAAALcAAAACgAAAAoAVABUbWF4cAAAAugAAAAfAAAAIABIADluYW1lAAADCAAAAQUAAAHc+4lFanBvc3QAAAQQAAAAKwAAADlLkh2id2ViZgAABDwAAAAGAAAABrO3VDIAAAABAAAAAMw9os8AAAAA0EXXpQAAAADQWGQ1eNpjYGRgYOADYgkGEGBiYARCZiBmAfMYAARrADYAAAB42mNgZn7BOIGBlYGFqYspgoGBwRtCM8YxGDHqAPlAKewg1Dvcj8GBgZfBkVnhvwXDCeYXDCeAwoxIShQYGAEA7AotAHjaY2BgYGaAYBkGRgYQ8AHyGMF8FgYDIM0BhExgGV4Gx///kViM/7/+PwTVBQaMbAxwLiNIDxMDKmBkIAyYGYY0AAAwHgk2AAAhAnkAAAAB//8AAgACACEAAAEqApoAAwAHAC6xAQAvPLIHBADtMrEGBdw8sgMCAO0yALEDAC88sgUEAO0ysgcGAfw8sgECAO0yMxEhESczESMhAQnox8cCmv1mIQJYAHjaY2BkYGAA4vlljjfj+W2+MsgzvwCKMFyISDGF04pAJVpMs4BcDgYmkCgAKfgJT3jaY2BkYGB+8d8CRDIAAaMWAyMDKmABAFs2Az8BbAAhA+gAAAPoAAAAAAAAAAAAKgAqACoAKgAAeNpjYGRgYGBh4GBgYgABEMnIABJzYNADCQAABIEAggB42m2PzUrDQBRGT0ws6MJV6cJV6MKFYGnTWrVdCeJG/MGi3QlWrA2mraZRdOPz6SP4Cj6E9JvJEGqRYcK5X+49uQHW+cDHC9aAqm7OHoGqnFfYYMuxzzYtxwFlbhyv8kbquKT8x/EnFX4df1H3yjl/+2x6R9wx5Yl3TcY8MCIjZCye6cRMlB1S55J70QsJt+psUFNmTpcrTuhzJjJ9O0udJguXsmtVqbVP5Q//2C7oKTG8mI7UmdlNJ7wWEzX27NuxrI9ymp6h0kTmAZFo1959mqoO/t2vr2qgKWPOCvOp2+xc3zRpSNu+a9CRKdKzaf8rsnu2OC7mezzLHcucypzMAcGmPvcAAAB42mNgYgCD/1sZjBiwARYGBkYmRmYGFbb0nMqCDEP20rxMAwMDFwCFRwaaAAABVDKztgAA', 15 | fontDataTTF = 'data:application/x-font-ttf;base64,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', 16 | styleText = '@font-face{font-family:A0;src:' + 17 | 'url(' + fontDataWOFF2 + ')format("woff2"),' + 18 | 'url(' + fontDataWOFF + ')format("woff"),' + 19 | 'url(' + fontDataTTF + ')format("truetype")}', 20 | testNode = document.createElement('span'); 21 | 22 | if (typeof style.appendChild !== 'function') { 23 | return { 24 | test: function () { 25 | return this; 26 | } 27 | }; 28 | } 29 | 30 | style.id = 'fontdetect-style'; 31 | style.appendChild(document.createTextNode(styleText)); 32 | document.head.appendChild(style); 33 | 34 | testNode.id = 'fontdetect-test'; 35 | testNode.style.fontFamily = 'A0'; 36 | testNode.style.height = 0; 37 | testNode.style.overflow = 'hidden'; 38 | testNode.style.position = 'absolute'; 39 | testNode.style.visibility = 'hidden'; 40 | testNode.appendChild(document.createTextNode('A')); 41 | document.body.appendChild(testNode); 42 | 43 | return { 44 | test: test 45 | }; 46 | 47 | function test (slug, familyName) { 48 | 49 | var testInterval = setInterval(detect, 16), 50 | testTimeout = setTimeout(function () { 51 | clearInterval(testInterval); 52 | }, 4096); 53 | 54 | detect(); 55 | 56 | function detect () { 57 | 58 | var test = false, 59 | key, 60 | i, 61 | len; 62 | 63 | if (testNode.offsetWidth === 0) { 64 | clearInterval(testInterval); 65 | clearTimeout(testTimeout); 66 | if (typeof slug === 'object') { 67 | for (key in slug) { 68 | FontDetect.test(key, slug[key]); 69 | } 70 | } else { 71 | if (Object.prototype.toString.call(familyName) === '[object Array]') { 72 | len = familyName.length; 73 | for (i = 0; i < len; i++) { 74 | if (isFontAvailable(familyName[i])) { 75 | test = true; 76 | break; 77 | } 78 | } 79 | } else { 80 | if (familyName === undefined) { 81 | familyName = slug; 82 | slug = slug.toLowerCase().replace(/\s/g, ''); 83 | } 84 | test = isFontAvailable(familyName); 85 | } 86 | document.documentElement.className += (test? ' ': ' no-') + slug; 87 | FontDetect[slug] = test; 88 | } 89 | } 90 | } 91 | 92 | function isFontAvailable (fontName) { 93 | var result; 94 | testNode.style.fontFamily = '"' + fontName + '",A0'; 95 | result = testNode.offsetWidth > 0; 96 | testNode.style.fontFamily = 'A0'; 97 | return result; 98 | } 99 | 100 | return this; 101 | } 102 | }()); 103 | --------------------------------------------------------------------------------