Bootstrap img-fluid, responsive images and the srcset sizes?

I have a hard time understanding the sizes on srcset or how to set them.
Also there is img-fluid in Bootstrap.

Lets say i have this:

<section id="listing" class="row mb-4"><!-- Listing -->
  <ul class="col-lg-12 text-center">
    <li class="mb-4">
	  <header>
        <h2 class="mb-2">Entry 1</h2>
      </header>

      <a href="https://mydomain.net/entry1">                              
        <picture>
          <source srcset="/media/frontcover_00497665dd46c88fddd1253ccd1a95c4.jpg 180w,
                          /media/frontcover_a81dcdc47d435b3f3d65823d2d137fd0.jpg 360w,
                          /media/frontcover_952d4388dada8a9265cb79206a40abe4.jpg 720w" type="image/jpeg">
                <img src="/media/frontcover_00497665dd46c88fddd1253ccd1a95c4.jpg"
                  srcset="/media/frontcover_00497665dd46c88fddd1253ccd1a95c4.jpg 180w,
                          /media/frontcover_a81dcdc47d435b3f3d65823d2d137fd0.jpg 360w,
                          /media/frontcover_952d4388dada8a9265cb79206a40abe4.jpg 720w"
                  sizes="(min-width: 900px) 1000px, (max-width: 900px) and (min-width: 400px) 50em, 50vw"
                  width="auto"
                 height="250"
                  class="img-fluid mr-3">
        </picture>
                                          
        <picture>
          <source srcset="/media/frontcover_00497665dd46c88fddd1253ccd1a95c4.jpg 180w,
                          /media/frontcover_a81dcdc47d435b3f3d65823d2d137fd0.jpg 360w,
                          /media/frontcover_952d4388dada8a9265cb79206a40abe4.jpg 720w" type="image/jpeg">
                <img src="/media/frontcover_00497665dd46c88fddd1253ccd1a95c4.jpg"
                  srcset="/media/frontcover_00497665dd46c88fddd1253ccd1a95c4.jpg 180w,
                          /media/frontcover_a81dcdc47d435b3f3d65823d2d137fd0.jpg 360w,
                          /media/frontcover_952d4388dada8a9265cb79206a40abe4.jpg 720w"
                  sizes="(min-width: 900px) 1000px, (max-width: 900px) and (min-width: 400px) 50em, 50vw"
                  width="auto"
                 height="250"
                  class="img-fluid mr-3">
        </picture>
      </a>
    </li>

    <li class="mb-4">
	  <header>
        <h2 class="mb-2">Entry 2</h2>
      </header>

      <a href="https://mydomain.net/entry2 ">                              
        <picture>
          <source srcset="/media/frontcover_00497665dd46c88fddd1253ccd1a95c4.jpg 180w,
                          /media/frontcover_a81dcdc47d435b3f3d65823d2d137fd0.jpg 360w
                          /media/frontcover_952d4388dada8a9265cb79206a40abe4.jpg 720w" type="image/jpeg">
                <img src="/media/frontcover_00497665dd46c88fddd1253ccd1a95c4.jpg"
                  srcset="/media/frontcover_00497665dd46c88fddd1253ccd1a95c4.jpg 180w,
                          /media/frontcover_a81dcdc47d435b3f3d65823d2d137fd0.jpg 360w
                          /media/frontcover_952d4388dada8a9265cb79206a40abe4.jpg 720w"
                  sizes="(min-width: 900px) 1000px, (max-width: 900px) and (min-width: 400px) 50em, 50vw"
                  width="auto"
                 height="250"
                  class="img-fluid mr-3">
        </picture>
                                          
        <picture>
          <source srcset="/media/frontcover_00497665dd46c88fddd1253ccd1a95c4.jpg 180w,
                          /media/frontcover_a81dcdc47d435b3f3d65823d2d137fd0.jpg 360w
                          /media/frontcover_952d4388dada8a9265cb79206a40abe4.jpg 720w" type="image/jpeg">
                <img src="/media/frontcover_00497665dd46c88fddd1253ccd1a95c4.jpg"
                  srcset="/media/frontcover_00497665dd46c88fddd1253ccd1a95c4.jpg 180w,
                          /media/frontcover_a81dcdc47d435b3f3d65823d2d137fd0.jpg 360w
                          /media/frontcover_952d4388dada8a9265cb79206a40abe4.jpg 720w"
                  sizes="(min-width: 900px) 1000px, (max-width: 900px) and (min-width: 400px) 50em, 50vw"
                  width="auto"
                 height="250"
                  class="img-fluid mr-3">
        </picture>
      </a>
    </li>
  </ul>
