Image

Information

Folder
src/components/elements/image

Files

Schema
// src/components/elements/image/schema.yaml

$schema: http://json-schema.org/draft-07/schema#
$id: /elements/image
additionalProperties: false
required:
  - src
  - alt
  - height
  - width
  - id
properties:
  is_eager:
    type: boolean
  src:
    type: string
    format: uri-reference
  alt:
    type: string
  width:
    type: number
  height:
    type: number
  style:
    type: string
  id:
    type: string
  sources:
    type: array
    items:
      type: object
      properties:
        width:
          type: number
        height:
          type: number
        srcset:
          type: string
        media:
          type: string
      required:
        - width
        - height
Mocks
// src/components/elements/image/mocks.yaml

height: 240
width: 320
src: https://via.placeholder.com/320x240
alt: Alternative text
id: '1'
$variants:
  - $name: Same Ratio
    width: 320
    height: 240
    src: https://via.placeholder.com/320x240
    alt: Alternative text
    id: '2'
    sources:
      - width: 320
        height: 240
        srcset: https://via.placeholder.com/320x240
        media: '(max-width: 1023px)'
      - width: 1024
        height: 768
        srcset: https://via.placeholder.com/1024x768
        media: '(min-width: 1024px) and (max-width: 1279px)'
      - width: 1280
        height: 960
        srcset: https://via.placeholder.com/1280x960
        media: '(min-width: 1280px)'
  - $name: Same Ratio 16 9
    width: 1016
    height: 572
    src: https://via.placeholder.com/1016x572
    alt: Alternative text
    id: '10'
    sources:
      - width: 823
        height: 463
        srcset: https://via.placeholder.com/823x463
        media: '(max-width: 1023px)'
      - width: 1016
        height: 572
        srcset: https://via.placeholder.com/1016x572
        media: '(min-width: 1024px) and (max-width: 1279px)'
      - width: 1016
        height: 572
        srcset: https://via.placeholder.com/1016x572
        media: '(min-width: 1280px)'
  - $name: Same Ratio Portrait
    width: 240
    height: 360
    src: https://via.placeholder.com/320x360
    alt: Alternative text
    id: '3'
    sources:
      - width: 240
        height: 360
        media: '(max-width: 1023px)'
        srcset: https://via.placeholder.com/1000x1500
      - width: 1024
        height: 1536
        srcset: https://via.placeholder.com/1024x1536
        media: '(min-width: 1024px) and (max-width: 1279px)'
      - width: 1280
        height: 1920
        srcset: https://via.placeholder.com/1280x1920
        media: '(min-width: 1280px)'
  - $name: Different Ratio
    width: 320
    height: 240
    src: https://via.placeholder.com/320x240
    alt: Alternative text
    id: '4'
    sources:
      - width: 320
        height: 640
        srcset: https://via.placeholder.com/320x640
        media: '(max-width: 1023px)'
      - width: 1024
        height: 768
        srcset: https://via.placeholder.com/1024x768
        media: '(min-width: 1024px) and (max-width: 1279px)'
      - width: 1280
        height: 960
        srcset: https://via.placeholder.com/1280x960
        media: '(min-width: 1280px)'
  - $name: Retina
    width: 320
    height: 240
    src: https://via.placeholder.com/320x240
    alt: Alternative text
    id: '5'
    sources:
      - width: 320
        height: 240
        srcset: >-
          https://via.placeholder.com/320x240 1x,
          https://via.placeholder.com/640x480 2x
        media: '(max-width: 1023px)'
      - width: 1024
        height: 768
        srcset: >-
          https://via.placeholder.com/1024x768 1x,
          https://via.placeholder.com/2048x1536 2x
        media: '(min-width: 1024px) and (max-width: 1279px)'
      - width: 1280
        height: 960
        srcset: >-
          https://via.placeholder.com/1280x960 1x,
          https://via.placeholder.com/2560x1920 2x
        media: '(min-width: 1280px)'
  - $name: Stage
    is_eager: true
    width: 600
    height: 450
    src: https://via.placeholder.com/600x450
    alt: Alternative text
    id: '6'
    sources:
      - width: 600
        height: 450
        srcset: https://via.placeholder.com/600x450
        media: '(max-width: 35.5625rem)'
      - width: 960
        height: 720
        srcset: https://via.placeholder.com/960x720
        media: '(min-width: 35.625rem) and (max-width: 59.9375rem)'
      - width: 1080
        height: 810
        srcset: https://via.placeholder.com/1080x810
        media: '(min-width: 60rem) and (max-width: 79.9375rem)'
      - width: 1280
        height: 960
        srcset: https://via.placeholder.com/1280x960
        media: '(min-width: 80rem)'
  - $name: Stage Small
    is_eager: true
    width: 375
    height: 205
    src: https://via.placeholder.com/375x205
    alt: Alternative text
    id: '7'
    sources:
      - width: 375
        height: 205
        srcset: https://via.placeholder.com/375x205
        media: '(max-width: 35.5625rem)'
      - width: 960
        height: 528
        srcset: https://via.placeholder.com/960x528
        media: '(min-width: 35.625rem) and (max-width: 59.9375rem)'
      - width: 1080
        height: 594
        srcset: https://via.placeholder.com/1080x594
        media: '(min-width: 60rem) and (max-width: 79.9375rem)'
      - width: 1280
        height: 704
        srcset: https://via.placeholder.com/1280x704
        media: '(min-width: 80rem)'
  - $name: Teaser
    width: 537
    height: 358
    src: https://via.placeholder.com/537x358
    alt: Alternative text
    id: '8'
    sources:
      - width: 537
        height: 358
        srcset: https://via.placeholder.com/537x358
        media: '(max-width: 35.5625rem)'
      - width: 927
        height: 618
        srcset: https://via.placeholder.com/927x618
        media: '(min-width: 35.625rem) and (max-width: 59.9375rem)'
      - width: 397
        height: 265
        srcset: https://via.placeholder.com/397x265
        media: '(min-width: 60rem) and (max-width: 79.9375rem)'
      - width: 392
        height: 262
        srcset: https://via.placeholder.com/392x262
        media: '(min-width: 80rem)'
  - $name: Teaser medium
    width: 537
    height: 358
    src: https://via.placeholder.com/537x358
    alt: Alternative text
    id: '9'
    sources:
      - width: 537
        height: 358
        srcset: https://via.placeholder.com/537x358
        media: '(max-width: 35.5625rem)'
      - width: 927
        height: 618
        srcset: https://via.placeholder.com/927x618
        media: '(min-width: 35.625rem) and (max-width: 59.9375em)'
      - width: 604
        height: 403
        srcset: https://via.placeholder.com/604x403
        media: '(min-width: 60em) and (max-width: 79.9375em)'
      - width: 600
        height: 400
        srcset: https://via.placeholder.com/600x400
        media: '(min-width: 80em)'
  - $name: Image teaser
    width: 514
    height: 514
    src: https://via.placeholder.com/514x514
    alt: Alternative text
    id: '36'
    sources:
      - width: 514
        height: 514
        srcset: https://via.placeholder.com/514x514
        media: '(max-width: 35.5625rem)'
      - width: 904
        height: 904
        srcset: https://via.placeholder.com/904x904
        media: '(min-width: 35.625rem) and (max-width: 59.9375em)'
      - width: 784
        height: 784
        srcset: https://via.placeholder.com/784x784
        media: '(min-width: 60em) and (max-width: 79.9375em)'
      - width: 784
        height: 784
        srcset: https://via.placeholder.com/784x784
        media: '(min-width: 80em)'
