DevToys Web Pro iconDevToys Web ProБлог
Перекладено за допомогою LocalePack logoLocalePack
Оцініть нас:
Спробуйте розширення для браузера:
← Back to Blog

Letterbox, Pillarbox, and Windowbox: A Complete Image Boxing Guide

8 min read

Every social media platform enforces a fixed canvas size. Instagram wants a square, YouTube needs a 16:9 thumbnail, LinkedIn prefers a near-widescreen rectangle. Your source images rarely match. When the aspect ratios disagree you have two choices: crop content away, or add padding to preserve it. The second technique is called image boxing — and the Image Boxing tool handles it entirely in your browser. This guide explains the terminology, the math, the CSS approach, and the server-side implementation.

Letterbox, Pillarbox, and Windowbox Defined

These three terms describe where padding appears relative to the image content. The names come from television broadcasting, where source material and display formats have always fought over aspect ratios.

TermPadding LocationWhen It OccursClassic Example
LetterboxTop and bottomWide source fit into a taller canvas16:9 film on a 4:3 TV
PillarboxLeft and rightTall source fit into a wider canvas4:3 broadcast on a 16:9 widescreen
WindowboxAll four sidesSource is smaller than the canvas in both dimensionsSD video centered on a 4K display

In all three cases the image content is never cut. It is scaled to the largest size that fits inside the target canvas while preserving its original aspect ratio, then centered. The remaining space is filled with a background color.

When Boxing Matters: Social Media Aspect Ratios

Social platforms transcode uploads into fixed dimensions. If your image does not already match, the platform will crop it — often badly, cutting off faces or text. Boxing the image yourself before upload puts you in control of what is preserved and what color fills the gaps.

Platform / FormatAspect RatioTypical Pixel SizeNotes
Instagram — square post1:11080 × 1080Most common feed format
Instagram — portrait post4:51080 × 1350Maximum vertical real estate in feed
Instagram — Stories / Reels9:161080 × 1920Full-screen vertical
YouTube — thumbnail16:91280 × 720Standard HD; minimum 640 × 360
Twitter / X — in-stream image16:9 or 2:11200 × 675 or 1200 × 600Cropped to 16:9 in timeline
LinkedIn — shared image1.91:11200 × 628Same as Open Graph standard
TikTok — video cover9:161080 × 1920Vertical full-bleed

The takeaway: you need to produce 1:1, 4:5, 9:16, 16:9, 2:1, and 1.91:1 variants from a single source. Boxing lets you do that without discarding content for every format.

CSS object-fit: The Display-Layer Approach

CSS object-fit controls how a replaced element (an <img> or <video>) fills its container. It does not produce a new image file — it only affects rendering in the browser. This is useful for UI layouts but is not a substitute for actual boxing when you need to export or upload a fixed-size image.

ValueBehaviorPreserves Aspect RatioEquivalent to
containScale down to fit entirely inside the box; letterbox/pillarbox gaps visibleYesImage boxing / letterboxing
coverScale up to fill the box completely; overflow croppedYesCropping
fillStretch to fill the box exactlyNoDistortion
scale-downSmaller of none or containYesContain but never upscale
noneNatural size, no scalingYesWindowbox when image is smaller than container
/* Letterbox effect in CSS */
.thumbnail {
  width: 1280px;
  height: 720px;
  object-fit: contain;
  background-color: #000;
}

/* The background shows through where the image does not reach */

Limitation: object-fit: contain has no IE11 support. For legacy environments you need a JavaScript polyfill or server-side boxing. Modern browsers (Chrome, Firefox, Safari, Edge) all support it without issue.

Server-Side Boxing with sharp

For generating actual image files — uploads, thumbnails, exports — the Node.js library sharp is the standard tool. Its resize method accepts a fit option that maps directly to the boxing strategies above.

npm install sharp
import sharp from 'sharp';

// Box a portrait photo into a 1080x1080 square (Instagram)
await sharp('input.jpg')
  .resize({
    width: 1080,
    height: 1080,
    fit: 'contain',          // letterbox or pillarbox as needed
    background: { r: 255, g: 255, b: 255, alpha: 1 }, // white padding
  })
  .toFile('output-square.jpg');

// Box into 16:9 for a YouTube thumbnail
await sharp('input.jpg')
  .resize({
    width: 1280,
    height: 720,
    fit: 'contain',
    background: { r: 0, g: 0, b: 0, alpha: 1 }, // black padding
  })
  .toFile('output-16x9.jpg');

// Box with a semi-transparent background (PNG output)
await sharp('input.png')
  .resize({
    width: 1080,
    height: 1920,
    fit: 'contain',
    background: { r: 0, g: 0, b: 0, alpha: 0 }, // transparent padding
  })
  .png()
  .toFile('output-9x16.png');

The fit: 'contain' option calculates the scaled dimensions automatically. You only specify the target canvas. Sharp places the scaled image centered on that canvas and fills the remainder with the background color.

Canvas-Based Boxing in the Browser

When you need to box images client-side without a server — the approach used by the Image Boxing tool — the HTML Canvas API gives you precise control. The pattern is: create a canvas at target dimensions, draw the background, calculate the centered position of the scaled source, then draw the image.