</section>

In this case i want to show two images side by side width the same height.
The second image can have different widths.

The first image is 250H x 180W and that’s the sizes you see on a normal FHD PC Monitor.
I also made 500H x 360W and 1000H x 720W for 2x and 4x device pixel radio.

I need to take out img-fluid and set width and height. If i don’t do that the picture is stretched over the whole 12 columns.

But non tutorial i did read does set a fixed width or height?

What i have in “sizes” is just a placeholder because i don’t get what to put in there.

If you write articles the pictures you place in your text can have all kind of different sizes


Also i did read that this takes the internet speed into account?
That means if somebody has a slow connection he gets the picture with the lowest resolution on his 4x device and thinks i have crappy images on my site?

Nobody?

Wow you like making life hard for yourself don’t you :slight_smile:

The picture element is mainly for art-direction in that you deliver different images at various widths/ resolutions. It’s not usually used when you just provide lower/higher quality versions of the same image. e.g. A large seascape image on desktop may be changed for a small sand-castle on small screens. Not just the large seascape made smaller or cropped badly.

Your code is giving some validator errors anyway and you need the sizes attribute on your source tag when using the format you have. You also have width=“auto” which is invalid and will have no effect. It should be like this to be valid.

 <picture>
          <source srcset="/media/frontcover_00497665dd46c88fddd1253ccd1a95c4.jpg 180w,
                          /media/frontcover_a81dcdc47d435b3f3d65823d2d137fd0.jpg 360w,
                          /media/frontcover_952d4388dada8a9265cb79206a40abe4.jpg 720w"
                          sizes="(min-width: 900px) 1000px, (max-width: 900px) and (min-width: 400px) 50em, 50vw" 
                           type="image/jpeg">
                <img src="/media/frontcover_00497665dd46c88fddd1253ccd1a95c4.jpg"
                  srcset="/media/frontcover_00497665dd46c88fddd1253ccd1a95c4.jpg 180w,
                          /media/frontcover_a81dcdc47d435b3f3d65823d2d137fd0.jpg 360w,
                          /media/frontcover_952d4388dada8a9265cb79206a40abe4.jpg 720w"
                  sizes="(min-width: 900px) 1000px, (max-width: 900px) and (min-width: 400px) 50em, 50vw"
                 alt=""
                 height="250"
                  class="img-fluid mr-3">
        </picture>

However srcset and sizes are down to the browsers discretion to choose and if you want full control you would need to use the media attribute on the source tag. The media attribute is a directive that the browsers must use if conditions are met.

This is mentioned here:

(I suggest reading that whole article a few times. :))

I am unsure of why you have duplicated the srcet in the img tag as I believed the img tag was a fallback for those that didn’t understand the picture tag or srcset attribute but I guess it may also be a fall back for those that don’t understand the source tag. (Edit: Just having looked at caniuse it may be that a few older browsers will recognise srcset but not picture but I wonder if the complexity it adds is worth the price?)

Assuming your images don’t have the same height to begin with then you would need to do this with css preferably and set the image height to the height you want. You would then set the image width to auto but not as an attribute in the image tag.

e.g.

.my-image{
height:250px;
width:auto;
}

That will make the image 250px tall and maintain its aspect ratio. It will not make the image fill the width unless it happens to match the width available. It has nothing to do with what you have set up in the html and the image displayed will be the image that was selected in the picture element. The css will then set its width to auto and its height to 250px or whatever you set it to be.

Note that your img-fluid class in bootstrap will be contrary to what you want as that sets the width to 100% and height to auto which is the reverse of what you wanted.