Template
// src/components/elements/image/image.html.twig

{% set is_lazy = not is_eager %}
{% set base64_src = "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" %}
{% set placeholder_src = is_lazy ? base64_src : src %}

{% set placeholder_image %}
  <img
    class="Image{% if is_lazy %} is-lazy{% endif %}"
    src="{{ placeholder_src }}"
    {% if is_lazy %}data-src="{{ src }}"{% endif %}
    alt="{{ alt }}"
  >
{% endset %}

{% set no_script %}
  <noscript>
    <img class="Image" src="{{ src }}" alt="{{ alt }}">
  </noscript>
{% endset %}

{% set modifier = 'FlexEmbed-ratio--' ~ id %}

{%- set default_style -%}
  .{{ modifier }} {
    {{- "padding-bottom:" ~ height / width * 100 ~ "% !important;" -}}
  }
{%- endset -%}

{%- set style = "" -%}

{% if sources is not empty %}
  {% set img %}
    {{ no_script }}
    <picture>
      {% for source in sources %}
        {% set srcset = is_lazy ? placeholder_src : source.srcset %}
        {# quickfix to add type for webp sources, to enable legacy browser to ignore them #}
        <source
          {% if "webp" in source.srcset %}type="image/webp"{% endif %}
          srcset="{{ srcset }}"
          {% if is_lazy %}data-srcset="{{ source.srcset }}"{% endif %}
          media="{{ source.media }}"
        >
        {%- set style_media -%}
          {%- if source.height and source.width and not ("webp" in source.srcset) -%}
            @media {{ source.media }} {.{{ modifier }} {
              {{- "padding-bottom:" ~ source.height / source.width * 100 ~ "% !important;" -}}
            }}
          {%- endif -%}
        {%- endset -%}
        {%- set style = style_media ~ style -%}
      {% endfor %}
      {%- set style = default_style ~ style -%}
      {{ placeholder_image }}
      {% include "@elements/image/image-script.html.twig" with {style: style} only %}
    </picture>
  {% endset %}
{% else %}
  {% set img %}
    {{ placeholder_image }}
    {% include "@elements/image/image-script.html.twig" with {style: default_style} only %}
    {{ no_script }}
  {% endset %}
{% endif %}

{% include "@elements/flex-embed/flex-embed.html.twig" with {
  "content": img,
  "modifier": modifier,
} only %}

Variants

default
Open
Alternative text
Same Ratio
Open
Alternative text
Same Ratio 16 9
Open
Alternative text
Same Ratio Portrait
Open
Alternative text
Different Ratio
Open
Alternative text
Retina
Open
Alternative text
Stage
Open
Alternative text
Stage Small
Open
Alternative text
Teaser
Open
Alternative text
Teaser medium
Open
Alternative text
Image teaser
Open
Alternative text