src/components/elements/image
// 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
// 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)'
// 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 %}
Same Ratio mock data
height: 240
width: 320
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)'
Same Ratio 16 9 mock data
height: 572
width: 1016
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)'
Same Ratio Portrait mock data
height: 360
width: 240
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)'
Different Ratio mock data
height: 240
width: 320
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)'
Retina mock data
height: 240
width: 320
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)'
Stage mock data
height: 450
width: 600
src: https://via.placeholder.com/600x450
alt: Alternative text
id: '6'
is_eager: true
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)'
Stage Small mock data
height: 205
width: 375
src: https://via.placeholder.com/375x205
alt: Alternative text
id: '7'
is_eager: true
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)'