Also note that by setting the height of the image to 250px it may mean that the image width is massive or tiny unless you have chosen specific aspect ratio images to use and the image may overflow or be too small. If images have been set with a max-width of 100% then you may also find your images will be squashed because the height will be 250px and the width will be the max-width available and will not match the original aspect ratio.

I believe srcset takes into account bandwidth and will provide the best image available but I think that only applies when not using the picture element because the picture element should provide different pictures not just different resolutions. That’s why I was concerned about the list of srcset images in the img tag alhough I guess they are not used when browsers understand the source tag.

I find that high bandwidth images simply do not load when I have a slow connection. The whole page on my phone just freezes. I would much rather get a crappy image than no content at all.

I think the main thing to consider is that if you want different images then you use the picture element. e.g. A picture of a forest for desktop but a picture of a single tree on small screen.

If on the other hand you just want lower or higher quality versions of the exact same image then you use srcset on the img tag and not the picture element.

To be honest I have avoided using srcset or the picture image because of the complexity and indeed I often find that I have optimised the largest image to a smaller filesize than most people are using in their srcsets anyway and without much loss of quality. Optimising images is one of the most important things to handle properly and indeed you can create larger images suitable for retina devices bycreating at larger sizes and squashing smaller.

More info:
https://css-tricks.com/responsive-images-css/

I know I haven’t really answered your questions exactly as the issues are multiple and complex. The crux of the issue is that the image selection is done by the html you use but how the image will be displayed is down to your css.

If you are having trouble with one aspect of this like setting your images to a specific height then it would be helpful if you could make a live demo of the problem so that it can be debugged more easily.

My general thinking is that using well optimised images the first place will save on hundreds of lines of complex code although I do realise that sometimes this is unavoidable.

Also be aware that using srcset in some browsers means that a user may end up downloading all the images if they regularly resize their browsers window (as I do). Some browsers only do this on refresh but some do it it on resize. Also cached images may be selected by a browser even if its not the one specified in the srcset criteria (unless using the picture element of course).

As I said above I’m not an expert on picture or srcset so some of my conclusions may be a little wide of the mark. I think this article is a good resource although its a little old now.

3 Likes

Wow you really did write a lot.
Just a quick response (i will go trough it later step by step).

You need to group source and img together? And you need source for webp?

Isn’t that what its all about?
You serve the image in different sizes like i do. On a x1 device pixel radio the browser should take the “250 x 500px” image and on a x2 device the “500 x 1000px” image.

My biggest problem is that i don’t understand what values to set in “sizes”.

Then you say you need to set height/width in css. But that means inline css if images in articles have different sizes?

Here is some stuff i did read and they all use source, src and srcset in combination:

source, src and srcset:
https://responsiveimages.org/

https://nystudio107.com/blog/creating-optimized-images-in-craft-cms

source and src:
https://cloudfour.com/thinks/responsive-images-101-part-6-picture-element/
https://developer.mozilla.org/en-US/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images#Use_modern_image_formats_boldly

src and srcset:
https://css-tricks.com/planning-for-responsive-images/
https://amp.dev/documentation/guides-and-tutorials/develop/style_and_layout/art_direction/
https://bitsofco.de/the-srcset-and-sizes-attributes/
https://developer.mozilla.org/en-US/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images#Resolution_switching_Different_sizes

He says you need minimum 6/7 sizes of your image:
https://medium.com/hceverything/applying-srcset-choosing-the-right-sizes-for-responsive-images-at-different-breakpoints-a0433450a4a3

As I understand it the comma-separated list in sizes describes the size of the image in relation to the viewport or as an actual size. So in your example:

sizes="(min-width: 900px) 1000px, etc...

You are saying that at greater than 900px viewport width you are going to show a 1000px width image. The browser will then choose the best image from your srcset that meets that criteria. What width the image will actually be rendered at will also depend upon the css that you have applied in the CSS media query for 900px (if any).

Of course if you are showing fixed width images then a 1000px width image is going to be too wide for a 900px screen. I would assume that you are using flexible images but if they are a series of fixed images then you’d need to ensure they will fit in the space you allocate them for and would usually match your media query breakpoints in your css.

As I mentioned a number of times that unless you use the media attribute in the source tag of the picture element then the browser decides which image to use as it thinks best. If you use the media attribute then you are telling the browsers to use this image explicitly as in the case for art direction.

There’s a good video here explaining sizes in some detail and the picture element here


Yes that’s correct but you missed the point I was making that if you explicitly set the height to 250px for the image then its width is auto. That may be fine for your purpose so may not be an issue but if you wanted two images side by side taking up 50% of the screen then setting the height would be out of the question.

It all depends on what you are doing but it never means inline css.

Usually when you display images you are placing them inside a flexible container and the image is sized to fit the width of that container. That means when you scale up and down the image grows and shrinks.In those cases you are just using setting the image width to 100% and the height to auto (or a max-width of 100%).

Of course there will be cases where you want a fixed width image only and then change with media queries for a series of adaptive fixed widths or whatever you want but generally you would want to keep it as simple as possible.

I follow the logic but its a lot of work and (probably) most users wouldn’t notice the difference. You can make it as complex as you like but I would try to keep it as simple as possible at first.

Looking at your picture element again it seems to be mixing up the methods a bit.

You want to use the picture element for art-direction so you would use the media attribute to set the media query and that will direct the browser to choose the image (or images in that srcset). The sizes attribute will merely relate to the browser how wide compared to the viewport those list of images will be. It only needs the one size because you already have the media query in the source tag.

E.G.

 <picture>
    <source media="(min-width: 1200px)" 
  				  srcset="https://via.placeholder.com/1500 1500w,
                          https://via.placeholder.com/3000 3000w"
                          sizes="50vw" 
                         >
    <source media="(min-width: 900px)" 
  				  srcset="https://via.placeholder.com/1200 1200w,
                          https://via.placeholder.com/2400 2400w"
                          sizes="75vw" 
                         >
    <source  
  				  srcset="https://via.placeholder.com/320 320w,
                          https://via.placeholder.com/640 640w"
                          sizes="100vw" 
                         >
    <img src="https://via.placeholder.com/1000" alt="" class="img-fluid"> </picture>
  

The point with the above is that at each media query there is a completely different image because of the art direction changes but there can still be multiple copies of each image in each set to cater for retina resolution etc.

If you don’t need art-direction and just want flexible images then you do it all in the img tag using srscet and no picture at all.

e.g.

<img src="https://via.placeholder.com/1000" 
  srcset="https://via.placeholder.com/320 320w,
          https://via.placeholder.com/640 640w,
          https://via.placeholder.com/1200 1200w, 
          https://via.placeholder.com/1500 1500w, 
          https://via.placeholder.com/2400 2400w, 
          https://via.placeholder.com/3000 3000w"  
	    sizes="(min-width:900px) 75vw, 
        		(min-width:1200px) 50vw, 100vw"		
alt="" class="img-fluid">

The difference here is that they are all the same image but just at different resolutions.

Here’s a codepen so it can be tested and changed more easily.

You should see that the html media attribute and sizes queries match the css media queries. The above is a simple example and you can of course set fixed (non-changing) width images into the mix if you want but the format would be much the same.

1 Like

As i understand it you need “picture” and “source” for webp and you need to set the type=“image/webp”

With just “img src” how do you tell the browser to prefer webp if it has support for it?

But lets forget the source tag for now. I first need to figure out the sizes.
I found this generator: https://www.responsivebreakpoints.com/

My picture is 350px on a Desktop so i set Resolution “from 350 to 350” and did select “Retina Resolution”.
So for Redina (x2) i get a 700px image and the example code is telling me:
sizes= "(max-width: 700px) 100vw, 700px"

With that Firefox is downloading the 700px and not the 350px image.
It seems to work for the images that need to be 700px.
So i have to generate somehow automatically the sizes tag in my CMS?

You can see it here:
https://skulltronics.net/phantasialand-parkfuehrer-1972-und-1973

Without img-fluid the pictures never fit on phones.
This is what i want (first image set to width = “350px”):


But if i set img-fluid i get:

EDIT:
Ok, i have to put a container arround the first image like:

<div class="container px-0">
  <div class="col-12 col-sm-12 col-md-6 col-lg-6 col-lx-6 px-0 mx-auto">

    image

  </div>
</div>

Back then it was bad practice to use that much div’s anywhere


I’ll reply in detail tomorrow as out today but this code 


That code is saying that at 700px viewport width and under the image width is going to be 100vw. That means for viewport widths of 351px to 700px the 700px width image will be chosen.

At less than 351px viewport width the 350px image will be chosen unless it is a retina device then the 700px image will be chosen.

At viewport widths greater than 700px width the sizes attribute says the image will be 700px so a 700px image will be chosen unless the device is retina where it will choose a larger sized image if available in the srcset.

Yes currently you would need to use the picture element to provide fallback for webp.

If you don’t want art-direction then I believe the format is this:

<picture>
  <source srcset="imgnicepic_1.jpg 640w,
                  imgnicepic_2.jpg 768w,
                  imgnicepic_3.jpg 1024w,
                  imgnicepic_4.jpg 1366w,
                  imgnicepic_5.jpg 1600w,
                  imgnicepic_6.jpg 1920w"
                  sizes="100vw" 
                  type="image/jpeg">
    	
  <source srcset="imgnicepic_1.webp 640w,
                  imgnicepic_2.webp 768w,
                  imgnicepic_3.webp 1024w,
                  imgnicepic_4.webp 1366w,
                  imgnicepic_5.webp 1600w,
                  imgnicepic_6.webp 1920w"
                  sizes="100vw" 
                  type="image/webp">
  <img src="imgdefaultpic.jpg" alt="" class="img-fluid">
</picture>

The above just assumes that images will be at 100% viewport width but you can change the sizes attribute to match the actual css media queries you are using if you are fixing image widths at specific sizes.

If you want art direction at specific media query breakpoints then you would need the media attribute on the source tag as from my demo in post#6 but with the type attribute added and the source tag duplicated for jpg etc.

Yes when the image is set to 100% width it will then fill its container so needs to be in the appropriate structure. As you are using bootstrap then 99% of the time your content should be within the appropriate column class otherwise there’s no real point in using a framework.

Yes unnecessary tags should be kept to a minimum but there’s no harm in the odd extra div where appropriate. It’s the multiple nesting of unnecessary elements that complicate matters and should be avoided but of course frameworks come with a slight overhead on extra code in order to make the framework do its job.

I think I have answered most of your points (in one way or another) but if you have a specific question with example then perhaps we can address that in more detail rather than a general question of how things work.

All the images on this page were too small for me to read the details on the image (if I was supposed to) and in my mind it would be better to load slightly lower quality images to start with and then offer a link (or modal) to “View larger image option” so I could choose to load the higher quality image and see it properly.

As I said at the start I like to keep things simple and I would go with as few images as you can manage and make sure they are fully optimised. Some sites (like artist or graphic sites) need high quality images and users would expect the payload that they entail but most general sites do no need to go overboard with file sizes. I can rarely see the difference between a 100% jpg and an 80% jpg and most times I am interested in the content rather than the picture so perhaps I am a bad example of a visitor .:slight_smile:

Sorry for the delay. I ditched Bootstrap and made everything new. Bootstrap has to many kb.
I don’t need most of whats in there and do to much overwriting of rules. Also without it i don’t need jQuery.

So the images NEED a container? Then the right image (size) is downloaded?
I guess i can use a and set a max-width?

I still don’t get what “sizes” i need to set.

The pictures are only previews. Below them are links for hires (FHD, 4K, 8K) downloads.
These are scans from old guides from a German amusement park.

I also want the preview images to be high quality and save them as png on the server.
Then ImageMagick converts them to 80% jpg.
So it does not matter if i serve 5 or 20 images for responsiveness because ImageMagick does the work.

1 Like

