Pictures on the web 2019

    The problem with displaying images has arisen since the advent of adaptability on the Internet. We want the site to look good on any tablet, phone, in portrait or landscape screen orientation, as well as on super-large 5K displays. Also on the market are Retina displays with a high pixel density (DPI), where regular images look blurry. The share of mobile traffic is growing, and large resources are aimed at economically loading images. Let's see how they solve these problems on the websites of Apple, Tilda and the blog platform Medium.

    Apple: background-image power user


    Apple relies on design for its products, with a strong focus on image display research. On the Apple website - at the time of this writing - image optimization is provided by CSS capabilities, more precisely, background-image. The key principle of this approach is the fixed width of the image between the breakpoints, that is, the rejection of “rubber” images. Consider the example of one of the images from the site www.apple.com/mac


    .section-imac .imac-image {
     width:939px;
     height:631px;
     background-size:939px 631px;
     background-repeat:no-repeat;
    background-image:url("/v/mac/home/af/images/overview/hero/imac__dlz2ciyr6hm6_large.jpg");
    }
    @media only screen and (-webkit-min-device-pixel-ratio: 1.5), only screen and (min-resolution: 1.5dppx), (-webkit-min-device-pixel-ratio: 1.5), (min-resolution: 144dpi) {
     .section-imac .imac-image {
      background-image:url("/v/mac/home/af/images/overview/hero/imac__dlz2ciyr6hm6_large_2x.jpg")
     }
    }
    @media only screen and (max-width: 1068px) {
     .section-imac .imac-image {
      width:795px;
      height:536px;
      background-size:795px 536px;
      background-repeat:no-repeat;
    background-image:url("/v/mac/home/af/images/overview/hero/imac__dlz2ciyr6hm6_medium.jpg")
     }
    }
    @media only screen and (max-width: 1068px) and (-webkit-min-device-pixel-ratio: 1.5), only screen and (max-width: 1068px) and (min-resolution: 1.5dppx), only screen and (max-width: 1068px) and (min-resolution: 144dpi) {
     .section-imac .imac-image {
    background-image:url("/v/mac/home/af/images/overview/hero/imac__dlz2ciyr6hm6_medium_2x.jpg")
     }
    }
    @media only screen and (max-width: 735px) {
     .section-imac .imac-image {
      width:365px;
      height:246px;
      background-size:365px 246px;
      background-repeat:no-repeat;
    background-image:url("/v/mac/home/af/images/overview/hero/imac__dlz2ciyr6hm6_small.jpg")
     }
    }
    @media only screen and (max-width: 735px) and (-webkit-min-device-pixel-ratio: 1.5), only screen and (max-width: 735px) and (min-resolution: 1.5dppx), only screen and (max-width: 735px) and (min-resolution: 144dpi) {
     .section-imac .imac-image {
    background-image:url("/v/mac/home/af/images/overview/hero/imac__dlz2ciyr6hm6_small_2x.jpg")
     }
    }
    

    For cross-browser compatibility, three methods are used to set the screen pixel density:

    -webkit-min-device-pixel-ratio: 1.5
    min-resolution: 1.5dppx
    min-resolution: 144dpi

    What are the pros and cons of this approach?

    pros


    1. Ease of implementation. This is perhaps the most understandable way to change the image to a certain size and density of the screen.
    2. Coverage of all problems: the issue of screen size and pixel density is being addressed.
    3. No jumping layout thanks to pre-fixed sizes.
    4. You can use the built-in CSS features for working with backgrounds (blend-mode for effects, position - crop the image if necessary).

    Minuses


    1. You cannot make a “rubber” picture. Fixed sizes determine the aspect ratio, so when you try to compress or stretch, we crop the picture or there is an empty space at the bottom. Yes, you can use padding-bottom in percent instead of size, but this is already a workaround, CSS hack that complicates the basic concept.
    2. Lots of CSS code. Yes, CSS is easy to read, but with a large number of breakpoints and images, the CSS size can increase indefinitely (see below “CSS preprocessors to the rescue”).
    3. There is no control over downloading images. If you use this approach in its pure form, you will load all the pictures on the page at the same time. And CSS, unlike img, does not have onload callbacks that allow you to control whether images are loaded or not.
    4. Requires meticulous accuracy. You will have to set the dimensions for all the pictures. And no less important, when replacing one image with another, you will need to edit the CSS for the new dimensions.

    CSS preprocessors to the rescue


    Most likely, you are already using one of the CSS preprocessors such as SCSS, LESS, PostCSS or Stylus - and they can greatly simplify your life. Let's try to optimize the code from the Apple website using SCSS. For media expressions, take the media mixin and write our mixin for the picture:

    @mixin image($width, $height, $url) {
      width: $width;
      height: $height;
      background-size: $width $height;
      background-repeat:no-repeat;
      background-image:url($url);
    }
    

    Let's set the variables:

    $breakpoints: (
      'phone': 735px,
      'tablet': 1068px
    );
    $media-expressions: (
      'screen': 'only screen',
      'retina': '(-webkit-min-device-pixel-ratio: 1.5), (min-resolution: 1.5dppx), (min-resolution: 144dpi)'
    );
    

    We get a SCSS that compiles one-on-one in Apple’s CSS:

    .section-imac .imac-image {
      @include image(939px, 631px, "image_large.jpg");
    }
    @include media('screen', 'retina') {
      .section-imac .imac-image {
    	@include image(939px, 631px, "image_large2x.jpg");
      }
    }
    @include media('screen', '<=tablet') {
      .section-imac .imac-image {
    	@include image(795px, 536px, "image_medium.jpg");
      }
    }
    @include media('screen', '<=tablet', 'retina') {
      .section-imac .imac-image {
    	@include image(795px, 536px, "image_medium_2x.jpg");
      }
    }
    @include media('screen', '<=phone') {
      .section-imac .imac-image {
    	@include image(365px, 246px, "image_small.jpg");
      }
    }
    @include media('screen', '<=phone', 'retina') {
      .section-imac .imac-image {
    	@include image(365px, 246px, "image_small_2x.jpg");
      }
    }
    

    Summary


    This is a great approach to live with if you don't have a lot of pictures or they rarely change.

    Tilda: background-image with blur effect


    Tilda is a site builder that provides various components for displaying images. Consider the easiest way to “lazy" upload pictures. What does html look like before loading a picture:




    The blur effect is achieved due to the fact that the preview has a small size (20x20 pixels), but with the help of the css property of the cover, the picture is stretched to the entire width and height. Minus: this blurry does not look very nice, but it is very simple and does not overload the processor.

    After loading, the full-size image is simply substituted in the inline style.

    pros


    1. Lazy loading.
    2. Easy to maintain.

    Minuses


    1. The same picture for any device. Adaptability is implemented only within the limits of stylization (the picture is simply cropped in different ways).
    2. Ugly blur effect.
    3. There is no transition between blur and full resolution.

    Summary


    This is a working method if you need a simple component and do not want to bother with six or more pictures for different screen resolutions. Good for sites with lots of pictures.

    Medium: canvas blur


    The medium.com blogging platform has made a big difference in the world of web images due to the beautiful blur effect for underloaded images. This effect is achieved using the stackblur-canvas library.




    HTML looks like a sandwich:


    This allows you to realize the effect of a smooth transition. For a full-size picture, initially opacity: 0 goes through css transition to opacity: 1.

    Blur Battle: CSS vs SVG vs Canvas


    So, if we are not Apple, most likely it will be more convenient to use lazy loading of pictures and the blur effect. At the moment there are at least three ways to create a blair effect (and another option from Tilda, but we will not consider it, since this is not a “real” blair).
    Why is it worth using stackblur-canvas for blurring if you already have a filter for blurring built into the css browser?

    1. Problems. CSS and SVG filters by default blur the edges of the image. There is a special solution for the svg filter , for the built-in filter: blur () you have to use cropping.
    2. Performance Stackblur-canvas works very fast, css filters work even faster, so with a large number of blurry images, the choice is definitely for css filters.
    3. Beauty. Here, subjectively, but in my opinion stackblur looks more beautiful. An svg filter has ugly artifacts.

    Picture tag - the pinnacle of evolution


    At the very beginning, we described the Apple method and found out that css has media expressions for both screen size and pixel density. And they can be used simultaneously to select a specific picture for display. A significant drawback is only that the picture on the background does not “know” its aspect ratio, cannot be “rubber”. In addition, from the point of view of the semantics of the web, using the background is incorrect for displaying all images in a row.

    The img tag may have an srcset attribute, but you must choose a screen size or pixel density - you cannot combine these parameters.

    The picture tag is free from this drawback, and, like img, it “knows” its aspect ratio. Already, it is supported by 92%browsers. This tag is suitable for those who can afford not to adapt to IE.

    Intersection Observer API


    Finally, let's talk about the implementation of lazy loading pictures. The classic approach is to use a combination of scroll, resize, and orientationchange events and calculate the position of a particular picture relative to the visible area of ​​the screen.

    In 2019, you can replace the set of crutches with a special browser API - intersection observer . It is supported by all modern browsers. For older iOS and IE, you should use the official w3c polyfill .

    A look into the future: what else is missing for complete happiness


    So, we already have a picture tag, which has good browser support, but the problem of lazy loading remains. We still need to rely on our own implementations based on intersection observer or a combination of JS events. When will browsers offer a native solution? For example, Chrome version 75 promises to provide support for the loading property for img and iframe tags. You can update your components for native support for lazy loading by checking the presence of a property in the prototype of the picture: if successful, you can abandon your own lazy loading code, since everything will be done by the browser for you!

    if ('loading' in HTMLImageElement.prototype)
    

    CMS and user content


    What is the best way to display images uploaded by users? As a rule, it is worth doing everything as simple as possible, without forcing him to upload pictures separately for the phone, tablet and desktop. So, we have only one picture for all devices. For such a situation, the Tilda (for maximum simplicity) or Medium approach is perfect - if you want to make a real blur effect, perhaps replacing stackblur-canvas with standard css: blur () for greater performance.

    Summary


    There is still no single, “most correct” way to display pictures. If you need to support older browsers and IE, then your choice is a background-image with media expressions and img for simple cases. For new projects, it may be more convenient to replace background-image with picture. If you want to do a beautiful lazy load, try stackblur-canvas, and if performance is important to you, then css filters or stretched pictures on a tilde-style background.

    Also popular now: