image

Image Styles

Whenever Drupal needs to provide an image in specific dimenions, FE needs to provide an image style.

Create a file in /.tools/es/responsive_image and define the height and width of the image for each breakpoint. Afterwards run phab scaffold .tools/es/index.yml to create the image styles. They are getting created in /config/sync. Don't forget to commit them and let the BE devs know what the relevant file is.

To see the changes locally:

  1. the configurations generated above must be imported via:
    phab -cmbb drush cim
    
  2. image's cache has to be cleaned via (press 1 when you are prompted to):
    phab -cmbb drush 'image-flush --all'
    
  3. clean cache via:
    phab -cmbb drush cr
    

Troubleshooting:

If you get any php errors during running phab scaffold .tools/es/index.yml you might need to update the scaffolder via composer update factorial-io/phab-entity-scaffolder

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
type: object
required:
  - uri
  - width
  - height
  - alt
properties:
  uri:
    type: string
    format: uri-reference
  width:
    type: number
  height:
    type: number
  alt:
    type: string
  picture_classes:
    type: array
    items:
      type: string
  sources:
    type: array
    items:
      type: object
      properties:
        srcset:
          type: string
        media:
          type: string
        size:
          type: string
          enum:
            - xs
            - sm
            - md
            - lg
            - xl
            - xxl
        width:
          type: number
        height:
          type: number
      required:
        - srcset
        - media
        - size
        - width
        - height
  classes:
    type: array
    items:
      type: string
  wrapper_classes:
    type: array
    items:
      type: string
  is_lazy:
    type: boolean
Mocks
// src/components/elements/image/mocks.yaml

uri: https://via.placeholder.com/320x240
height: 240
width: 320
alt: Sample alt text
$variants:
  - $name: src with lazy
    is_lazy: true
  - $name: srcset with same ratio
    uri: https://via.placeholder.com/320x240
    alt: alt text
    sources:
      - srcset: https://via.placeholder.com/2560x1920
        media: '(min-width: 100em)'
        size: xxl
        height: 1920
        width: 2560
      - srcset: https://via.placeholder.com/1440x1080
        media: '(min-width: 80em) and (max-width: 99.9375em)'
        size: xl
        height: 1080
        width: 1440
      - srcset: https://via.placeholder.com/1024x768
        media: '(min-width: 64em) and (max-width: 79.9375em)'
        size: lg
        height: 768
        width: 1024
      - srcset: https://via.placeholder.com/768x576
        media: '(min-width: 48em) and (max-width: 63.9375em)'
        size: md
        height: 576
        width: 768
      - srcset: https://via.placeholder.com/570x427
        media: '(max-width: 47.9375em)'
        size: sm
        height: 427
        width: 570
  - $name: srcset with different ratio
    uri: https://via.placeholder.com/320x240
    alt: alt text
    sources:
      - srcset: https://via.placeholder.com/2560x120
        media: '(min-width: 100em)'
        size: xxl
        height: 120
        width: 2560
      - srcset: https://via.placeholder.com/1440x1080
        media: '(min-width: 80em) and (max-width: 99.9375em)'
        size: xl
        height: 1080
        width: 1440
      - srcset: https://via.placeholder.com/1024x768
        media: '(min-width: 64em) and (max-width: 79.9375em)'
        size: lg
        height: 768
        width: 1024
      - srcset: https://via.placeholder.com/576x768
        media: '(min-width: 48em) and (max-width: 63.9375em)'
        size: md
        height: 768
        width: 576
      - srcset: https://via.placeholder.com/427x570
        media: '(max-width: 47.9375em)'
        size: sm
        height: 570
        width: 427
  - $name: srcset with lazy loading
    is_lazy: true
    uri: https://via.placeholder.com/320x240
    alt: alt text
    sources:
      - srcset: https://via.placeholder.com/2560x1920
        media: '(min-width: 100em)'
        size: xxl
        height: 1920
        width: 2560
      - srcset: https://via.placeholder.com/1440x1080
        media: '(min-width: 80em) and (max-width: 99.9375em)'
        size: xl
        height: 1080
        width: 1440
      - srcset: https://via.placeholder.com/1024x768
        media: '(min-width: 64em) and (max-width: 79.9375em)'
        size: lg
        height: 768
        width: 1024
      - srcset: https://via.placeholder.com/576x768
        media: '(min-width: 48em) and (max-width: 63.9375em)'
        size: md
        height: 768
        width: 576
      - srcset: https://via.placeholder.com/427x570
        media: '(max-width: 47.9375em)'
        size: sm
        height: 570
        width: 427
  - $name: 16x9
    uri: https://via.placeholder.com/720x406?text=16x9
    height: 406
    width: 720
    alt: Sample alt text
  - $name: 3x4
    uri: https://via.placeholder.com/256x342?text=3x4
    height: 256
    width: 342
    alt: Sample alt text
  - $name: 16x9_9x16
    uri: https://via.placeholder.com/1584x891?text=16x9
    width: 1584
    height: 891
    sources:
      - srcset: https://via.placeholder.com/1584x891?text=16x9
        media: '(min-width: 100em)'
        size: xxl
        width: 1584
        height: 891
      - srcset: https://via.placeholder.com/1584x891?text=16x9
        media: '(min-width: 80em) and (max-width: 99.9375em)'
        size: xl
        width: 1584
        height: 891
      - srcset: https://via.placeholder.com/1584x891?text=16x9
        media: '(min-width: 64em) and (max-width: 79.9375em)'
        size: lg
        width: 1584
        height: 891
      - srcset: https://via.placeholder.com/1406x2500?text=9x16
        media: '(min-width: 48em) and (max-width: 63.9375em)'
        size: md
        width: 1406
        height: 2500
      - srcset: https://via.placeholder.com/1406x2500?text=9x16
        media: '(max-width: 47.9375em)'
        size: sm
        width: 1406
        height: 2500
  - $name: 2x1_9x16
    uri: https://via.placeholder.com/768x1365
    alt: alt text
    sources:
      - srcset: https://via.placeholder.com/1440x720
        media: '(min-width: 100em)'
        size: xxl
        height: 720
        width: 1440
      - srcset: https://via.placeholder.com/1440x720
        media: '(min-width: 80em) and (max-width: 99.9375em)'
        size: xl
        height: 720
        width: 1440
      - srcset: https://via.placeholder.com/1024x512
        media: '(min-width: 64em) and (max-width: 79.9375em)'
        size: lg
        height: 512
        width: 1024
      - srcset: https://via.placeholder.com/768x1365
        media: '(min-width: 48em) and (max-width: 63.9375em)'
        size: md
        height: 768
        width: 1365
      - srcset: https://via.placeholder.com/569x1012
        media: '(max-width: 47.9375em)'
        size: sm
        height: 1012
        width: 569
  - $name: 9x16
    uri: /build/assets/img/dummy/9x16.webp
    height: 626
    width: 375
    alt: Sample alt text
  - $name: 9x16_picture
    uri: /build/assets/img/dummy/9x16.webp
    alt: ''
    sources:
      - srcset: /build/assets/img/dummy/story-slider/intro-slide.webp
        media: '(min-width: 200em)'
        size: xxl
        height: 626
        width: 375
  - $name: Story slider intro slide
    uri: /build/assets/img/dummy/story-slider/intro-slide.webp
    height: 626
    width: 375
    alt: Sample alt text
  - $name: Story slider picture
    uri: /build/assets/img/dummy/story-slider/intro-slide.webp
    alt: Sample alt text
    picture_classes:
      - StorySliderSlideIntro-introImage
    sources:
      - srcset: /build/assets/img/dummy/story-slider/intro-slide.webp
        media: '(min-width: 200em)'
        size: xxl
        height: 626
        width: 375
  - $name: Avatar
    uri: /build/assets/img/dummy/avatar/6.webp
    width: 200
    height: 200
  - $name: benefit overview
    uri: https://via.placeholder.com/566x454?text=Benefit+Overview
    alt: alt text
    width: 566
    height: 454
  - $name: benefit 1
    uri: https://via.placeholder.com/626x770?text=Benefit+1
    alt: alt text
    width: 626
    height: 770
  - $name: benefit 2
    uri: https://via.placeholder.com/831x709?text=Benefit+2
    alt: alt text
    width: 831
    height: 709
  - $name: benefit 3
    uri: https://via.placeholder.com/589x657?text=Benefit+3
    alt: alt text
    width: 589
    height: 657
  - $name: benefit 4
    uri: https://via.placeholder.com/482x560?text=Benefit+4
    alt: alt text
    width: 482
    height: 560
  - $name: benefit 5
    uri: https://via.placeholder.com/775x775?text=Benefit+5
    alt: alt text
    width: 775
    height: 775
  - $name: Mixed story slide
    uri: /build/assets/img/dummy/story-slider/mixed287x216.webp
    height: 216
    width: 287
    alt: Sample alt text
Template
// src/components/elements/image/image.twig

{% if sources and sources is not empty %}
	<picture {% if picture_classes %}class="{{ picture_classes|join(" ") }}"{% endif %}>
		{% for source in sources %}
			<source
				{% if source.type %}
					type="{{ source.type }}"
				{% endif %}
				{% if source.media %}
					media="{{ source.media }}"
				{% endif %}
				{% if source.width %}
					width="{{ source.width }}"
				{% endif %}
				{% if source.height %}
					height="{{ source.height }}"
				{% endif %}
				srcset="{{ source.srcset }}"
			>
		{% endfor %}
		<img
			{% if classes %}
				class="{{ classes|join(" ") }}"
			{% endif %}
			src="{{ uri }}"
			alt="{{ alt }}"
			{% if alt == "" %}
				aria-hidden="true"
			{% endif %}
			{% if width %}
				width="{{ width }}"
			{% endif %}
			{% if height %}
				height="{{ height }}"
			{% endif %}
			{% if is_lazy %}
				loading="lazy"
				decoding="async"
			{% elseif is_priority %}
				fetchpriority="high"
			{% endif %}
		>
	</picture>
{% else %}
	<img
		{% if classes %}
			class="{{ classes|join(" ") }}"
		{% endif %}
		src="{{ uri }}"
		alt="{{ alt }}"
		{% if alt == "" %}
			aria-hidden="true"
		{% endif %}
		{% if width %}
			width="{{ width }}"
		{% endif %}
		{% if height %}
			height="{{ height }}"
		{% endif %}
		{% if is_lazy %}
			loading="lazy"
			decoding="async"
		{% elseif is_priority %}
			fetchpriority="high"
		{% endif %}
	>
{% endif %}

Variants

default
Open
Sample alt text
src with lazy
Open
Sample alt text
srcset with same ratio
Open
alt text
srcset with different ratio
Open
alt text
srcset with lazy loading
Open
alt text
16x9
Open
Sample alt text
3x4
Open
Sample alt text
16x9_9x16
Open
Sample alt text
2x1_9x16
Open
alt text
9x16
Open
Sample alt text
9x16_picture
Open
Story slider intro slide
Open
Sample alt text
Story slider picture
Open
Sample alt text
Avatar
Open
Sample alt text
benefit overview
Open
alt text
benefit 1
Open
alt text
benefit 2
Open
alt text
benefit 3
Open
alt text
benefit 4
Open
alt text
benefit 5
Open
alt text
Mixed story slide
Open
Sample alt text