function boxImage(sourceImg, targetWidth, targetHeight, background = '#ffffff') {
  const canvas = document.createElement('canvas');
  canvas.width = targetWidth;
  canvas.height = targetHeight;
  const ctx = canvas.getContext('2d');

  // Fill background
  ctx.fillStyle = background;
  ctx.fillRect(0, 0, targetWidth, targetHeight);

  // Scale source to fit inside canvas preserving aspect ratio
  const srcAspect = sourceImg.naturalWidth / sourceImg.naturalHeight;
  const dstAspect = targetWidth / targetHeight;

  let drawWidth, drawHeight;
  if (srcAspect > dstAspect) {
    // Source is wider — letterbox (bars top and bottom)
    drawWidth = targetWidth;
    drawHeight = targetWidth / srcAspect;
  } else {
    // Source is taller — pillarbox (bars left and right)
    drawHeight = targetHeight;
    drawWidth = targetHeight * srcAspect;
  }

  // Center the image on the canvas
  const x = (targetWidth - drawWidth) / 2;
  const y = (targetHeight - drawHeight) / 2;

  ctx.drawImage(sourceImg, x, y, drawWidth, drawHeight);

  return canvas;
}

// Export as a Blob
canvas.toBlob((blob) => {
  const url = URL.createObjectURL(blob);
  // use url for download or upload
}, 'image/jpeg', 0.92);

Background Color Choice

The padding color is a creative and functional decision. Common approaches:

  • Black (#000000): The classic cinema letterbox. Works for dark-themed content, video thumbnails, product photography on dark backgrounds.
  • White (#ffffff): Clean and neutral. Standard for editorial, e-commerce, and document-style content.
  • Brand color: Reinforces identity. The padding becomes part of the composition rather than dead space.
  • Blurred backdrop: Instagram Reels style — the source image is blurred, stretched to fill the canvas, and the original sits centered on top. Avoids distracting solid bars and keeps visual interest edge-to-edge.
  • Transparent (PNG): Best for compositing — place the boxed image over any background later.

For the blurred backdrop effect in canvas, render the source twice: first scaled to cover the full canvas with a CSS blur filter, then the actual boxed version centered on top.

// Blurred backdrop (Instagram Reels style)
function boxWithBlurredBackdrop(sourceImg, targetWidth, targetHeight) {
  const canvas = document.createElement('canvas');
  canvas.width = targetWidth;
  canvas.height = targetHeight;
  const ctx = canvas.getContext('2d');

  // Draw blurred cover layer
  ctx.filter = 'blur(20px) brightness(0.7)';
  const coverRatio = Math.max(targetWidth / sourceImg.naturalWidth, targetHeight / sourceImg.naturalHeight);
  const coverW = sourceImg.naturalWidth * coverRatio;
  const coverH = sourceImg.naturalHeight * coverRatio;
  ctx.drawImage(sourceImg, (targetWidth - coverW) / 2, (targetHeight - coverH) / 2, coverW, coverH);

  // Reset filter, draw sharp centered image on top
  ctx.filter = 'none';
  const srcAspect = sourceImg.naturalWidth / sourceImg.naturalHeight;
  const dstAspect = targetWidth / targetHeight;
  let drawWidth, drawHeight;
  if (srcAspect > dstAspect) {
    drawWidth = targetWidth;
    drawHeight = targetWidth / srcAspect;
  } else {
    drawHeight = targetHeight;
    drawWidth = targetHeight * srcAspect;
  }
  ctx.drawImage(sourceImg, (targetWidth - drawWidth) / 2, (targetHeight - drawHeight) / 2, drawWidth, drawHeight);

  return canvas;
}

When to Crop vs When to Box

Boxing and cropping are not interchangeable — the right choice depends on what the image communicates.

  • Box editorial and documentary images. A landscape photograph, a group portrait, or an infographic contains content across the full frame. Cropping removes meaning. Box to the target ratio and let the full image breathe.
  • Crop product and hero images. A product photo has a clear subject. Cropping to center that subject on a tight canvas is more impactful than showing it floating with empty padding around it.
  • Box when aspect ratios are close. If source is 3:2 and target is 1:1, boxing adds modest bars. If source is 9:16 and target is 16:9, boxing produces a tiny image surrounded by enormous bars — cropping is almost certainly the better choice.
  • Box for archival and lossless workflows. When you need to produce multiple output sizes later, a boxed version preserves the original framing. A cropped version does not.

Common Pitfalls

  • Asymmetric padding from odd dimensions in sharp. If your target dimensions are odd numbers (e.g., 1081 × 1081), the centering calculation produces fractional pixel offsets that sharp rounds asymmetrically, placing one extra row of padding on one side. Use even dimensions for all target canvas sizes.
  • CSS object-fit does not export a file. It affects how an existing image is displayed in a browser element. If you need to upload a boxed file to a platform, you must use canvas or a server-side tool — the CSS approach produces no downloadable asset.
  • IE11 does not support object-fit. The property has zero support in IE11. If your audience includes legacy Windows enterprise users, use the canvas approach or a polyfill such as object-fit-images.
  • Canvas toBlob JPEG quality default. Calling canvas.toBlob(cb, 'image/jpeg') without a quality argument uses 0.92 by default, which is reasonable. Do not omit it on JPEG outputs where file size matters — explicit is safer.
  • Transparency lost on JPEG output. If your source has an alpha channel and you box it onto a transparent canvas, then export as JPEG, the transparency is composited against black. Use PNG output when preserving transparency.

Box any image to a fixed canvas directly in your browser with the Image Boxing tool — no upload, no server, nothing leaves your machine. For more image workflows, see the guides on image resizing and image optimization.