Javascript Retina / HD display detection and blocking page render during reload

242 views Asked by At

My question is pretty much about page reload rather than retina detection. I'm using the code below in head tag for retina display :

<script type="text/javascript">
               if( document.cookie.indexOf('device_pixel_ratio') == -1
                  && 'devicePixelRatio' in window
                  && window.devicePixelRatio == 2 ){

                var date = new Date();
                date.setTime( date.getTime() + 3600000000 );

                document.cookie = 'device_pixel_ratio=' + window.devicePixelRatio;
                //if cookies are not blocked, reload the page
                if(document.cookie.indexOf('device_pixel_ratio') != -1) {
                    window.location.reload(true);
                }
              }
</script>

It's detecting the visitor's screen type, then storing the cookie and reload if it's a retina display. It's working without an issue except one.

Reload function doesn't stop page rendering. Because of this, you see unstyled page on the first visit (half loaded) then refresh comes. Afterwards, everything is fine for the rest of the site since cookie is stored.

So obviously, PHP doesn't provide a function to detect screen type. It must be done through JS. But JS doesn't have the proper tool for reloading / redirecting without loading the page, even code is being used in head.

In short, I'm stuck in between. I hope someone may have a suggestion for reloading without showing any content on first load (it's even displaying inline styling that I put in head). Or displaying standard images on the first load and allowing retina for the rest of browsing experience is the best option?

By the way I tried both reload(true) and reload(false). It didn't help.


UPDATE : Please see Marat Tanalin's answer below for possible workarounds and better solutions on retina / HD display image use rather than storing cookie + reloading.

After I went deeper on this, I realized that generating both retina and standard images may not be the answer all time due to *caching methods. In other words, displaying low quality images to visitor on first visit and displaying high quality images after refresh may not work since low quality images (and scripts) already cached.

I decided to go with 1.5x single image size with SVG upload support. Although it's not 100% best answer on every aspect, much better option then losing reliability.

*I'm a Wordpress developer and I refer WP Super Cache and similar cache methods but be aware of it may be an issue on other cache methods as well.

2

There are 2 answers

5
xrisk On BEST ANSWER

Essentially, you want to stop the page from rendering till you have run this script.

This can be done using an external JS file. When the browser finds an external file, it will wait till this is run. On the other hand if you have an inline <script> tag, then the browser will not wait.

Actually, it is recommended to never block page rendering, to improve page load times, but for this purpose it is necessary. For more information, you can consult https://developers.google.com/speed/docs/insights/BlockingJS

9
Marat Tanalin On

Instead of using pure-JS solution, it's generally better practice to use CSS for styling, native HTML elements for content images, and unobtrusive JavaScript if needed. Unobtrusive JavaScript means that webpage does work even if JS is disabled.

In CSS, just use Media Queries.

For responsive images in HTML, there is the standard PICTURE element, but it's not yet widely supported, so a polyfill like picturefill may be used.

Another possible approaches for responsive images:

  • using high-resolution images always (regardless of actual pixel density; will somewhat waste traffic and provide lower image quality for users of monitors with low pixel density);

  • or using JavaScript to replace low-resolution images with their high-resolution versions on page load. To prevent loading low-res versions prior to high-res ones, low-res ones may be put into NOSCRIPT element which contents are then read dynamically and image source is extracted, modified, and NOSCRIPT element is replaced with hires image via JS.

For photographic images, an acceptable tradeoff may be using 1.5x images. Be careful with lineart images (like logos or schemes) though: they typically look best at 1:1 scale (when one image pixel exactly corresponds to one physical display pixel) and there may be evident quality loss when scaled with blur.

Also, consider using vector images in SVG format when possible — they scale without quality loss regardless of actual pixel density; though, on monitors with regular pixel density (e.g. popular Full-HD monitors compared with 4K monitors), they may have noticeably lower visual quality compared with pixel-perfect 1:1 raster images.