You need to say what size the image will be displayed at (I think my post #9 explains it quite well).

If for example on larger screens you have 4 images across then you would say the image is 25vw. On small screen if the image is 1 across then you’d specify 25vw.

The idea is basically to follow your existing media query breakpoints as that is where you will be changing how images are displayed.

Of course you may have some images that display full width or at a fixed size so you would tailor the sizes attribute to suit.

Basically you are allowing the browser to work out the width the image will be displayed at so it can choose the best image from your list. The browser doesn’t know that you will be displaying the images 4 across the viewport but you do so that’s basically what you specify in the sizes media queries.

Responsive images and SRC sizes are really essential to get good results in SERPs, I get this all done to my website.

Then perhaps you can elaborate on the methods you used to achieve this otherwise your post is off topic.

.myImg { background-image: url(“my-image.png”); background-size: cover;}

.myImg { object-fit: cover; width: 320px; height: 180px;}

.wrapper { position: relative; padding-top: 56.25%; /* 16:9 Aspect Ratio */}

img { position: absolute; left: 0; top: 0; width: 100%; height: auto;}

img { height: auto; width: 100%;

/* even more control with max-width */ max-width: 720px;}

Why think me off topic. I am sorry.

It’s off topic because it doesn’t really address any iof the issues that are being discussed. We are talking about srcset, the picture element and the sizes attribute rather than getting good results in SERPS :slight_smile:

It’s a much more complex subject as we are discussing how the sizes attribute is used in tandem with responsive images using the srscet attribute (and picture tag) to supply multiple versions of an image in different resolutions.

If you read through the thread (as you should do before posting) you will see what has been discussed and then if you have something relevant to the topic that has not been discussed (or a correction to something that has been discussed ) then post away to your heart’s content. :wink:

1 Like

Ok, i did set my image to:

#listing article img {
  min-width: 150px;
  max-width: 150px;
  height: auto;
}

@media all and (min-width: 360px) {
  #listing article img {
    max-width: 160px;
  }
}

for this page: https://skulltronics.net/phantasialand

Without the min and max 150px the picture is to large on a 320px phone (iPhone 4s) if the heading on the left is short or gets squashed if the heading has a long word.

Now Firefox pulls the right images if i switch phones:
iPhone 4s pulls 320px because of the 2x DPR
Galaxy Note 3 pulls 480px (3x DPR)
Galaxy S9 pulls 640px (4x DPR)

That is the expected behavior.
But that means a lot of KB for Phone user who most of the time use cellular connection?

So on that site what do i do set “sizes” to?

And I’m wrong if i think that the phone should not pull just x2, x3 or x4 mages because the 160px width image on the desktop is not 160px on a phone with a viewport of 320?

That’s a design issue and I would not design the section like that for smaller screens because the words are too squashed and long words may break. I would centre the image and have the text run the full 320px underneath for smaller phones like the iphone4. What you have there is just too cramped for the smallest phones. Obviously on lager phones you could move back to the side by side layout in your media queries as required.

I believe that the ‘sizes’ attribute does allow for the UA to make a decision on slow connections on which image to serve best (mileage may vary by browser). However if you use the picture element then the browser will only choose the image you tell it to. In your example above you have wrapped the image in a picture tag but you don’t use the source tag so the picture tag is redundant I believe. Do one or the other.

The problem with retina devices is that they do require good connections and indeed the latest phones these days are as fast as desktops at accessing the web (faster when 5g rolls out). Users with the latest devices will usually be on good connections (else why purchase such a device). However I do believe that when using the sizes attribute (outside of the picture tag) the device may take into account connection time and choose an appropriate image.

You have this in your sizes attribute.

sizes="(min-width: 1366px) 160px, (min-width: 1536px) 160px, 160px"

You are saying at greater than 1366px viewport widths the image will be 160px wide.
Then you are saying if the viewport is greater than m1526px then the image width is still 160px.!! 
and then you go on to say anything outside of those media queries will be 160px width.

All you needed to say was the image will be 160px whatever the viewport size.

e.g.

sizes="160px"

A 160px image will still be 160px on a phone or whatever device you display it on. An iphone4 is 320px (but double density means its 640px) therefore every pixel of the image will cover 2 pixels on the device (basically the device maps 1px to 2px for double density). Therefore the iphone4 will choose the 320w image from your srcset list and you will not get a loss of quality in the image.

You told the device my image will never be displayed greater than 160px. You also supplied an image that was 160w and 320w (and so on). The device now knows that it has an image that will never be greater than 160px wide, the device is double density so it chooses the image that is 320w.

On a desktop or a device that is only 320px width and single density the browser would choose the 160w image.

Hope that makes sense :slight_smile:

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.