Choosing a new wallpaper for your devices is always a tough endeavor. Yet, there's nothing worse than stumbling upon the perfect wallpaper and finding it doesn't quite fit. If this has happened to you, we're here to help! Take a look at how you can use the power of Transloadit to resize any wallpaper and make it fit perfectly on any device.

A minimalistic, modern wallpaper, with the Transloadit logo and the text 'Create a wallpaper' above a blank iPhone.


As (part of) the saying goes: "Teach a man to fish, and you feed him for a lifetime." Therefore, we will be teaching you how to make a website that automatically resizes any wallpaper to fit any screen size 🎣

The first step in making our website is creating a Transloadit Template. A Template is a series of Assembly Instructions that Transloadit will later use to resize our wallpaper to the correct dimensions, using the fillcrop resize strategy. Below is the Template that we'll be using today.

  "steps": {
    ":original": {
      "robot": "/upload/handle"
    "crop_thumbed": {
      "use": ":original",
      "robot": "/image/resize",
      "result": true,
      "height": "${fields.height}",
      "width": "${fields.width}",
      "imagemagick_stack": "v3.0.0",
      "resize_strategy": "fillcrop"
    "exported": {
      "use": ["crop_thumbed"],
      "robot": "/s3/store",
      "credentials": "S3_CREDENTIALS"

You might notice that we are using ${fields.height} and ${fields.width}. These are fields that can be dynamically passed into a Template, so that we can adjust the behavior at runtime. More generically speaking, these are Assembly Variables, and there's a variety of them that you can use in your Assemblies. Learn more about the different uses of Assembly Variables here.


We are not going to take as deep a dive into the HTML and CSS as we usually do, but feel free to take a look at both below, in case you'd like to copy-paste them into your own project.

  <link href="" rel="stylesheet" />
<div class="content">
  <h1>Wallpaper Resizer</h1>
  <div class="button-list" id="preview-buttons"></div>
  <p>Drag a photo over the frame to preview it</p>
  <div id="preview-box"><img id="preview-image" /></div>
  <div id="progress-bar"></div>
  <div class="button-list">
      <a id="download" href="" download="wallpaper"> Download </a>
    <button id="clear">Clear</button>
#preview-box {
  border: 1px solid black;
  border-radius: 10px;
  display: flex;
  align-items: center;
  justify-content: center;
  height: 216px;
  width: 384px;
  overflow: clip;
  position: relative;
#preview-box::after {
  background-size: 100%;
  position: absolute;
  box-sizing: border-box;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  border-radius: 10px;
#preview-image {
  height: 100%;
  width: 100%;
  object-fit: cover;
.content {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  font-family: Helvetica;
.button-list {
  display: flex;
  gap: 10px;


Now we can take a look at my favorite part of each blog – the integration code.

import {
} from ''

const uppy = new Uppy({
  restrictions: {
    allowedFileTypes: ['image/*'],
    maxNumberOfFiles: 1,
  autoProceed: true,
  .use(DropTarget, {
    target: '#preview-box',
    onDrop: setAssemblyFields,
  .use(Informer, {
    target: 'body',
  .use(ProgressBar, {
    target: '#progress-bar',
    fixed: true,
  .on('transloadit:complete', setPreviewImage)

const previewBox = document.getElementById('preview-box')
const previewImage = document.getElementById('preview-image')

let url = ''
let crop_height = 1080
let crop_width = 1920

const resolutions = [
  [1920, 1080],
  [1080, 1920],
  [2560, 1080],
  [1080, 2560],
  [1366, 768],
  [768, 1366],
const previewScale = 0.2


document.getElementById('clear').addEventListener('click', clearPreview)

function setPreviewImage(assembly) {
  url = assembly.results.crop_thumbed[0].ssl_url
  previewImage.setAttribute('style', 'display: block;')
  previewImage.setAttribute('src', url)
  const downloadButton = document.getElementById('download')
  downloadButton.setAttribute('href', url)

function clearPreview() {
  previewImage.setAttribute('style', 'display: none;')

function setAssemblyFields() {
  uppy.use(Transloadit, {
    waitForEncoding: true,
    assemblyOptions: {
      params: {
        auth: { key: 'YOUR_AUTH_KEY' },
        template_id: 'YOUR_TEMPLATE_ID',
        fields: {
          height: crop_height,
          width: crop_width,

function appendButton(resolution) {
  const buttonTextEl = document.createElement('button')
  buttonTextEl.className = 'button'
  buttonTextEl.innerText = `${resolution[0]}x${resolution[1]}`
  buttonTextEl.setAttribute('data-width', resolution[0])
  buttonTextEl.setAttribute('data-height', resolution[1])
  buttonTextEl.addEventListener('click', setPreviewBoxDimensions)

function setPreviewBoxDimensions(e) {
  const height ='data-height') * previewScale
  const width ='data-width') * previewScale
  previewBox.setAttribute('style', `width:${width}px;height:${height}px`)
  crop_height = height / previewScale
  crop_width = width / previewScale

Let's comb through the code line by line.

Since we are making a website, we naturally start by importing the best file uploader in the world, Uppy. We first need to create a new instance of Uppy, and then initialize all of our plugins. For today's demo, we will be using the: Drop target plugin, Informer plugin, Progress bar plugin and finally, the Transloadit plugin. Importantly, we set autoProceed to true, so that our file is uploaded to Transloadit as soon as we drop an image over the preview.

After this, we declare a few variables and constants to be used in our functions later on, as well as an array of resolutions. We can later call the appendButton function for each resolution to create a button corresponding to each screen size we want to target.


Let's now move on to each of the functions we reference.

The setPreviewImage function is called from the transloadit:complete event from Uppy – which is called whenever the Transloadit Assembly is finished. We then inspect the Assembly JSON from our result and retrieve the ssl_url of the file from our S3 bucket. We can then set the preview image's visibility, and assign it the correct image.

Since we are setting a preview image, we're going to want to clear it too! That's where the suitably named clearPreview comes in. This function completes two very basic tasks: it hides the preview image element and it removes the file we just uploaded from the Uppy instance, too – in case we want to upload a duplicate image.

Following that, setAssemblyFields configures the Transloadit plugin for our Uppy instance. We can pass the Assembly Variables we touched on earlier here, letting us dynamically resize the wallpaper to fit any device.

Next up is appendButton! The functionality here is pretty self-explanatory. We create a button element, using one of the resolution pairs. Notably, we add two data attributes, data-width and data-height, just to make it a little easier for us later on to retrieve these values from the button.

Last but not least is setPreviewBoxDimensions. Here, we retrieve the data attributes that were previously mentioned, and use these to resize our preview box to the same aspect ratio, only scaled down a little to fit the page.

Final results

Piece it all together, and you should end up with a result similar to the one below.

See the Pen Wallpaper Resizing Website by MSSNG (@missing-tech) on CodePen.

Pick a resolution, drag a photo over, and download a perfectly resized wallpaper that fits any device, ranging from a Samsung Galaxy smartphone to an ultrawide desktop monitor.

And with that, we've reached the end of today's blog! If you are eagerly waiting for the next blog, be sure to sign up for the newsletter in order to receive updates on the latest Transloadit developments, as well as tech articles that we find interesting.