Skip to main content
Home  › ... Razor

Images Tutorial

Tutorial HomeImages
#7 Responsive and optimal Server-Side Images (picture)

Browser-Capabilities picture with different formats

The perfect image depends on browser capabilities. The following example will get modern browsers a webp image (which is smaller/faster) and normal browsers a jpg.

What you need to know about picture

  1. It's just a wrapper for the img
  2. You always need an img tag inside it, and this is what old browsers like IE6 will take even if they don't understand picture
  3. The img tag also caries the alt description, width, size, styles etc. which is used for all images
  4. The source tags contain rules like type or media which the browser uses to pick the best image
  5. The source also supports the same srcset and sizes just like the img tag
  6. Important: you must use srcset and not src on the source tags
  7. Important: Order matters! Put the source tags first in the order you need, as the first match will be taken.


<picture>
  <source type="image/webp" srcset="@App.Path/img/assets/koi-400.webp">
  <source type="image/png" srcset="@App.Path/img/assets/koi-400.png">
  <img style="width: 40%;" src="@App.Path/img/assets/jellyfish-1000.jpg">
</picture>

Responsive picture with many resolutions

The perfect image is often different depending on the screen size. The following example will get two different sizes, depending on the screen size. Try resizing the screen and watch the network (F12) to see when the other sizes are loaded.

Picture srcset demo

<picture>
  <source type="image/webp"
    srcset="@App.Path/img/assets/koi-img-srcset-2000.webp 2000w,
      @App.Path/img/assets/koi-img-srcset-1000.webp 1000w,
      @App.Path/img/assets/koi-img-srcset-500.webp 500w,
      @App.Path/img/assets/koi-img-srcset-250.webp 250w,"
    sizes="(max-width: 300px) 250px, (max-width: 600px) 500px, (max-width: 1200px) 1000px, 2000px">
  <source type="image/png"
    srcset="@App.Path/img/assets/jellyfish-img-srcset-2000.jpg 2000w,
      @App.Path/img/assets/jellyfish-img-srcset-1000.jpg 1000w,
      @App.Path/img/assets/jellyfish-img-srcset-500.jpg 500w,
      @App.Path/img/assets/jellyfish-img-srcset-250.jpg 250w,"
    sizes="(max-width: 300px) 250px, (max-width: 600px) 500px, (max-width: 1200px) 1000px, 2000px">
  <img class="img-fluid" src="@App.Path/img/assets/jellyfish-img-srcset-1000.jpg" alt="Picture srcset demo">
</picture>

Automatically Resized Files & Formats


@{
  var imgSvc = GetService<IImageService>();
}
@imgSvc.Picture(App.Path + "/img/assets/jellyfish-img-srcset-2000.jpg")
This generates
<picture>
<source type='image/webp' srcset='/Portals/tutorials/2sxc/Tutorial-Razor/img/assets/jellyfish-img-srcset-2000.jpg?w=2460&amp;h=1520&amp;quality=75&amp;mode=crop&amp;scale=both&amp;format=webp 2460w,
/Portals/tutorials/2sxc/Tutorial-Razor/img/assets/jellyfish-img-srcset-2000.jpg?w=1230&amp;h=760&amp;quality=75&amp;mode=crop&amp;scale=both&amp;format=webp 1230w,
/Portals/tutorials/2sxc/Tutorial-Razor/img/assets/jellyfish-img-srcset-2000.jpg?w=922&amp;h=569&amp;quality=75&amp;mode=crop&amp;scale=both&amp;format=webp 922w,
/Portals/tutorials/2sxc/Tutorial-Razor/img/assets/jellyfish-img-srcset-2000.jpg?w=615&amp;h=380&amp;quality=75&amp;mode=crop&amp;scale=both&amp;format=webp 615w' sizes='(max-width: 1400px) 100vw,
 1230px'>
