Table of Contents

Recipes in Image Resize Settings in 2sxc

you are here (click to zoom) - discover the stack

Version 13.10 will introduce a new ImageService which can generate advanced multi-resolution img and picture tags. As the configuration can be quite complex, it is explained here:

A Resize Recipe

A resize recipe has the following values, most of which are optional:

  • Resize Settings
    1. variants (string) - determines which variant resolutions will be provided
    2. width (int) size of the initial image before variants are applied
  • Restrictions
    1. forFactor if set, the rule will only apply to images which should be resized to this factor
    2. forCss if set, the rule will only apply to images when the page uses this Css Framework
    3. forTag if set, the rule will only apply to this tag type - either img or source
  • Additional Effects
    1. setWidth (bool) will add an appropriate width attribute to the img tag if width is known
    2. setHeight (bool) will add an appropriate height attribute to the img tag if height is known
    3. attributes (Dictionary<string, object>) lists additional tag-attributes to apply to the img tag

This is an example of a simple resize recipe:

{
  "recipe": {
    // Means the initial image will be 700px wide
    "width": 700,
    // This will generate 3 variants: 700px, 1400px and 350px
    "variants": "1*, 2*, 0.5*",
    "attributes": {
      // This will always add an img-fluid class to the img-tag
      "class": "img-fluid"
    }
  }
}
Tip

In v14.09 we updated the editor to use a JSON schema, so you should now get intellisense 😉.

Variants

variants is a string which tells us which variants to generate. It is comma-separated. There are three different ways to specify the variants:

  1. By multiplier - marked by * or no trailing character
    1. 1* means the original image will be used
    2. 2* means the image will be resized to 2 times its original size
    3. 0.5* means the image will be resized to half its original size
  2. By Pixel size marked by w
    1. 700w means the image will be resized to 700px wide
    2. 1400w means the image will be resized to 1400px wide
    3. 350w means the image will be resized to 350px wide
  3. By Screen Pixel Density marked by x
    1. 1x means the image will be used as is, for normal screen pixel density
    2. 2x means the image will be douled in size for 2x screen pixel density
    3. 3x means the image will be trippled in size for 3x screen pixel density
Warning

It's tempting to mix these, but only * and w can be combined. Trying to combine x (pixel density) with any of the others results in an invalid configuration which the browser cannot handle. It will not generate an error, but the browser will usually then just ignore the x variants.

Adding Many Recipes

A perfect resizing system must actually behave differently in many scenarios. Here are some reasons, why we need many recipes:

  1. If we use Bootstrap5 we may want to add the class img-fluid, but not if we use Tailwind
  2. If we want an image that fits 1/2 the content-area and we have Bootstrap5, then 100% is 1230px, but a 50% image is 600px because of paddings

So a really amazing configuration will need a LOT of recipes - easily 10-20 per CssFramework. This is how it's done:

{
  // Default Recipe
  "recipe": {
    "width": 1400,
    "variants": "1*, 2*, 0.5*",
    "setWidth": true,
    // Sub-Recipes, which inherit all the settings from main, unless they override it
    "recipes": [
      {
        // This section would only affect Bootstrap5
        "forCss": "bs5",
        "width": 1230,
        "attributes": {
          "class": "img-fluid"
        },
        // Sub-Sub-Recipes, which inherit from the BS5 and from main, unless they override it
        "recipes": [
          { "forFactor": "1", "width": 1230 },
          { "forFactor": "1/2", "width": 600 },
          { "forFactor": "12/3", "width": 400 },
          { "forFactor": "12/4", "width": 300 }
        ]
      },
      {
        // This section would only affect non-Bootstrap5, as that would match first
        "setWidth": false,  // override default to false
        "attributes": {
          "class": "img"
        }
      }
    ]
  }
}
Tip

Sub-Recipes inherit everything from the parents. This is so you are DRY - you don't have to repeat yourself.

It's important to know that at runtime this is flattened to a table. So the hierarchy you see in the JSON is purely to make the configuration easier to write.

Tip

Attributes are cummulative, so if a parent-node has attributes and a child-node has other attributes, they will be merged. Child node attributes will replace parent node attributes. To reset an attribute which the parent had set already, use null on the child node.


Recipe in Content for 2sxc v14-v18

This is just for your info, in case you want to create your own based on this.

{
  "recipe": {
    "name": "default",
    "variants": "2*, 1*, 3/4*, 1/2*",
    "setWidth": false,
    "attributes": {
      "loading": "lazy"
    },
    "recipes": [
      {
        "name": "Bootstrap3",
        "forCss": "bs3",
        "attributes": { "class": "img-responsive" },
        "setWidth": false
      },
      {
        "name": "Bootstrap4",
        "forCss": "bs4",
        "attributes": { "class": "img-fluid" },
        "setWidth": true
      },
      {
        "name": "Bootstrap5",
        "forCss": "bs5",
        "attributes": { "class": "img-fluid" },
        "setWidth": true,
        "setHeight" : true,
        "recipes": [
          { 
            "forFactor": "12/12", 
            "width": 1230,
            "attributes":{
              "sizes": "(max-width: 1400px) 100vw, 1230px"
            }
          },
          { "forFactor": "11/12", "width": 1100 },
          { "forFactor": "10/12", "width": 1000 },
          { "forFactor": "9/12", "width": 900 },
          { "forFactor": "8/12", "width": 800 },
          { "forFactor": "7/12", "width": 700 },
          { 
            "forFactor": "6/12", 
            "width": 600, 
            "attributes": {
              "sizes": "(max-width: 1400px) 50vw, (max-width: 576px) 100vw, 600px" 
              }
          },
          { "forFactor": "5/12", "width": 500 },
          { 
            "forFactor": "4/12", 
            "width": 390,
            "attributes":{
              "sizes": "(max-width: 1400px) 34vw, (max-width: 991px) 50vw, (max-width: 575px) 100vw, 390px"
            }
           },
          { 
            "forFactor": "3/12", 
            "width": 285,
            "attributes": {
              "sizes": "(max-width: 1400px) 25vw, (max-width: 991px) 50vw, (max-width: 575px) 100vw, 285px"
              }
          },
          { "forFactor": "2/12", "width": 170 },
          { "forFactor": "1/12", "width":  75 }
        ]
      }
    ]
  }
}

History

  • Advanced Json configuration with Recipe added in v13.05, to be released v13.10