A blog post I recently read suggested setting the sizes attribute of <img> tags automatically, using a ResizeObserver.
This would mean that at different image widths (in practice usually different breakpoints) the sizes would update each time the image resizes.
Imgix is doing something similar, and they state:
The sizes attribute was designed to give the break-points information to the browser as early as possible, typically before the images on the page have even rendered. Because imgix.js is loaded after the page's HTML markup, the browser gets the information about sizes just a tad-bit later than usual. This means that some of the performance gains from using the sizes attribute are lost, since the browser has to wait for imgix.js to load before it can make a decision.
Is this approach useful at all? Or is it wrongly using what was intended to be a static hint at image widths?
Related
We're currently building a website for mobile devices. Supported operating systems and browsers should be:
Android 4.x (Stock Browser, Google Chrome)
iOS6+ (Safari, Google Chrome)
In order to also support high resolution displays we evaluated various techniques and libraries to automatically replace images with their high-res pendants:
Attempt 1: retina.js
http://retinajs.com/
The first attempt was to use a normal <img> Tag like this: <img src="foo.png"> and use retina.js to let it automatically replace the src Attribute with the name of the retina image (foo#2x.png). This works but has 2 downsides: First, it will create unwanted overhead because both, the original as well as the retina image, would be loaded and second, if there is no retina image available it will cause lots of 404 errors on server log which we do not want.
Attempt 2: picturefill.js
https://github.com/scottjehl/picturefill
This framework uses some weird html markup based on <span> elements. For me it looks like as if the author tried to mimic the proposed <picture> element which is not a standard (yet), see http://picture.responsiveimages.org - I don't like this approach because of the weird markup. For me it doesn't make sense to semantically describe images with spans.
Attempt 3: Replace images via CSS property background-image
I see sometimes people using CSS media queries to detect retina displays and then set a background-image on a div (or similar element) with a higher or lower solution picture. I personally don't like this approach either because it completely discourages creating semantically good markup à la <img src="foo.png">. I can't imagine building a website just with div's and then set all images as background images - This just feels very weird.
Attempt 4: Set images via CSS property content:url(...)
As proposed here Is it possible to set the equivalent of a src attribute of an img tag in CSS? it seems to be possible to overwrite the src Attribute in img Tags via CSS using the property content:url(). Now, here is the plan: We set img tags for each image with a transparent blank 1x1 png referenced in its src attribute, like this: <img id="img56456" src="transp_1x1.png" alt="img description">. Now this is semantically ok and also valid against the W3C validator. Then we load a CSS Stylesheet that sets all the images on the website via Media Queries.
Example:
#img56456{content:url(foo.png)}
#media (-webkit-min-device-pixel-ratio: 2){
#img56456{content:url(foo#2x.png)}
}
Now, this approach works pretty good:
No overhead
Solid markup
Works on the required devices/browsers
SEO for Images is not requirement here
Now, could this approach cause any side effects we didn't think of? I am just asking because I know it works but kinda "feels" weird to set all images via CSS and I also found this comment on this approach on SO Is it possible to set the equivalent of a src attribute of an img tag in CSS?:
"Worth to add that even in browsers that support assigning content to
img, it changes its behavior. The image starts to ignore size
attributes, and in Chrome/Safari it loses the context menu options
like 'Save image'. This is because assigning a content effectively
converts img from empty replaced element to something like
<span><img></span>"
Could this be a problem? (I didn't notice any sizing problems and the context menu is not a requirement)
There are lots of advantages and disadvantages, but one disadvantage is that the image won't be cached. This is more of a problem on mobile devices where internet is generally slower and more expensive for the user (if on a data connection not wifi).
I don't know about those libraries but you could use media-queries, depending on how many images you have, otherwise it would be lots of code variations to write. And have a threshold screen size at which point you use a different file. Only one file is actually loaded, even though you specify both in the media-queries.
The new version of picturefill http://scottjehl.github.io/picturefill/ doesn't rely on <span> any more. Instead it simply uses the official HTML5 srcset attribute and mimics its behavior if the browser doesn't support it, so for me this is the ideal solution after quite a while now.
Using the CSS property content:url(...) was a neat little idea but it made things a little complicated and hackish too.
So, to answer my own question: No, it's a bad idea. Using the new version of picturefill is a way better solution. You can even remove it after a while when newer versions of all major browsers support the srcset attribute and you'll still be standard compliant. http://caniuse.com/#search=srcset
Example:
<img srcset="examples/images/small.jpg, examples/images/medium.jpg 2x" alt="A giant stone face at The Bayon temple in Angkor Thom, Cambodia">
<script src="picturefill.js"></script>
In my HTML5 mobile app, I am retrieving 10 images at a time from imgur (the user clicks a button to get more images). When the images are retrieved, I apply some formatting via CSS (mostly to the height and width so that it properly fits the dimensions of an iPhone).
My guess is that one of the reasons why it’s taking so long is because I’m applying formatting to the images once they’re retrieved and then showing these images. Would I be better off saving the images in the state they should be displayed with the right dimensions so I don’t have to apply any CSS to them? Would this help in getting the images to load faster?
Thanks!
According to this post, you should probably be grabbing only six at a time.
Also, open your browser's debugger, go to the NETOWRK tab and watch how long things are actually taking.
Are the images that you are loading actually bigger than the display size? If so, it will load slower not because of the CSS application, but because you are loading unnecessarily big images. You should always re-size the images that you use to the displaying size. You can also change the format and/or compression of the images to make it smaller, thus loading faster.
I don't want to set them to display:none; with media queries because they would still load. Is there any way to load them only if the device's width is over 500px for example?
You could load them all after the page itself has loaded using javascript, and ignore certain images if window.innerWidth is less than 500.
The specifics of the implementation would be determined by your own application, but I would recommend something like the following:
Replace all images with placeholders, and give the ones you may wish to hide a certain class:
<img src="placeholder.png" class="gt500" data-source="realimage.png">
You could then do something like (assuming jQuery):
$(document).ready(function(){
if(window.innerWidth > 500) { return; }
$('img.gt500').each(function() {
$(this).attr('src', $(this).data('source'));
});
});
Which will swap all the placeholders for the real images, but only if the window is wide enough.
I'd try something like this:
<img src="" data="actualimagesource" />
Check each image, either on the server or client side: If the site's width allows the image to display, pull the string from "data" and place it in the "src" attribute.
Very similar to: http://www.appelsiini.net/projects/lazyload
You can't prevent an image from loading except to delete it from the DOM or change it's src. Even then, it'll already have started loading, so whether it loads in full will depend on how the browser implements it, and I don't know the answer to that.
All I can suggest is that you prefix all the image srcs with a #, then do something like this:
var imgs = document.querySelectorAll('img[src^="#"]');
for (var i = 0; i < imgs.length; i++) {
imgs[i].setAttribute('src', imgs[i].getAttribute('src').substr(0));
}
if the screen width is greater than a certain number. That prevents users who have JavaScript disabled from seeing your images though, so consider the pros and cons carefully.
I'd probably do this server-side. WURFL is a database that's often used for mobile device sniffing, a PHP example is here. In desktop web development browser and device sniffing is considered super bad practice. For mobile, because of the sheer number of devices and their different capabilities it's often a necessity. I believe WURFL tests the user agent string server side (amongst other things) to detect the device and will then return a bunch of information about it (including screen resolution) you could then serve different sized images based on this information.
I don't think there's a way of cleanly preventing image load at the front-end. You could loop through all images with javascript on document load and set the src attribute to an empty string if their width was greater than 500px. The problem with this is that you'd have to make sure that all your images had specific dimensions in the markup and even then some browsers won't report the width until the image has finished loading. You also couldn't guarantee that images wouldn't start download before the javascript kicked in (and not all mobile devices support js or have it turned on) This feels horribly hacky to me though.
Are there any differences in performance or load/caching behavior when displaying images in img tags vs divs with image backgrounds?
My example:
I have a site with many overlapping images, some of which I will need to load dynamically with javascript. One issue is that I need to anchor the images to the right of the element, so that I can do a nice wipe-to-right effect. Because of this I was using a div with background image positioned right. Couldn't figure out how to do this with img but since divs are working for me I didn't know if this would matter...
AFAIK, browsers cache images the same whether they're in a DIV or an IMG. In any case, I think this one of those cases where specific performance is defined as an implementation detail internal to each rendering engine (and possibly the browsers built around them). As such, it's both out of our control as designers/developers and subject to change from browser to browser and version to version. In other words, I wouldn't spend too much time worrying about it.
The main performance difference is using background images allows you to use CSS sprites. Having one image contain a large number of images from your page means the user only has to make one request instead of one for each image.
Another difference is with responsive layouts. If you have an element that is only shown at certain screen widths (ie, not on mobile phones), it will still load the image if it is specified in the html (using display:none for instance), but most all browsers now will NOT load the image if is a background-image specified in unused media query-CSS rules. A lot of early responsive layouts got criticized because they still used the same bandwidth as the full size sites.
It is also useful with such designs because you can easily specify different images for different screen sizes. "Retina" displays on tablets and even laptops now won't look their best without 2x res graphics. So... even if you don't do such things now, it is probably a good practice to get into, because you might find yourself needing it soon!
I think by using background-image attribute in the div, the page layout gets loaded first and image present in the divs loaded later after the dom is loaded. so by using background-image the html layout is loaded faster on the web browser.
The only difference I can conceive of it this:
You can't scale images as backgrounds, although you can for img tags. This would open a scenario where background images loaded faster becuase it forces you to have the correct native size as opposed to downloading the entire image and scaling it. However, the converse could be true: given that you didn't care about image quality so much, you could deliver smaller imgs to your page and scale them up.
I'd stick with whatever rendered cleaner (and more consistently -- IE/FF/Chrome/Safari/etc).
Technical differences yes, most notably you can set the width/height of an IMG tag and it will stretch the image, which can be useful in some situations.
The main thing you've got to keep in mind though is the context of the image within the HTML document. If the image is content, say an image in a gallery, I'd use a IMG tag. If it is just part of the interface I might use a div instead.
I'm trying to display an iframe, which can be pointed to various urls, and would like to dynamically resize it to display its contents without a scrollbar.
How can I find those dimensions?
I don't think this is possible. Many sites resize their content to fit their container, so resizing the container to fit the content will be messy at best. Additionally, due to the single-origin policy, JavaScript won't be able to inspect the page loaded in the iframe if it comes from another site, so I don't think you'll even be able to tell if it needs to scroll or not.
You could approximate it by calculating the dimensions ahead of time, but even then it would only be a guess, since the exact size of objects in the browser is controlled only by the browser. If the user has picked a large font size, for example, there may be no size you can expand the iframe to that will be big enough for the user to see the entire page without scrolling.
You can only do it by communicating between the iframe and your website. This is the technique OpenSocial gadgets use for example. This is only possible if both the iframe and the parent are under control, in which case you can use HTML5 cross-window messaging and fall back to other cross-domain hacks if the browser can't deal with that.
You could also try to avoid the iframe by pulling the site directly and serving its content. That would only be possible for a very limited number of sites, mostly just static sites, and even then, not ideal by any means.