<source type='image/jpeg' srcset='/Portals/tutorials/2sxc/Tutorial-Razor/img/assets/jellyfish-img-srcset-2000.jpg?w=2460&amp;h=1520&amp;quality=75&amp;mode=crop&amp;scale=both 2460w,
/Portals/tutorials/2sxc/Tutorial-Razor/img/assets/jellyfish-img-srcset-2000.jpg?w=1230&amp;h=760&amp;quality=75&amp;mode=crop&amp;scale=both 1230w,
/Portals/tutorials/2sxc/Tutorial-Razor/img/assets/jellyfish-img-srcset-2000.jpg?w=922&amp;h=569&amp;quality=75&amp;mode=crop&amp;scale=both 922w,
/Portals/tutorials/2sxc/Tutorial-Razor/img/assets/jellyfish-img-srcset-2000.jpg?w=615&amp;h=380&amp;quality=75&amp;mode=crop&amp;scale=both 615w' sizes='(max-width: 1400px) 100vw,
 1230px'>
<img src='/Portals/tutorials/2sxc/Tutorial-Razor/img/assets/jellyfish-img-srcset-2000.jpg?w=1230&amp;h=760&amp;quality=75&amp;mode=crop&amp;scale=both' loading='lazy' class='img-fluid' width='1230' height='760'>
</picture>

Automatically Resized With Custom Alt and Classes

This is the ALT text

@imgSvc.Picture(App.Path + "/img/assets/jellyfish-img-srcset-2000.jpg", imgAlt: "This is the ALT text", imgClass: "dummy-class")
This generates
<picture>
<source type='image/webp' srcset='/Portals/tutorials/2sxc/Tutorial-Razor/img/assets/jellyfish-img-srcset-2000.jpg?w=2460&amp;h=1520&amp;quality=75&amp;mode=crop&amp;scale=both&amp;format=webp 2460w,
/Portals/tutorials/2sxc/Tutorial-Razor/img/assets/jellyfish-img-srcset-2000.jpg?w=1230&amp;h=760&amp;quality=75&amp;mode=crop&amp;scale=both&amp;format=webp 1230w,
/Portals/tutorials/2sxc/Tutorial-Razor/img/assets/jellyfish-img-srcset-2000.jpg?w=922&amp;h=569&amp;quality=75&amp;mode=crop&amp;scale=both&amp;format=webp 922w,
/Portals/tutorials/2sxc/Tutorial-Razor/img/assets/jellyfish-img-srcset-2000.jpg?w=615&amp;h=380&amp;quality=75&amp;mode=crop&amp;scale=both&amp;format=webp 615w' sizes='(max-width: 1400px) 100vw,
 1230px'>
<source type='image/jpeg' srcset='/Portals/tutorials/2sxc/Tutorial-Razor/img/assets/jellyfish-img-srcset-2000.jpg?w=2460&amp;h=1520&amp;quality=75&amp;mode=crop&amp;scale=both 2460w,
/Portals/tutorials/2sxc/Tutorial-Razor/img/assets/jellyfish-img-srcset-2000.jpg?w=1230&amp;h=760&amp;quality=75&amp;mode=crop&amp;scale=both 1230w,
/Portals/tutorials/2sxc/Tutorial-Razor/img/assets/jellyfish-img-srcset-2000.jpg?w=922&amp;h=569&amp;quality=75&amp;mode=crop&amp;scale=both 922w,
/Portals/tutorials/2sxc/Tutorial-Razor/img/assets/jellyfish-img-srcset-2000.jpg?w=615&amp;h=380&amp;quality=75&amp;mode=crop&amp;scale=both 615w' sizes='(max-width: 1400px) 100vw,
 1230px'>
<img src='/Portals/tutorials/2sxc/Tutorial-Razor/img/assets/jellyfish-img-srcset-2000.jpg?w=1230&amp;h=760&amp;quality=75&amp;mode=crop&amp;scale=both' loading='lazy'
alt='This is the ALT text' class='dummy-class img-fluid' width='1230' height='760'>
</picture>

Automatically Resized Bits with More Control



@{
  var picControlled = imgSvc.Picture(App.Path + "/img/assets/jellyfish-img-srcset-2000.jpg");
}
<picture>
  @picControlled.Sources
  @picControlled.Img.Id("some-id").Style("width: 75%").Title("Mouseover this!")
</picture>
This generates
<picture>
  <source type='image/webp' srcset='/Portals/tutorials/2sxc/Tutorial-Razor/img/assets/jellyfish-img-srcset-2000.jpg?w=2460&amp;h=1520&amp;quality=75&amp;mode=crop&amp;scale=both&amp;format=webp 2460w,
/Portals/tutorials/2sxc/Tutorial-Razor/img/assets/jellyfish-img-srcset-2000.jpg?w=1230&amp;h=760&amp;quality=75&amp;mode=crop&amp;scale=both&amp;format=webp 1230w,
/Portals/tutorials/2sxc/Tutorial-Razor/img/assets/jellyfish-img-srcset-2000.jpg?w=922&amp;h=569&amp;quality=75&amp;mode=crop&amp;scale=both&amp;format=webp 922w,
/Portals/tutorials/2sxc/Tutorial-Razor/img/assets/jellyfish-img-srcset-2000.jpg?w=615&amp;h=380&amp;quality=75&amp;mode=crop&amp;scale=both&amp;format=webp 615w' sizes='(max-width: 1400px) 100vw,
 1230px'>
<source type='image/jpeg' srcset='/Portals/tutorials/2sxc/Tutorial-Razor/img/assets/jellyfish-img-srcset-2000.jpg?w=2460&amp;h=1520&amp;quality=75&amp;mode=crop&amp;scale=both 2460w,
/Portals/tutorials/2sxc/Tutorial-Razor/img/assets/jellyfish-img-srcset-2000.jpg?w=1230&amp;h=760&amp;quality=75&amp;mode=crop&amp;scale=both 1230w,
/Portals/tutorials/2sxc/Tutorial-Razor/img/assets/jellyfish-img-srcset-2000.jpg?w=922&amp;h=569&amp;quality=75&amp;mode=crop&amp;scale=both 922w,
/Portals/tutorials/2sxc/Tutorial-Razor/img/assets/jellyfish-img-srcset-2000.jpg?w=615&amp;h=380&amp;quality=75&amp;mode=crop&amp;scale=both 615w' sizes='(max-width: 1400px) 100vw,
 1230px'>
  <img src='/Portals/tutorials/2sxc/Tutorial-Razor/img/assets/jellyfish-img-srcset-2000.jpg?w=1230&amp;h=760&amp;quality=75&amp;mode=crop&amp;scale=both' loading='lazy' class='img-fluid' width='1230' height='760' id='some-id' style='width: 75%;width: 75%' title='Mouseover this!'>
</picture>

Automatically Resized Bits with Lots of Control



@{
  var picFullControl = imgSvc.Picture(App.Path + "/img/assets/jellyfish-img-srcset-2000.jpg");
}
<picture>
  @foreach(var st in picFullControl.Sources){
    @st
  }
  <img src='@picFullControl.Src' style='width: 50%' class='border border-primary'>
</picture>
This generates
<picture>
  <source type='image/webp' srcset='/Portals/tutorials/2sxc/Tutorial-Razor/img/assets/jellyfish-img-srcset-2000.jpg?w=2460&amp;h=1520&amp;quality=75&amp;mode=crop&amp;scale=both&amp;format=webp 2460w,
/Portals/tutorials/2sxc/Tutorial-Razor/img/assets/jellyfish-img-srcset-2000.jpg?w=1230&amp;h=760&amp;quality=75&amp;mode=crop&amp;scale=both&amp;format=webp 1230w,
/Portals/tutorials/2sxc/Tutorial-Razor/img/assets/jellyfish-img-srcset-2000.jpg?w=922&amp;h=569&amp;quality=75&amp;mode=crop&amp;scale=both&amp;format=webp 922w,
/Portals/tutorials/2sxc/Tutorial-Razor/img/assets/jellyfish-img-srcset-2000.jpg?w=615&amp;h=380&amp;quality=75&amp;mode=crop&amp;scale=both&amp;format=webp 615w' sizes='(max-width: 1400px) 100vw,
 1230px'>
<source type='image/jpeg' srcset='/Portals/tutorials/2sxc/Tutorial-Razor/img/assets/jellyfish-img-srcset-2000.jpg?w=2460&amp;h=1520&amp;quality=75&amp;mode=crop&amp;scale=both 2460w,
/Portals/tutorials/2sxc/Tutorial-Razor/img/assets/jellyfish-img-srcset-2000.jpg?w=1230&amp;h=760&amp;quality=75&amp;mode=crop&amp;scale=both 1230w,
/Portals/tutorials/2sxc/Tutorial-Razor/img/assets/jellyfish-img-srcset-2000.jpg?w=922&amp;h=569&amp;quality=75&amp;mode=crop&amp;scale=both 922w,
/Portals/tutorials/2sxc/Tutorial-Razor/img/assets/jellyfish-img-srcset-2000.jpg?w=615&amp;h=380&amp;quality=75&amp;mode=crop&amp;scale=both 615w' sizes='(max-width: 1400px) 100vw,
 1230px'>
