Images in Catwalk

Status: Accepted

There are generally four types of "images" in Catwalks:

  • Media Images for Landing pages, like category cover images and advertisement images
  • Product Images or images coming from headless content management systems like Contentful or GraphCMS
  • Icons
  • Small static Images, for example logos

Each image type is handled differently inside the Catwalk stack because their usage patterns and optimisation criteria are different.

Media Images

All banner images, category images, etc should be uploaded in the Media application in Backstage. This application can be found on the start page of Backstage and you can just upload images of any format using drag and drop.

The CDN we are using optimises and scales these images.

If you want to use these images in Catwalk you should use the <Image /> component from Catwalk:

import React, { Component } from 'react'
import PropTypes from 'prop-types'

import Image from 'frontastic-catwalk/src/js/image'

class MyTastic extends Component {
    render () {
        return (
            <Image
                media={this.props.data.image}
            />
        )
    }
}

MyTastic.propTypes = {
    data: PropTypes.object.isRequired,
}

export default MyTastic

This Image component ensures that the image is cropped as specified by the Editor in Backstage and the image is also delivered in all the appropriate sizes etc. It also supports additional properties like title and alt.

The Image component tries to get the sizes of the HTML element it is embedded in and optimises crop and size based on this. Thus you can only embed this inside a properly sized block element.

External Product / Content Images

External Images are not handled or scaled by us by default and the backend system you're using is supposed to take care of this.

Frontastic can also scale, transform and optimise these images, but we need to put your image domains on an include list for this, since this causes additional expenditure for Frontastic. If your image domains are on our include list you can use the RemoteImage component:

import React, { Component } from 'react'

import Image from 'frontastic-catwalk/src/js/remoteImage'

class MyTastic extends Component {
    render () {
        return (
            <RemoteImage
                url={someUrl}
                alt="My custom alt text"
                options={{ crop: 'pad', background: 'white' }}
                cropRatio='2:1'
            />
        )
    }
}

export MyTastic

Icons

We strongly suggest to use SVG images as Icons. If you use this path we can transform those SVG images into React components as soon as you import them from a React component as well as optimising them while doing so as we use a svgr webpack plugin.

Thus you can use Icons like this in your tastics:

import React, { Component } from 'react'

import { ReactComponent as MyIcon } from 'icons/some-icon.svg'

class MyTastic extends Component {
    render () {
        return (
            <MyIcon />
        )
    }
}

export MyTastic

This way we ensure optimising, bundling and scaling of the Icons work in a logical way.

Small Images

Small Images (e.g Logos) can still be imported using classic import directives. This approach should not be used for Media Images, because these should be replaceable by Content Editors and therefore should go through Backstage (see first paragraph):

import React, { Component } from 'react'

import myLogo from '../my-logo.png'

class MyTastic extends Component {
    render () {
        return <img src={myLogo} />
    }
}

export MyTastic

Image Formats

Cloudinary (our CDN) supports all formats - including the new WebP and converts "correctly" as needed.

Very briefly:

  • PNGs support transparency but are generally more suitable for illustrations because PNGs cannot compress gradients and shades efficiently.

  • JPEGs cannot display transparencies or hard edges - JPEGs draw everything soft (internally, the image data is translated into sine curves).

A subsequent automatic release of images is almost impossible except in trivial cases - even tools such as PhotoShop fail if this is to happen without manual interaction.

Because Product Images generally have many natural colour gradients, PNGs (especially in high resolutions) are much larger - as long as images do not need transparencies, so JPEGs are much more useful.

WebP (https://de.wikipedia.org/wiki/WebP) theoretically supports everything PNGs and JPEGs can do (transparency, lossless, but also compression). However, the format is relatively new, not yet supported by all browsers, and probably not yet accepted by all image processing programs. Cloudinary supports WebP and should automatically convert the images for old browsers into other useful formats.

For graphics, (logos, ...) PNG (or SVG as vector format) is the best choice. For Product Images, WebP could be the most useful format by now, but we would have to see how exactly the support across all tools & browsers really works. JPEG with the correct background colour is the most stable decision. PNGs also work, but are large in upload (hardly smaller than TIFF / BMP for product images), but should be able to be delivered sensibly by our CDN.