Contensio logo

Image Variants

How Contensio automatically generates resized and cropped versions of uploaded images — and how to configure sizes per content type.

When you upload an image, Contensio queues a background job that generates multiple resized copies — called variants — based on the image size configuration of each content type. Variants are always saved as WebP for optimal file size and quality.

Why variants exist

A 4 MB original photo shouldn't be sent to a mobile visitor loading a 300 px thumbnail. Variants let your theme serve the right size for every context — thumbnails in listing pages, full-width images in post headers, OG images for social shares — without any resizing at request time.

Default size presets

Contensio ships with six size presets. Each content type can activate or deactivate them independently and override their dimensions.

Key Label Default size Fit Active by default
small Small 480 × 320 Cover All content types
medium Medium 900 × 600 Cover All content types
large Large 1600 × 900 Cover All content types
og OG Image 1200 × 630 Cover Post, Page
thumbnail Thumbnail 150 × 150 Pad None (opt-in)
square Square 600 × 600 Pad None (opt-in)

Configuring image sizes per content type

Each content type has its own Image Sizes tab in its edit form (Configuration → Content Types → edit). There you can, for each preset:

  • Enable or disable the variant for this type.
  • Change the width and height to match your theme's layout.
  • Change the fit mode and quality.

Changes are saved immediately. After saving, Contensio queues a regeneration job for all existing images so variants are updated to the new dimensions.

Fit modes explained

The fit mode controls how the source image is transformed to reach the target dimensions.

Mode Behaviour Best for
Cover Scales the image up/down and crops the edges so the canvas is filled exactly. No empty space, no distortion. Hero images, featured images, cards
Contain Scales the image to fit entirely within the box. Aspect ratio is preserved; empty space may appear if the image ratio differs from the target. Logos, icons
Scale Stretches or squashes the image to the exact dimensions. Distorts if the aspect ratios differ. Rarely useful — prefer cover or contain
Crop Hard-crops the image from the centre to the exact dimensions without scaling. When you need a pixel-perfect extract of the centre
Pad Like contain, but fills the empty space with the configured background colour. Produces an image that is exactly width × height with the subject centred. Square thumbnails, product images on white

Quality

All variants are encoded at the configured quality level (default: 85). Valid range is 1–100. Higher values produce larger files with more detail; lower values produce smaller files with more compression artefacts. 85 is a good default for photographic content.

Background colour

Only applies when fit is Pad. Sets the fill colour for the empty space. Default is #ffffff (white). Use a hex colour, e.g. #f3f4f6 for a light grey.

How variants are stored

Variants are stored alongside the original file on the same disk, in the same folder. The filename pattern is:

{original_basename}_{size_key}.webp

For example, if the original is uploads/2026/04/photo.jpg and the medium variant is active, the variant is stored at:

uploads/2026/04/photo_medium.webp

A media_variants record is created for each variant, linked to the original media record.

Variants across content types

Variants are generated using the union of all active sizes across all content types. If even one content type has the thumbnail size active, every uploaded image will get a _thumbnail.webp variant — regardless of which content type the image is used in.

This means activating a size on a content type affects all future uploads, not just images assigned to that type.

Regenerating variants manually

If you change image size settings after images are already uploaded, Contensio automatically queues regeneration jobs on save. If your queue is not running or you need to force regeneration, dispatch the job manually from Tinker:

use Contensio\Models\Media;
use Contensio\Jobs\ProcessMediaVariants;

Media::whereNotNull('width')->each(fn ($m) => ProcessMediaVariants::dispatch($m));

Make sure your queue worker is running:

php artisan queue:work

Adding custom size presets

The built-in presets are defined in config/contensio.php under image_sizes. To add a custom preset, publish the config and add an entry:

php artisan vendor:publish --tag=contensio-config

Then in config/contensio.php:

'image_sizes' => [
    // ... existing presets ...

    'hero' => [
        'label'       => 'Hero',
        'width'       => 1920,
        'height'      => 800,
        'fit'         => 'cover',
        'quality'     => 90,
        'background'  => '#000000',
        'default_for' => ['post'],   // active by default for posts only
    ],
],

The new preset appears in the Image Sizes tab for all content types.

Using variants in themes

The Media model exposes its variants via the variants relationship. Each MediaVariant has size_key, path, width, height, and file_size.

$image = $content->featuredImage; // Media model

// Get a specific variant URL
$variant = $image->variants->firstWhere('size_key', 'medium');
$url = Storage::disk($image->disk)->url($variant->path);

// Or fall back to the original if the variant doesn't exist
$url = $variant
    ? Storage::disk($image->disk)->url($variant->path)
    : Storage::disk($image->disk)->url($image->file_path);