<img src='/Portals/tutorials/2sxc/Tutorial-Razor/img/assets/jellyfish-img-srcset-2000.jpg?w=1230&h=760&quality=75&mode=crop&scale=both' style='width: 50%' class='border border-primary'>
</picture>
#7 Responsive and optimal Server-Side Images (picture)

Source Code of this file

Below you'll see the source code of the file. Note that we're just showing the main part, and hiding some parts of the file which are not relevant for understanding the essentials. Click to expand the code

@inherits Custom.Hybrid.Razor12
@using ToSic.Sxc.Services;
<!-- unimportant stuff, hidden -->

Browser-Capabilities picture with... <!-- unimportant stuff, hidden -->

<!-- unimportant stuff, hidden -->


<picture>
  <source type="image/webp" srcset="@App.Path/img/assets/koi-400.webp">
  <source type="image/png" srcset="@App.Path/img/assets/koi-400.png">
  <img style="width: 40%;" src="@App.Path/img/assets/jellyfish-1000.jpg">
</picture>

<br>
<code id="demo-picture-formats-label"></code>


Responsive picture with many resolutions... <!-- unimportant stuff, hidden -->


<picture>
  <source type="image/webp"
    srcset="@App.Path/img/assets/koi-img-srcset-2000.webp 2000w,
      @App.Path/img/assets/koi-img-srcset-1000.webp 1000w,
      @App.Path/img/assets/koi-img-srcset-500.webp 500w,
      @App.Path/img/assets/koi-img-srcset-250.webp 250w,"
    sizes="(max-width: 300px) 250px, (max-width: 600px) 500px, (max-width: 1200px) 1000px, 2000px">
  <source type="image/png"
    srcset="@App.Path/img/assets/jellyfish-img-srcset-2000.jpg 2000w,
      @App.Path/img/assets/jellyfish-img-srcset-1000.jpg 1000w,
      @App.Path/img/assets/jellyfish-img-srcset-500.jpg 500w,
      @App.Path/img/assets/jellyfish-img-srcset-250.jpg 250w,"
    sizes="(max-width: 300px) 250px, (max-width: 600px) 500px, (max-width: 1200px) 1000px, 2000px">
  <img class="img-fluid" src="@App.Path/img/assets/jellyfish-img-srcset-1000.jpg" alt="Picture srcset demo">
</picture>

<code id="demo-picture-srcset-label"></code>


<hr>
<h2>Automatically Resized Files &amp Formats</h2>


@{
  var imgSvc = GetService<IImageService>();
}
@imgSvc.Picture(App.Path + "/img/assets/jellyfish-img-srcset-2000.jpg")

<code id="pic-auto-label"></code>



<hr>
<h2>Automatically Resized With Custom Alt and Classes</h2>


@imgSvc.Picture(App.Path + "/img/assets/jellyfish-img-srcset-2000.jpg", imgAlt: "This is the ALT text", imgClass: "dummy-class")

<code id="pic-auto-label"></code>


<hr>
<h2>Automatically Resized Bits with More Control</h2>

@{
  var picControlled = imgSvc.Picture(App.Path + "/img/assets/jellyfish-img-srcset-2000.jpg");
}
<picture>
  @picControlled.Sources
  @picControlled.Img.Id("some-id").Style("width: 75%").Title("Mouseover this!")
</picture>

<br>
<code id="pic-auto-control1-label"></code>


<hr>
<h2>Automatically Resized Bits with Lots of Control</h2>

@{
  var picFullControl = imgSvc.Picture(App.Path + "/img/assets/jellyfish-img-srcset-2000.jpg");
}
<picture>
  @foreach(var st in picFullControl.Sources){
    @st
  }
  <img src='@picFullControl.Src' style='width: 50%' class='border border-primary'>
</picture>

<br>
<code id="pic-auto-control2-label"></code>

<!-- unimportant stuff, hidden -->