Jon Aquino's Mental Garden

Engineering beautiful software jon aquino labs | personal blog

Saturday, February 24, 2007

Workaround for the Safari FOUC bug

The Safari browser occasionally exhibits the dreaded Flash of Unstyled Content (FOUC) bug, in which the webpage is unstyled black-on-white text for a second or two before the styles kick in. This happens because Safari loads CSS and JavaScript in parallel - if the JavaScript accesses certain properties, it triggers a page render in Safari, even if the CSS hasn't fully loaded. Hence, the Flash of Unstyled Content. (Firefox does not suffer from this because it loads CSS and JavaScript in series rather than in parallel).

A workaround is to hide the body before the CSS files have loaded, and show the body afterwards:

body { display: none; }

body { display: block; }

Save these lines as safari-fouc-workaround-1.css and safari-fouc-workaround-2.css, respectively. Then place the following at the top of the <head> section, before your CSS declarations:

<link rel="stylesheet" type="text/css" media="screen" href="/safari-fouc-workaround-1.css" />

And after your CSS declarations, at the bottom of the <head> section, put:

<link rel="stylesheet" type="text/css" media="screen" href="/safari-fouc-workaround-2.css" />

(Even better, add these lines only if you detect that the browser is Safari.)

Update: The best way to implement this workaround is as follows:

Put the following in <head>:

<?php
if (strpos($_SERVER['HTTP_USER_AGENT'], 'Safari') !== FALSE) { ?>
<!-- First part of FOUC workaround -->
<style type="text/css">body { display: none; }</style>
<?php
}
and the following at the end of your main CSS file:
/* Second part of FOUC workaround */
body { display: block; }

