Font-Face Changing via JavaScript

Font-Face changing via JavaScript

You can create a new <style> element with the @font-face rule and append it to the document's head:

var newStyle = document.createElement('style');
newStyle.appendChild(document.createTextNode("\
@font-face {\
font-family: " + yourFontName + ";\
src: url('" + yourFontURL + "') format('yourFontFormat');\
}\
"));

document.head.appendChild(newStyle);

Of course, you'll probably need to provide all the necessary font formats and URLs, too, unless you're only worried about support for modern desktop browsers (in which case you would just use WOFF – I assume that's reasonable, because of the other features you mentioned).

How to style JavaScript created text using CSS's @font-face

Well, after a bit of searching through Raphael's code I found it automatically sets its own font style (Arial) on all its text elements. I don't think that really makes sense, especially since I couldn't figure out on how to override it with a CSS '@font-face' font, but ok.
My solution was to simply delete the automatic setting of the font attribute in Raphael's source code.

For anyone interested, it's in the part where theText is declared. Just delete the font: availableAttrs.font bit in res.attrsand everything will obey the CSS style you want.

Preloading @font-face fonts?

This answer is no longer up to date

Please refer to this updated answer: https://stackoverflow.com/a/46830425/4031815



Deprecated answer

I'm not aware of any current technique to avoid the flicker as the font loads, however you can minimize it by sending proper cache headers for your font and making sure that that request goes through as quickly as possible.

Using jQuery to know when @font-face fonts are loaded?

Ok, it was pretty easy. Basically I just set my text to:

a.main {visibility: hidden;}

and then add:

$(window).bind("load", function() {
$('#nav a.main').addClass('shown');
});

Then make sure that the following is also in my css file:

a.main.shown {visibility: visible;}

How to know if a font (@font-face) has already been loaded?

Now on GitHub: https://github.com/patrickmarabeas/jQuery-FontSpy.js

Essentially the method works by comparing the width of a string in two different fonts. We are using Comic Sans as the font to test against, because it is the most different of the web safe fonts and hopefully different enough to any custom font you will be using. Additionally we are using a very large font-size so even small differences will be apparent. When the width of the Comic Sans string has been calculated, the font-family is changed to your custom font, with a fallback to Comic Sans. When checked, if the string element width is the same, the fallback font of Comic Sans is still in use. If not, your font should be operational.

I rewrote the method of font load detection into a jQuery plugin designed to give the developer the ability to style elements based upon whether the font has been loaded or not. A fail safe timer has been added so the user isn’t left without content if the custom font fails to load. That’s just bad usability.

I have also added greater control over what happens during font loading and on fail with the inclusion of classes addition and removal. You can now do whatever you like to the font. I would only recommend modifying the fonts size, line spacing, etc to get your fall back font as close to the custom as possible so your layout stays intact, and users get an expected experience.

Here's a demo: http://patrickmarabeas.github.io/jQuery-FontSpy.js

Throw the following into a .js file and reference it.

(function($) {

$.fontSpy = function( element, conf ) {
var $element = $(element);
var defaults = {
font: $element.css("font-family"),
onLoad: '',
onFail: '',
testFont: 'Comic Sans MS',
testString: 'QW@HhsXJ',
delay: 50,
timeOut: 2500
};
var config = $.extend( defaults, conf );
var tester = document.createElement('span');
tester.style.position = 'absolute';
tester.style.top = '-9999px';
tester.style.left = '-9999px';
tester.style.visibility = 'hidden';
tester.style.fontFamily = config.testFont;
tester.style.fontSize = '250px';
tester.innerHTML = config.testString;
document.body.appendChild(tester);
var fallbackFontWidth = tester.offsetWidth;
tester.style.fontFamily = config.font + ',' + config.testFont;
function checkFont() {
var loadedFontWidth = tester.offsetWidth;
if (fallbackFontWidth === loadedFontWidth){
if(config.timeOut < 0) {
$element.removeClass(config.onLoad);
$element.addClass(config.onFail);
console.log('failure');
}
else {
$element.addClass(config.onLoad);
setTimeout(checkFont, config.delay);
config.timeOut = config.timeOut - config.delay;
}
}
else {
$element.removeClass(config.onLoad);
}
}
checkFont();
};

$.fn.fontSpy = function(config) {
return this.each(function() {
if (undefined == $(this).data('fontSpy')) {
var plugin = new $.fontSpy(this, config);
$(this).data('fontSpy', plugin);
}
});
};

})(jQuery);

Apply it to your project

.bannerTextChecked {
font-family: "Lobster";
/* don't specify fallback font here, do this in onFail class */
}

$(document).ready(function() {

$('.bannerTextChecked').fontSpy({
onLoad: 'hideMe',
onFail: 'fontFail anotherClass'
});

});

Remove that FOUC!

.hideMe {
visibility: hidden !important;
}

.fontFail {
visibility: visible !important;
/* fall back font */
/* necessary styling so fallback font doesn't break your layout */
}

EDIT: FontAwesome compatibility removed as it didn't work properly and ran into issues with different versions. A hacky fix can be found here: https://github.com/patrickmarabeas/jQuery-FontFaceSpy.js/issues/1

How to import fonts with pure JS?

I would suggest using Google's Webfontloader, it's incredibly simple to use:

WebFont.load({
google: {
families: ['Droid Sans', 'Droid Serif']
}
});

Which would allow you to use the massive web font library hosted by google here, without needing to explicitly specify the CSS. You can use custom fonts as well if you're willing to use a style tag or a .css file (or you can inject the @font-face via javascript.) There are other web font providers that work with the Webfontloader, just look on the github page.

If you're interested in learning how to do this manually in javascript, any query on injecting CSS via javascript will sort you, but, that's still technically using CSS. Not sure if this/that is what you want.



Related Topics



Leave a reply



Submit