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.attrs
and 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
Get All CSS Root Variables in Array Using JavaScript and Change the Values
React Native Flexbox - How to Do Percentages || Columns || Responsive || Grid etc
Make the on Scroll Growing <Path> to Dashed Line
Capture/Save/Export an Image with CSS Filter Effects Applied
How to Get the Opacity of an Element Using JavaScript
Dynamically Changing Stylesheet Path Not Working in Ie and Firefox
Highcharts: Make the Legend Symbol a Square or Rectangle
How to Properly Escape Attribute Values in CSS/Js Attribute Selector [Attr=Value]
Customize Ng-Repeat in Angularjs for Every Nth Element
How to Show the Child Div on Mouse Hover of Parent Div
Hiding Div If Using Mobile Browser
Modify Pseudo-Element :After's Width Using JavaScript
How to Style Canvas Elements with CSS
How to Create and Apply CSS to JavaScript Alert
How to Change the Label Size of a Material UI Textfield
Kendo Chart Legend:Label at Left, Color at Right
Something Similar to Treegrid in Jqgrid
How to Change Url in Browser Without Navigating Away from Page