31 Comments:

  • Update: To save an HTTP request, the first statement can be done inline rather than in a separate file.

    <style type="text/css">body { display: none; }</style>

    By Blogger Jonathan, at 2/26/2007 11:49 a.m.  

  • This didn't work for me at first but when I created two inline styles and put one in the header just after the "title" tag and the other just BEFORE the "/html" tag (closing html tag) then everything worked; I no longer get the 'flash'.

    Yours a fairly elegant solution that I've spent much time looking for. Thanks.

    By Anonymous Anonymous, at 4/12/2007 9:48 a.m.  

  • Hey Varen - super!

    By Blogger Jonathan, at 4/12/2007 8:38 p.m.  

  • Actually I am finding that, rather than putting "body { display: block; }" in a separate file, it is better to put it at the end of your main css file. This will ensure that, in Safari, the page will not display anything until the main css file finishes loading.

    By Blogger Jonathan, at 5/02/2007 6:44 p.m.  

  • Here's the PHP code for what goes at the top:

    if (mb_strpos($_SERVER['HTTP_USER_AGENT'], 'Safari') !== FALSE) { ?>
    <style type="text/css">body { display: none; }</style>
    <?php
    }

    By Blogger Jonathan, at 5/03/2007 11:49 p.m.  

  • Hi Jonathan, I also found that using your snippet of php in the header to set display none for safari and just having body { display:block; } at the end of my master stylesheet was the only was to stop the fouc, great fix thanks man!

    By Anonymous Anonymous, at 12/08/2007 8:57 p.m.  

  • Cool!

    By Blogger Jonathan, at 12/08/2007 9:18 p.m.  

  • Thanks Jonathan and Varen.
    I tried Varen's adaptation and this worked beautifully!

    By Anonymous Anonymous, at 5/10/2008 10:07 a.m.  

  • Glad you found it useful!

    By Blogger Jonathan, at 5/10/2008 10:10 a.m.  

  • that is like my nightmares ended...
    that works nice in IE too!!!

    thanks a lot!

    By Anonymous Anonymous, at 9/12/2008 6:43 a.m.  

  • You're welcome, Jean!

    By Blogger Jonathan, at 9/13/2008 7:22 p.m.  

  • Hey Jonathan! First thank you for this workaround. I have tried your code but it doesn't work for me. I'm using Safari 4.0 and when i'm previewing my site in safari i see this white flash between pages. Can you some how show me an example of some code with your implemented workaround or just point me a link.I'll be very thankful.

    By Blogger IronSpider Clothing and Design, at 6/27/2009 11:24 a.m.  

  • Hi Antoniya—We’re using it for Ning sites, e.g., http://accp.ning.com/.

    What’s the URL of your site?

    By Blogger Jonathan, at 6/27/2009 12:32 p.m.  

  • some how i cant find the snippet on your page (i'm not the best web master heheh). my site is http://ironspiderart.com/demo/index.html and if you can offer me some solution it will be great. thank you in advance

    By Blogger IronSpider Clothing and Design, at 6/27/2009 1:13 p.m.  

  • Actually it’s weird—I see the “body { display: none; }” and “body { display: block; }” when I do View Source on Chrome but not on Safari 3.2.1 for Windows. Do you see the two lines when you do View Source?

    By Blogger Jonathan, at 6/27/2009 1:24 p.m.  

  • no nothing here my page is clear . i was trying and maybe the site needs time to refresh but now is without any workaround. im using safari 4.0 with mac

    By Blogger IronSpider Clothing and Design, at 6/27/2009 1:30 p.m.  

  • k—make sure those two lines appear on Safari, and hopefully the Flash Of Unstyled Content will go away.

    By Blogger Jonathan, at 6/27/2009 6:36 p.m.  

  • i think i'm inserting them not on the right place and i'm not shure if i have to insert the php code also. is there a chance that you can insert this lines in my website code and send them back to me??
    i'll really appreciate this . i hope i'm not causing you extra job :)

    By Blogger IronSpider Clothing and Design, at 6/27/2009 7:30 p.m.  

  • Will do.

    By Blogger Jonathan, at 6/27/2009 9:37 p.m.  

  • I used this work around perviously for version 2 + 3 of safari and it worked well. However the FOUC bug does not seem to like this fix when using Safari 4. The exact same pages now show the FOUC behavior in Safari 4.

    Any other suggestions? Thanks

    By Anonymous Anonymous, at 7/17/2009 3:56 p.m.  

  • Alas!

    By Blogger Jonathan, at 7/17/2009 7:39 p.m.  

  • It's exactly what i was looking for the last 8 hours but when i red to the bottom of the thread I realized that it doesn't work anymore for Safari 4. Let me know if see or come up with any other solution for it? I would greatly appreciate it.

    By Anonymous Anonymous, at 7/21/2009 10:07 a.m.  

  • CAVEAT: Putting the second inline style tag between the closing body and html tags will lead to invalid (X)HTML. Nothing should go between these tags.

    By Anonymous Anonymous, at 8/06/2009 1:56 p.m.  

  • Just fixed my problem with the white flash which is seen just before loading a page with a dark background.

    In the opening html tag add the background color you want.

    (Turn the symbols >< around, I couldn't post these lines otherwise because of the html tags)

    >html style="background-color:#000000;"<

    so this works for me in a standard opening html tag:

    >html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en" style="background-color:#000000;"<

    By Anonymous Peter, at 10/15/2009 3:18 a.m.  

  • Nice one, Peter!

    By Blogger Jonathan, at 10/15/2009 8:00 p.m.  

  • This comment has been removed by the author.

    By Blogger Madeck, at 3/27/2010 4:35 p.m.  

  • The FOUC also appears on Chrome, so having the php condition is probably not the best solution.

    Anyway, as some people pointed out, it seems the trick is not working anymore...

    [EDIT]
    However, it seems that having body, html instead of only body does the trick!

    By Blogger Madeck, at 3/27/2010 4:39 p.m.  

  • Ah, interesting.

    By Blogger Jonathan, at 3/27/2010 6:02 p.m.  

  • Cheers... this saved me some time!

    By Blogger james, at 4/20/2010 12:42 p.m.  

  • Actually I am finding that, rather than putting "body { display: block; }" in a separate file, it is better to put it at the end of your main css file.
    Desert Safari

    By Blogger Unknown, at 12/25/2012 2:17 a.m.  

  • 1. I would not do this hack in 2014. If you are doing the hack, I would recommend removing it.

    2. Put js scripts at the bottom of your page, not at the top. The running of the js scripts will block the rest of the page from rendering.

    By Blogger Jonathan, at 8/06/2014 7:48 p.m.  

Post a Comment

<< Home