reliably load Fonts into DOM for canvas elements - javascript

I'm not sure if this is different for every browser, I'm primarily developing for webkit.
Loading fonts for use in canvas elements is easy, using #font-face...except that it seems the actual font file isn't loaded until it is first used.
If i don't use the font in the HTML at all, this creates a problem in canvas elements, the first time a custom font is called it generates text in the default font....however subsequent attempts to use the font are fine and use the custom font referenced, as if it was loaded because of the original call.
Question 1, is this standard for all browsers? is the font downloaded if it is declared in the CSS? or at first use?
Is there a "best practice" for loading fonts into the DOM? This is for a graphic project, and I'd rather not declare every font possible in the CSS. I also only want to load fonts that are going to be used. Is there a better way to load fonts with JavaScript?

Question 1, is this standard for all browsers? is the font downloaded
if it is declared in the CSS? or at first use?
Font loading is asynchronous which mean the font may still be loading in the background at the time you'd use canvas. For canvas this problem manifests right away as what you draw the first time is final.
For the DOM the content can be updated at a later point, although causing the infamous FOUT and FOIT, or Flash Of Unstyled Text and Flash Of Invisible Text. But for canvas the content need to be manually redrawn (or put on hold causing an inconvenient delay on the client side) when the font is ready to be used.
That being said - specific browsers may implement different loading strategies - and has, we would not always necessarily know which and when, and they would in any case have to take canvas into consideration so vendors would have to conform to similar strategies.
It's in general an "old" problem and not easy to get around depending on how old browsers you want to support. And the situation is less than ideal.
There are libraries that can help you get around the loading/readiness problem (have in mind that these libraries will add to the delay themselves) such as the mentioned Font Loader library from Google. You can futher improve speed by using CDN for the fonts and also storing fonts in localStorage.
These libraries are targeting more those who need path and metrics information, I'll include them in case they could prove useful to load fonts dynamically: Font.js and OpenType.js.
Also take a look at these articles for tips & tricks to improve font loading and for workarounds:
Font Loading Revisited with Font Events (2015-02-16)
Non-blocking web fonts using LocalStorage (2014-12-31)
In relation to a font being available for canvas - I did provide an alternative option in this answer a while back, though this is more of a brute-force approach, but works specifically for canvas.

Yes, it would be nice if fonts had an 'onload' callback. But until then ...
... A common option is to use setTimeout to delay the app's start in order to give the font time to load. Of course, a delay that's too small will fail to give the font time to load and a delay that's too large will cause unnecessary delay.
... A better option is Google's webfont loader
... A Do-It-Yourself option is to continuously draw one font character to an in-memory canvas element until the opaque pixel count has changed. When the count changes, the font has been drawn on the in-memory canvas and is available for you to use. Example code for this technique can be found on this Stackoverflow Q&A.

Related

Performance of Font Awesome

A web development company develops a website for me, which uses 12 icons from Font Awesome 5.15.3. They use SVG with JavaScript. After using Google PageSpeed Insights, I find the Font Awesome JavaScript becomes the performance bottleneck.
I then find "Performance & Font Awesome". But this does not provide much information on each method. I try to contact the support but get no responses by now. So I am trying to test with these methods by myself, such as SVG Sprites and individual SVG icons, meanwhile sharing my understanding of the pro and con of each method in performance.
Note: I will only consider the case that I host Font Awesome on my own server.
SVG with JavaScript: Based on my debug in Chrome DevTools, it seems that the javascript code is just find the patterns like and replace them with the corresponding svg icons. This will be time-consuming if the DOM tree of the whole page is large. Also why bother to let the JavaScript to do the task if one can just insert SVG icon to the location manually? I guess there are 3 reasons:
a. <i class="fas fa-camera"></i> is short(29 characters only) and more convenient to use than using an individual SVG Icon(normally 500 bytes) or a SVG Sprites(3 lines with total 88 characters).
b. It will not bloat the source HTML page too much.
c. It is good only if the same icon is used for many times, like below:
Web Fonts with CSS
In this method, one needs to include the Font Awesome font files with #font-face rule. And the download of the large Font Awesome font files will become the bottleneck of the performance. As far as I know, if I only use 16 icons from 1000 icons, there are no way to create a new font file containing only the 16 icons from the existing one.
SVG Sprites: This method seems to be great for my case. I can create a small svg file containing only the 16 icons I need. Then use the following way to include it in the HTML page:
<svg>
<use xlink:href="fa-brands.svg#facebook"></use>
</svg>
Though it requires 3 lines than 1 line(SVG with JS). It is still short, even if the icon is used for multiple times. I guess the disadvantage of this method is one plan to use many icons, for example, 100 icons. In such a case, the svg file will be large and become the performance bottleneck when downloading it.
Another disadvantage may be due to that to search in the SVG Sprite file, it will take some time, since the individual icons in SVG Sprite file is not indexed in any way.
Individual SVG icons: Embedding the SVG icon data to the HTML source will be the most efficient way in performance. But each SVG icon file will be about 500 bytes to 3KB, which will bloat the HTML file greatly. Also it is not good if the icon will be used in the page for many times, as in such a case, the HTML source will become huge.
Also "the browser cannot cache inline SVG as it would cache regular image assets, so pages that include the image will not load faster after the first page containing the image is loaded." based on https://developer.mozilla.org/en-US/docs/Learn/HTML/Multimedia_and_embedding/Adding_vector_graphics_to_the_Web
SVG + CSS: THis method is not mentioned in Font Awesome, but are widely used. See https://developer.mozilla.org/en-US/docs/Learn/HTML/Multimedia_and_embedding/Adding_vector_graphics_to_the_Web for different ways to add SVG to webpage, including SVG + CSS.
Please kindly advise if my understandings are correct or not. THank you very much!
Update:
I find one interesting comparison on their site: Web Fonts vs SVG
Update 2
I add another popular method which uses SVG + CSS
From my own personal experience I can tell you that I prefer to use the 12 icons approach VS anything else. Web fonts were great solution when not all major browsers were well performing svg standard. But today it's nonsense to use a bloating icon font when you just use 12 icons from there. If you want to be able to measure the impact of leaving the font and using the svg icons instead go and take a look to the performance and speed of my own web site here https://www.simbiosis-dg-apps.com. I tell you that except for the 2 pictures of myself and my partner every thing else that you will see is svg. Sometimes embedded into the html and most of the time called through the img tag. For the icons I use a similar method like the one that is used to set icons from an icon font but using my own css system. If want a better picture see this answer How to Replace the Web Font with SVG icon in CSS(Font Awesome)?

How to avoid page jump and FOUT during font loading and page loading

I am developing a website and I can't host the font. So it has to be loaded from an external resource. However, it loads slowly and because the font is not a standard font, it causes massive page jump on loading. The browser default font always loads first and when the font changes everything moves around and the entire scroll height of the page changes. And it's a big problem because one of the forms on the page shifts right at the point where you'd be starting to select a field and you end up selecting the wrong one when it jumps.
I have tried using font pre-loading just to find out that there is a massive lack of browser support. And even with testing on google chrome which is supposed to support it, it seems to fail and resort to the browser default font once in a while. ( link rel preload...)
Currently, I'm using a messy javascript solution that basically hides the page until the font loads and then uses a timeout to allow the browser time to render with the new font before making the page visible again. And then it uses another timeout that's a bit longer in case the font doesn't load at all to show the page as a backup.
It feels really unprofessional. I feel like it's causing an additional delay on the users end which shouldn't be necessary. There has to be a better way to go about this but I'm not finding one. I can't set a fixed height for the elements because some of the content and questions in the forms is user generated. I'm listing the terrible inline code which I'm currently using.
document.body.style.visibility="hidden";
//the link element that loads the font currently has an id
var font=document.getElementById('font');
font.onload=function(){
var timeout=self.setTimeout(function({
document.body.style.visibility="visible";
},100);
}
var fallback=self.setTimeout(function(){
document.body.style.visibility="visible";
},1000);
I don't mind the results I'm getting with my current solution. But I feel like there definitely has to be a better way of going about this?
I would agree with your assessment that the delay on the client side is unideal and unnecessary. Case studies by Google and the BBC have found that every second of load time can increase the bounce rate (the number of people who leave the site after visiting just one page) by as much as 10-20%.
One strategy you could use to reduce load time is narrowing the character set you load. If you're hosting the fonts yourself, segmenting the font and using a unicode-range value in your #font-face definition would be the best way to accomplish this. Some providers like Google Fonts allow you to do this with query string parameters, as well.
This can significantly reduce the number of unused, unneeded glyphs (e.g., foreign and special characters) that the client has to load.
As for reducing FOUT, one thing you could try is downloading the roman (regular) style to your machine, encoding it as base-64, and then embedding it directly into your page styling, e.g.,
#font-face {
font-family: MyFontName;
src: url('data:application/x-font-woff;charset=utf-8;base64, <font data> ') format('woff');
font-weight: normal;
font-style: normal;
}
Because the normal font style is directly integrated into your HTML/CSS contents, its load time is insignificant. The great part about this is that when browsers receive only a regular style, they automatically generate their own bold and italic versions. You can take advantage of this behavior and use it as a stand-in for your proper styles until they load.
Also, if you're not doing so already, take a look at different web font formats like WOFF2, and compression methods like Brotli (which WOFF2 uses).
Here are a couple of resources that cover these and other methods in detail:
A Comprehensive Guide to Font Loading
Strategies
FOUT, FOIT, FOFT
If you are using Google fonts make sure you don't have the &display=swap query param set.
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght#100;200;300;400;500;700;900&display=swap" rel="stylesheet">
This instructs the browser to do a font jump in every case.
Jumping fonts is not good, especially above the fold.
Remove the &display=swap and the jump will stop.

For a header background, does Javascript render faster than a straight image?

