javascript - Reduce page display flickering when using many flexbox, image icons, fonts - Stack Overflow

I have a HTML page with many uses of flexbox and a few icons div with CSS background-image.When openin

I have a HTML page with many uses of flexbox and a few icons div with CSS background-image.

When opening the HTML page (even locally, without using networking) in the browser, there is some little flickering (probably less than 100 milliseconds, but still):

  • some items move a few pixels (because of flexbox centering)

  • some icons take a few milliseconds to load

  • fonts take a few dozens of milliseconds to load, so we can see the content displayed with default font (maybe < 50 ms) and then with the right font (@font-face...)

How to ask the browser to only display/show a HTML element such as a toolbar <div class="header-toolbar"> only when it's ready to be 100% painted in a definitive way (without further moving/flickering)?

I have a HTML page with many uses of flexbox and a few icons div with CSS background-image.

When opening the HTML page (even locally, without using networking) in the browser, there is some little flickering (probably less than 100 milliseconds, but still):

  • some items move a few pixels (because of flexbox centering)

  • some icons take a few milliseconds to load

  • fonts take a few dozens of milliseconds to load, so we can see the content displayed with default font (maybe < 50 ms) and then with the right font (@font-face...)

How to ask the browser to only display/show a HTML element such as a toolbar <div class="header-toolbar"> only when it's ready to be 100% painted in a definitive way (without further moving/flickering)?

Share Improve this question edited Sep 14, 2022 at 9:15 Basj asked Sep 14, 2022 at 8:34 BasjBasj 46.6k110 gold badges459 silver badges808 bronze badges 2
  • 1 Can you please include the code of the relevant page? Specifically the part that loads the fonts. But the more, the better ;) – inwerpsel Commented Sep 20, 2022 at 13:33
  • @inwerpsel Thanks! @font-face { font-family: myfont; src: url(local-font.ttf); } – Basj Commented Sep 21, 2022 at 12:21
Add a ment  | 

5 Answers 5

Reset to default 2 +75
  1. You can use for images a specified width and height. This is also according to google insights to prevent "layout shift"

  2. As for fonts, maybe this would work

@font-face {
  font-family: "My Font";
  src: url("/fonts/My-Font.otf");
  font-display: block; /* Fix flickering */
}

or this:

<link rel="preload" href="assets/fonts/xxx.woff" as="font" type="font/woff" crossorigin>
  1. Icons are part of fonts. Maybe indeed according to @AlignItems answer have their visibility set to hidden by default, then on window load event, show them again.

  2. Background image shouldn't matter. Don't forget to set fallback background-color might prevent some flickering.

How to ask the browser to only display/show a HTML element such as a toolbar only when it's ready to be 100% painted in a definitive way (without further moving/flickering)?

One thing is very important to note: A browser does not render HTML/CSS asynchronously!

The issue is not the loading time of the HTML/CSS, instead it's the loading times of your async content (such as images/api calls/so on...)

To fix the issue you're having about the content flickering, you have 2 solutions:

  1. Use skeleton loaders. Skeleton loaders are a way to fill in contents of a page that are still being loaded asynchronously, but without losing the layout of your page which, in this case, is your issue. Learn more about this here.
  2. Decrease loading times. If you can decrease loading times of your async data, you can make it render basically instantaneously, barely (i.e. <20ms) noticing the shifting. Of course this is still not the best solution in terms of UX, but it is the fastest solution. One of the best way to decrease your load time would be to press images, or to decrease your font family sizes.

Here is another nice article that I found which could hopefully help u out even further. Good luck!

This method worked for me:

  1. First, add display: none;(opacity: 0; and visibility: hidden; works too) to your <body>.
  2. Make two functions:
function loaded() {
  // Change 'block' to default display value of your body element.
  document.querySelector('body').style.display = 'block';
}

requestAnimationFrame(loaded);

Maybe you're looking for window.onload:

.header-toolbar {
  visibility: hidden;
}

window.onload = function() {
const toolbar = document.querySelector('.header-toolbar');
toolbar.style.visibility = 'visible';
};

Or you can use a special loader, some spinner, which will be shown until window.load.

As pointed out by @Lorik: better focus on reducing layout shifts.
So optimizing all external assets is always a good idea.

Another approach could be to inline critical css in your HTML.
Critical means all css rules necessary to style the initial page view (without scrolling) a.k.a "above-the-fold" content.

This can be a tricky task, since depending on a device's viewport size, it's hard to get the ultimate critical css.

However you might find a decent promise by inlining only style rules e.g for your main nav/toolbar.

@font-face {
  font-family: MontserratWoff2;
  font-style: normal;
  font-weight: 900;
  src: url('https://fonts.gstatic./s/montserrat/v25/JTUHjIg1_i6t8kCHKm4532VJOt5-QNFgpCvC73w5aXo.woff2') format('woff2');
}

.woff2{
  font-family:MontserratWoff2;
  font-weight: 900;
}
<style>
/** 
* critical css for main toolbar
* font subset: ABCDEFGHIJKLMNOPQRSTUVWXYZ.:;?! 
*/
@font-face {
  font-family: 'MontserratSubset';
    src: url('data:font/woff2;charset=utf-8;base64,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') format('woff2');
  font-weight: 900;
  font-style: normal;
  font-display:swap;
}
  
body{
  font-size:2vw;
}

