views:

1297

answers:

3

I'm using Cufon to replace the font of selected heading elements on a site I'm working on, but whenever I load a page, there is a noticeable flash of unstyled text before Cufon replaces the text. I expect that I may be doing it wrong. Here's what I have in the <head>:

<script src="/js/Monotype_Corsiva_italic_400.font.js"></script>
<script src="/js/PalatinoBoldum_700.font.js"></script>
<script>
Cufon.replace('header h1', { fontFamily: 'Monotype Corsiva' });
Cufon.replace('header h2', { fontFamily: 'Monotype Corsiva' });
Cufon.replace('aside h1', { fontFamily: 'Monotype Corsiva' });
Cufon.replace('#site-info h1', { fontFamily: 'Monotype Corsiva' });
Cufon.replace('abbr[title="My Abbreviation"]', { fontFamily: 'PalatinoBoldum' });
</script>

And here's what I have at the end of my document:

<script>
// !Cufon: replace the fonts
// --------------------------------------------
Cufon.now();
// !Track & analyze stats
// --------------------------------------------
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
// Google analytics stuff...
</script> <!-- EO Tracking -->
</body>
</html>

What am I doing wrong? Thanks in advance!

+6  A: 

The browser renders the entire page (using the standard text rendering specified in your stylesheet), then the Cufon script goes back and replaces it. Due to the way browsers render pages, and the fact that the script fires after the page's DOMLoaded event, there's no good way to avoid the momentary flash of unreplaced text.

I said no "good" way... there are bad ways to do it, like hiding the text that's going to be replaced with CSS in your main stylesheet, but that's very bad for accessibility and/or people who have scripts/flash turned off.

Currently this problem is one of the known limitations of any script/flash-based text replacement techniques.

EDIT:

The 24 ways blog had an article on using Data URIs with the CSS3 @font-face declaration to avoid the "Flash Of Unstyled Text". Basically, you embed the font data directly into the stylesheet.

While it's not pretty, it does mean the font is loaded with the CSS and is ready for use immediately. @font-face is currently supported by Safari and Firefox, and will be supported in Chrome 4 (which is getting close). IE support is limited to Microsoft's EOT format, so I count it as "not supported".

Check it out: How to use Data URIs to avoid the Flash Of Unstyled Text

Gabriel Hurley
> Currently this problem is one of the known limitations of any script/flash-based text replacement techniques.Thanks, Gabriel! I thought that might be the case, but I appreciate the confirmation.
John Stephens
+1  A: 

Hiding the headings using CSS visibility is not advisable for reasons mentioned above. IE8 also has a problem rendering the cufon text when it's hidden...

The alternative is to simply move the heading text off to the left of the screen while it's rendered, using a large negative 'text-indent' value.

  1. You need to move the headings off screen using either standard CSS within the header, or if you are worried about hiding text from people who don't have JS enabled, the CSS could be set using jquery.

    eg. '#id { text-indent: -9999px; }'

  2. Then place your cufon replacement code just before the end body tag, within a set of script tags

  3. Add a call to Cufon.now();

  4. Using the jquery .css() method, bring the headings back into view by setting a text-indent of 0

    eg. $('#id').css('text-indent', '0');

EDIT:

It seems the initial negative indent, must be set with CSS (rather than jquery) because the page needs to be fully loaded before the jquery code is called.

The danger in setting the indent via CSS, is that people who have JS turned off, won't get to see the headings at all.

If I find a reasonable solution, I'll post it here.

codeinthehole
A: 

You could use js to insert a style rule to hide the cufon'd text before the body loads...

<html>
  <head> ... </head>
  <body>
    <script> // put this at the beginning of the body

      (function(){
        var i = document.styleSheets.length,
            s = document.createElement('style');
        document.head.appendChild(s);
        document.styleSheets[i].addRule(
          'h1,h2,h3,h4,h5,h6',
          'text-indent:-9999px'
        );
      }());

    </script>

    ...

  </body>
</html>
no