I have a header that is 10px tall, and the width of the browser window. It has a stripe pattern, that is repeatable on the x-axis.
At the moment I'm using Patternizer to fill the header using Javascript and some basic stripe rules.
But would a browser that has visited the site before render that faster than it would render a 20KB image repeating on the x-axis using CSS that had already been stored in the cache?
For reference, I'm talking about the header on Markpond.
To be honest, for a 10px Header-image, a repeated background-image is just fine (unless you want a dynamic pattern or plan to change it a lot).
Since Patternizr uses a canvas-element, it will be 'slower' (to compute) on some Browsers and definitely 'slower' (to compute) mobile. There are also compatibility issues for older IE versions, but I'm not sure of the details.
But we are talking about micro optimization here. There won't be any big difference and I'm not sure why you even bother asking this question.
I recommend: Make a screenshot of your page now, load an image and kick patternizr.

What is the most efficient way to store an image? HTML/CSS/JS

I am going to have a lot of images and trying to find the most efficient way of storing these images to keep the page snappy.
So far I have thought of just the two ways: load with javascript eg picture = new Image(); picture.src = "file.jpg"; and append / remove to the page as necessary, or load into <img> and set display:none.
Are there other options? what is considered the best way to do this?
The best way for a photo gallery (if thats what you are building) is usually to have several sizes of the images, at least two:
a smallish size that is highly compressed and thus have a small footprint: this is the image you load into grids and display in a page where there are multiple images
a larger image with lower compression and higher image quality - this is the one you show when people want to see details.
Since people most often come to the detailed image from a page where the small/fast loading version has already been shown, and thus is already in the browsers cache, you do a little trick and have instant photos, without preloading anything.
It goes like this:
On the details page you show the highly compressed small image in an image tag that has the dimension of the larger detailed version. You then load the larger detailed version in the background using new Image() with an onload event attached that changes the source of the image tag with the small compressed version to the large detailed version.
It looks great, works fast and users will love you ;)
PS: the best way to store images is the browsers cache, not js or the DOM, so if you truly wish to preload images, which is generally a bad practice (tho it can be necessary sometimes), make the browser fetch them for you in the background by including a css file that references them in styles that aren't applied to visual areas of your site.
I'm not sure about "efficient", but the most logical way would be not use the JavaScript to load an image (useless if you have JavaScript disabled) or to set the image as hidden via the display property (likewise, and the browser will probably just load the image anyway).
As such, a sensible suggestion would be to use boring old paging and display 'n' images per page. However, to bring this up to date, you could use "lazy" (a.k.a. "deferred") loading and load additional page content via Ajax as the user scrolls. However, it's key that this gracefully degrades into the standard "paged" behaviour if JavaScript is disabled, etc.
The perfect example of this in operation is Google's image search, and if you search here on StackOverflow you see a discussion of possible implementations, etc.
It's better to use javascript the way that you have it and then add it to the DOM as you need, as opposed to first adding it to the to the DOM and then hiding it because DOM manipulation is much slower and you may not use some images

Using a large image (file size) but not hinder load time?

My demo is here.
Basically, I have a HUGE image (19160px × 512px to be exact, just under 2MB) that I transition the backgroundx using javascript to make it appear as if a transformation was happening.
I cannot compress the image much more without ruining its quality dramatically. Is there another way that I can achieve this with the same level of cross-browser and not rely on plugins like flash, but have it load faster?
Have you considered making this a video?
It might improve loading time somewhat.
Also, another idea. Have you tried using only the first and last image, putting the last one on top of the first, give it opacity:0 and fade it in using JavaScript (e.g. jQuery)?
The effect won't be 100% identical to what you have now, but it might look good enough to please the client, and it would reduce loading time to a bare minimum.
If both ideas won't work for you, I think the first 10-12 frames could be compressed more effectively as GIF images. (It's an estimate, I haven't tried.) You would have to split the image into multiple div s to do that and change the method you use to switch the images, and you would have more requests, but it could be worth it.
If it is a jpeg, you can always use progressive encoding. it will become clearer as it is downloaded.
There is also an interlaced
"Progressive JPEG" format, in which
data is compressed in multiple passes
of progressively higher detail. This
is ideal for large images that will be
displayed while downloading over a
slow connection, allowing a reasonable
preview after receiving only a portion
of the data. -Wikipedia
Slice it like Google Maps.
If you want to change that many pixels on the screen at once, you'll have to get them to the client somehow. You could chunk it into multiple images and use something other than background-x, but then you expose yourself to other potential network interruptions along the way.
The only alternative I can think of to precomputed images like this one is to do the computation on the client - start with the full-colour image and manipulate it using the client's CPU. Your options here involve canvas or CSS3 or a plugin.
I'm not a big fan of Flash but in this case it seems like the right tool for the job (unless you need it work on the iPhone). If you don't have the Flash authoring tool you can use the free Flex compiler.
See http://www.insideria.com/2008/03/image-manipulation-in-flex.html
Make it into an animated gif? Break it up into individual parts to remove all the area that is obscured by content.

Categories

Resources