Search code examples
htmlcssresponsive-designresponsive-imagessrcset

Setting dimensions of <img> fallback for <source> inside <picture>, for SEO/page loading time


Using the code below, I am trying to achieve this:

  • allow the browser to choose between WEBP <source> and JPEG in<img> (as fallback)
  • display the image 754px wide for viewport widths >1058px, or, for smaller viewports, select one of the five images automatically and stretch to viewport width.
  • have an src attribute of <img> in place, which points to a low-res lazyload version
  • specify width and height of image in HTML specified for SEO/UX reasons (more below).

    <div>
    <picture>
    <source type="image/webp" 
         data-srcset="
            image_100.webp 100w, 
            image_200.webp 200w, 
            image_400.webp 400w, 
            image_600.webp 600w,
            image_754.webp 754w" 
            data-sizes="(min-width: 1058px) 1000px, 100%" />
    <img data-srcset="
            image_100.png 100w, 
            image_200.png 200w, 
            image_400.png 400w, 
            image_600.png 600w,
            image_754.png 754w" 
            data-sizes="(min-width: 1058px) 1000px, 100%" 
            src="image_min.png" width="1000" height="300" alt="image_alt" />
    </picture>
    </div>
    

Why are there a data- prefixes, you ask? I want to use a lazyloading script, which will remove them, at the right time, when the image should be displayed.

Before the lazyloading script kicks in, the browser will ignore the <source> element, because proper srcset and sizes will be absent at that point. The browser will also ignore data-srcset and data-sizes of <img>, and will, therefore, display a low-res/placeholder image as defined in src.

Knowing the image dimensions and thus w/h ratio, I also want to supply these, in HTML, so that the browser knows what space to reserve for the image during loading time, before the images are loaded, to prevent re-rendering.

Simply setting absolute values of the image into style or into width and height attributes of the <img>, are only valid for viewport width >1058px. Otherwise, the dimensions are relative to viewport size. So, I want to tell the browser, that the image will have a width 100% and height 30% of width of parent <div>, which si valid in all cases.

I know that there is a css padding-top trick, to keep aspect ratio of a div, but I'm not sure I can use it in theis scenario, since it actually creates a padding above the image.

Any other ideas on setting the fallback image dimension?


Solution

  • Ok, so a plausible answer is, after all, wrapping the <picture> in a <div> container and applying CSS, including the padding-top hack, to maintain its' aspect ratio:

    <div style="position:relative;"width:100%;padding-top:33%>
    <picture>
    <source type="image/webp" 
         srcset="
            image_100.webp 100w, 
            image_200.webp 200w, 
            image_400.webp 400w, 
            image_600.webp 600w,
            image_754.webp 754w" 
            sizes="(min-width: 1058px) 1000px, 100%" />
    <img srcset="
            image_100.png 100w, 
            image_200.png 200w, 
            image_400.png 400w, 
            image_600.png 600w,
            image_754.png 754w" 
            sizes="(min-width: 1058px) 1000px, 100%" 
            src="image_min.png" style="width:100%;height:100%;position:absolute" alt="image_alt" />
    </picture>
    </div>
    
    • CSS of the fallback <img>: width and height set to 100%, and position:absolute
    • The <div> wrapper must be CSS position:relative, for the image to be positioned inside it "absolutely".
    • The <div> must have width and padding-top set to reflect the dimensions/aspect ratio of the image.
    • The CSS does not need to be defined inline, and so the size of the div wrapper can be set differently for different viewport sizes using media queries.

    It works as follows:

    The <img> element fills up the <div> wrapper completely. Thanks to position:absolute, the padding-top of the <div> wrapper has no effect on position of the image. The percentage value of padding-top makes it relative to the element width, so aspect ratio remains constant (e.g. padding-top set to 100% would make the wrapper always square).

    The main benefit for SEO/UX:

    No matter what the sizes and the srcset values are, if the dimensions (thus aspect ratio) are known, we can create a placeholder using CSS of the fallback <img>, and so reserving space for an image which has not yet been loaded, or even chosen by the browser from the srcset.

    Ultimately this will prevent annoying changes in page layout, caused by images being painted on a page which has alreadey been rendered.