a{
  text-decoration:none;
  color:inherit;
}

.flex{
  display:flex;
  justify-content:center;
  gap:1em;
  border:1px solid #ccc;
  padding:3em;
}

.header-toolbar a{
  text-transform:uppercase;
}

.icon{
  height:1em;
  margin-right:0.333em;
  transform:translateY(0.1em)
}
  
.subset{
  font-family:MontserratWoff2, MontserratSubset;
  font-weight: 900;
}
  
</style>

<div class="flex header-toolbar woff2 subset">
  <a href="#"><svg class="icon" viewBox="0 0 448 512"><use href="#icon-calendar" /></svg>Home</a>
  <a href="#"><svg class="icon" viewBox="0 0 512 512"><use href="#icon-circle-right" /></svg>About us</a>
  <a href="#"><svg class="icon" viewBox="0 0 512 512"><use href="#icon-circle-check" /></svg>Legal notice</a>
  <a href="#"><svg class="icon" viewBox="0 0 512 512"><use href="#icon-circle-left" /></svg>Privacy policy</a>
</div>

<p class="woff2">One morning, when Gregor Samsa woke from troubled dreams, he found himself transformed in his bed into a horrible vermin. He lay on his armour-like back, and if he lifted his head a little he could see his brown belly, slightly domed and divided by arches into stiff sections.</p>


<!-- hidden svg icon assets -->

<svg width="0" height="0">
  <symbol class="icon icon-calendar" id="icon-calendar" viewBox="0 0 448 512">
    <path d="M152 64H296V24C296 10.75 306.7 0 320 0C333.3 0 344 10.75 344 24V64H384C419.3 64 448 92.65 448 128V448C448 483.3 419.3 512 384 512H64C28.65 512 0 483.3 0 448V128C0 92.65 28.65 64 64 64H104V24C104 10.75 114.7 0 128 0C141.3 0 152 10.75 152 24V64zM48 448C48 456.8 55.16 464 64 464H384C392.8 464 400 456.8 400 448V192H48V448z"></path>
  </symbol>

  <symbol class="icon icon-circle-right" id="icon-circle-right" viewBox="0 0 512 512">
    <path d="M280.2 150.2C273.1 143.8 262.1 142.2 254.3 146.1S239.1 158.5 239.1 167.1l.002 56L152 224C138.8 224 128 234.8 128 248v16C128 277.3 138.8 288 152 288L240 287.1v56c0 9.531 5.656 18.16 14.38 22c8.75 3.812 18.91 2.094 25.91-4.375l96-88.75C381.2 268.3 384 261.9 384 255.2c-.3125-7.781-2.875-13.25-7.844-17.75L280.2 150.2zM256 0C114.6 0 0 114.6 0 256s114.6 256 256 256s256-114.6 256-256S397.4 0 256 0zM256 464c-114.7 0-208-93.31-208-208S141.3 48 256 48s208 93.31 208 208S370.7 464 256 464z"></path>
  </symbol>

  <symbol class="icon icon-circle-check" id="icon-circle-check" viewBox="0 0 512 512">
    <path d="M335 175L224 286.1L176.1 239c-9.375-9.375-24.56-9.375-33.94 0s-9.375 24.56 0 33.94l64 64C211.7 341.7 217.8 344 224 344s12.28-2.344 16.97-7.031l128-128c9.375-9.375 9.375-24.56 0-33.94S344.4 165.7 335 175zM256 0C114.6 0 0 114.6 0 256s114.6 256 256 256s256-114.6 256-256S397.4 0 256 0zM256 464c-114.7 0-208-93.31-208-208S141.3 48 256 48s208 93.31 208 208S370.7 464 256 464z"></path>
  </symbol>
  
<symbol class="icon icon-circle-left" id="icon-circle-left" viewBox="0 0 512 512">
    <path d="M360 224L272 224v-56c0-9.531-5.656-18.16-14.38-22C248.9 142.2 238.7 143.9 231.7 150.4l-96 88.75C130.8 243.7 128 250.1 128 256.8c.3125 7.781 2.875 13.25 7.844 17.75l96 87.25c7.031 6.406 17.19 8.031 25.88 4.188s14.28-12.44 14.28-21.94l-.002-56L360 288C373.3 288 384 277.3 384 264v-16C384 234.8 373.3 224 360 224zM256 0C114.6 0 0 114.6 0 256s114.6 256 256 256s256-114.6 256-256S397.4 0 256 0zM256 464c-114.7 0-208-93.31-208-208S141.3 48 256 48s208 93.31 208 208S370.7 464 256 464z"></path>
  </symbol>
</svg>

In the above snippet the main nav can render the font instantly, whereas the next paragraph will render slightly delayed.

Inline font subsets as data-url

Apart from using the more efficient woff2 font format you could also add a subsetted font for the "critical letters" (used in your main nav) via data url.

This can be a suitable approach, especially if your man navigation uses only capital letter.

You can create a subsetted using a tool like transfonter
reducing the character/glyph range to e.g "ABCDEFGHIJKLMNOPQRSTUVWXYZ.:;?!"

Drawbacks
Obviously your HTML's filesize will increase.
As a result if your maintaining your code in plain HTML - readability will also suffer.

See also

  • CSS-tricks:Authoring Critical Above-the-Fold CSS
  • Jake Archibal: The future of loading CSS

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745438557a4627723.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信