34

I've made a mobile version of my site. When loading the page however, the site is first shown without the CSS applied, and after a second (at most) it applies the CSS and renders it properly. This behaviour is consistent across all browsers (including mobile ones).

Do you have any idea, how I could force browsers to load the CSS first (which is really tiny in size) and then render the content? I've seen something about including the CSS files outside the head, but as far as I know it's against the specs, and I am afraid such hack may brake things on some mobile browsers.

Thanks!

Update

Here's the source

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <title>Albite BOOKS mobile</title>
    <meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8"/>
    <meta name="description" content="Free e-books for Java Mobile phones."/>
    <meta name="keywords" content="free ebooks, free books, book reader, albite reader, albite books, java mobile"/>
    <meta name="language" content="en_GB"/>
    <meta name="classification" content="public"/>

    <link rel="shortcut icon" href="favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />
    <link href="/stylesheets/mobile.css?1289644607" media="screen" rel="stylesheet" type="text/css" />
  </head>
  <body>
  <!-- .... -->
  </body>
</html>
Nishant
  • 20,354
  • 18
  • 69
  • 101
Albus Dumbledore
  • 12,368
  • 23
  • 64
  • 105

5 Answers5

57

I believe I have found a better way to handle this...

At the top of your output file put the following:

<body>
  <div id="loadOverlay" style="background-color:#333; position:absolute; top:0px; left:0px; width:100%; height:100%; z-index:2000;"></div>
  ...
</body>

Then on the last line of your last loaded CSS file put:

#loadOverlay{display: none;}

This basically uses the problem against itself. The first bit of displayable html that is loaded places a blank canvas over top of everything while CSS loads and processes, the last bit of CSS to load and process removes the canvas. From my testing this solves the problem completely.

Nate Bunney
  • 2,418
  • 2
  • 22
  • 31
  • 3
    Does this affect SEO? – David Callanan Sep 27 '18 at 14:22
  • 2
    Good question and the answer is that I don't know, it would need to be tested. Thoughts: The elements of the page will load at the same speed they would otherwise, but they will be hidden from the user but not from a search engine spider. So from the spider's perspective you should get the same metrics, unless they are mapping what the user will actually see. If that is the case then it would lower SEO. This article at MOZ (https://moz.com/learn/seo/page-speed) would indicate that this practice should not hurt at all, that Google (and assumed others) are only rating on time to first byte. – Nate Bunney Sep 27 '18 at 18:55
  • 1
    However, perception of load speed IS an important metric to the users of the site. So if this cleans up a half second load time then that is not a big issue, but if you move from first perception of load at one second to four seconds then that is a big issue. – Nate Bunney Sep 27 '18 at 18:57
  • 2
    The `
    `. Put it in the body; it'll work just as fine. I tested even in IE7.
    – Marc.2377 Dec 21 '19 at 16:27
  • 2
    @Marc.2377 This is an old one, but you are right. I updated to be , Thanks! – Nate Bunney Oct 20 '21 at 21:52
5

You can ensure that an HTML element isn't displayed until its CSS is loaded with this simple technique:

// CSS
#my-div { display:block !important; }

// HTML
<div id = "my-div" style = "display:none;">

  <p>This will be display:none until the CSS is applied!</p>

</div>

Because the div tag has display:none as an inline style, it will not be displayed until after the CSS is applied. When the display:block !important rule is applied, the div's inline style will be overridden and the div will appear fully styled.

Frank
  • 2,050
  • 6
  • 22
  • 40
  • This solution violates best practices. Element-based CSS styles always have the hightest specificity. You can only override them by a rule which uses the `!important` flag. As you do in your example. But you should never use `!important` within your own code base, because `!important` makes it really difficult to override the rule another time. (Consider the case that you have several CSS classes which you might apply to the element.) Using `!important` is the first step into coding hell. – user2690527 Oct 28 '22 at 18:27
3

Nathan Bunney - good idea that ispired me, but i think better way is to remove overlay with javascript after document is fully loaded.

$(document).ready( function() {
  $("#loadOverlay").css("display","none");
});
zb226
  • 9,586
  • 6
  • 49
  • 79
mkoziol
  • 106
  • 6
  • 7
    This is worse because users with javascript disabled won't see your page at all! – jor May 07 '17 at 22:31
  • 8
    You also don't need to pull jQuery (which is incredibly heavy) to do that: `document.addEventListener('load',function(){document.getElementById("loadOverlay").style.display="none";});` – ElementW Jun 22 '17 at 20:07
  • 3
    If someone actually has javascript disabled, they can't see half the web. I personally don't worry about those folks, especially since I do most of my work in javascript frameworks. But if you wanted to you could put a warning to them using the – Nate Bunney Sep 27 '18 at 19:03
3

Have you ever used requirejs? you could set after your

requirejs.config(<confObj>);

something like this

require(Array[<all your CSS & JS >]);

requirejs will do the cache (like) stuff for you! requirejs api

2

Browsers read code from the top to the bottom, so the higher the code is on page, and how compact the code is, will affect the load time on the page. You can't really pre-load it like you would with images or something, so I would really look into caching the file, it's probably the best solution. Sorry theres no better alternative for this. But to be honest, one second load time isn't really too bad.

jub0bs
  • 60,866
  • 25
  • 183
  • 186
Blake
  • 756
  • 3
  • 16
  • 34