23

I've just finished creating an image upload feature and am a little disappointed.

Whilst visiting a page that contains one or more photos, I am experiencing:

  • Tedious load time (~0.5 secs).

  • Unaesthetic image loading (You can see the photo load from top to bottom).

My question is: How can I make sure the entire photo is loaded before presenting it to the user (I am trying to figure out a way to make sure the image is fully loaded before the body) without using Javascript?

Note: This question is assuming the photo is being loading from a folder cache in the same directory..

Robert Tossly
  • 613
  • 1
  • 6
  • 14
  • 1
    http://stackoverflow.com/questions/3646036/javascript-preloading-images and http://stackoverflow.com/a/14373798/747609 don't solve your problem? – IROEGBU Aug 26 '15 at 23:50
  • Are you using a CSS resize (as in does CSS scale your image for you or is it loaded automatically?) – q.Then Sep 05 '15 at 03:48

8 Answers8

16

1. Progressive JPEG

To avoid the "top to bottom" loading of an image you may use "progressive jpeg" which renders a "blurred" version of the picture during it's loading instead of "top to bottom" : Ex. : http://blog.patrickmeenan.com/2013/06/progressive-jpegs-ftw.html

2. Embedded (encoded in base64)

If you really want to show images and the page at the same time you should encode them as base64 and include them in your page :

<img src="data:image/jpeg;base64,iVBORw0KGgoAAAANSUhEUgAAADIA..." alt="" />

You can do it via PHP or any server side script.

<img src="data:image/jpeg;base64,<?=base64encode(file_get_contents($file_path))?>" alt="" />

https://en.wikipedia.org/wiki/Data_URI_scheme#Web_browser_support

3. Disguised as stylesheets (awful hack)

If you want to reaaaaally block rendering before images are loaded, you could double images in your page in a <link rel=stylesheet> tag in the <head> section of your page.

Browsers won't show the page until CSSs are loaded, even though your files are not CSS it will load and cache them, and once loaded the page will render and your images will be loaded from cache.

<html>
<head>
  <link rel="stylesheet" href="your_image_01.jpg" />
  <link rel="stylesheet" href="your_image_02.jpg" />
</head>
<body>
...
  <img src="your_image_01.jpg" alt="" />
  ...
  <img src="your_image_02.jpg" alt="" />
...
</body>
</html>
ᴇʟᴇvᴀтᴇ
  • 12,285
  • 4
  • 43
  • 66
Flunch
  • 816
  • 5
  • 17
  • About method 3: I like this hack for the "because we can"-factor (+1). Browsers block rendering until css is loaded to avoid FOUC. But can you confirm that this is guaranteed in all browsers? I tried searching the web, but could not find any specification requiring this (W3), nor could I find any source saying that all browsers do this (but also no counter-example). – Marten Koetsier Sep 04 '15 at 15:25
  • I only did a quick test in FF and Chrome that seemed to work as "expected". Can't guarantee this awful hack will work everywhere :) – Flunch Sep 07 '15 at 16:28
2

I don't think you can do it without javascript.

Partial workaround is load all images in the first page opened by the user so all images are saved into the cache, but the right way to do it is use javascript.

Why don't you want to use javascript?

Stefano P.
  • 179
  • 1
  • 9
2

Using http2/spdy will allow you to use server side pushes and will give you a server side control of when & how images can be fetched. You can try this way, but i think using javascript is an easier path.

131
  • 3,071
  • 31
  • 32
2

I've never tried that, but the fantasy tells me that you could encode uploaded image with

$im = file_get_contents('filename.gif');
$imdata = base64_encode($im);  
//taken from http://stackoverflow.com/questions/35879/base64-encoding-image

than on server request after upload validation generate inline css style and put the result as div background.

Of course enable gzip/deflate in htaccess. A litte pointless on first image appearing, but who knows...

cssBlaster21895
  • 3,670
  • 20
  • 33
1

Would using Link Prefetching accomplish what you want? It won't be perfect for every user, but it might be an easy way to accomplish what you are wanting.

https://developer.mozilla.org/en-US/docs/Web/HTTP/Link_prefetching_FAQ

For just one image: <link rel="prefetch" href="/images/big.jpeg">

For an entire page: <link rel="next" href="2.html">

For prerendering page content: <link rel="prerender" href="2.html">

These tags need to go in your sites html header section.

You might also want to consider using a CDN or a subdomain that will serve static content that does not pass headers (mostly cookies) if you are loading lots of images on the same page.

https://jack.ofspades.com/prefetching-preloading-and-prerendering-content-with-html/

Another method that might work for you: https://perishablepress.com/a-way-to-preload-images-without-javascript-that-is-so-much-better/

Derek
  • 4,864
  • 5
  • 28
  • 38
0

You cannot load images before page is opened as browser does not know what images your page will need. In order to avoid top-down loading effect without JS you can make images smaller and/or save them with interlace.

Saleniex
  • 615
  • 5
  • 4
0

Try loading it as a background of another element.

Or loading it into a hidden element (display:none).

#tinyElement{ background: url(images/picture.png) no-repeat -9999px -9999px; }

Also, see: https://css-tricks.com/snippets/css/css-only-image-preloading/

David
  • 124
  • 6
0

It is impossible to do this with just PHP (excluding methods relating to DOM loading and HTML, the recommended way would be to use a watcher and fire an event on detection of image loading completion).

There are however, ways you can speed up image loading in PHP:

Ensure that images are stored in directory and not as BLOB

If you are storing your images in some hardcoded format in your database, and not being directly accessed from your directory, then you should stop doing this. This dramatically increases load time and rendering the image.

Resizing done locally

Do a resize on the image directly before uploading it to the server. You can do this by using PHP built in functions. Something like this:

$source_imagex = imagesx($source_image);
$source_imagey = imagesy($source_image);
$dest_imagex = AVATAR_IMAGE_WIDTH;
$ratio = $dest_imagex / $source_imagex;
$dest_imagey = $ratio * $source_imagey;
$dest_image = imagecreatetruecolor($dest_imagex, $dest_imagey);
$image = imagecopyresampled($dest_image, $source_image, 0, 0, 0, 0, $dest_imagex, $dest_imagey, $source_imagex, $source_imagey);

You can calculate the pre-size image width and height and scale appropiately to maintain the aspect ratio. The constant AVATAR_IMAGE_WIDTH can be set to anything (or AVATAR_IMAGE_HEIGHT), or you can adjust the variables to your liking. This will prevent CSS having to load the DOM and load the image in full size and then resize it into whatever you want.

q.Then
  • 2,743
  • 1
  • 21
  • 31