Auto-align and resize images on every slide
Enforce consistent image placement across a Northwind deck — every photo same size, same spot.
Published Nov 23, 2025
When several people build a Northwind deck together, the images drift. One slide has a photo nudged slightly left, the next has it a touch too big, a third has it floating in the wrong corner. Individually each is minor; together they make a deck look unpolished. Fixing it by hand means clicking through every slide and dragging images into line.
This script enforces a single layout. It opens a deck, walks every slide, and sets each image to the same position and size — so every photo lands in exactly the same place. One run cleans up a whole deck.
What you’ll need
- The ID of the Google Slides deck you want to normalise, taken from its URL.
- A target layout: the
left,top,width, andheightin points that every image should snap to. The script ships with sensible defaults, which you can override per run. - Awareness that this is destructive — it overwrites the position and size of every image. Work on a copy of the deck first if you are not sure.
The script
// Default image layout in points. Override any of these per call by
// passing an options object as the second argument.
const DEFAULT_LAYOUT = { left: 50, top: 100, width: 600, height: 350 };
/**
* Sets every image in a deck to the same position and size, so photos
* land in an identical spot on every slide.
*
* @param {string} deckId ID of the Google Slides deck to normalise.
* @param {Object} [layout] Optional { left, top, width, height } in points.
*/
function normaliseImages(deckId, layout = {}) {
// 1. Merge any caller overrides onto the default layout.
const { left, top, width, height } = { ...DEFAULT_LAYOUT, ...layout };
// 2. Open the deck and grab every slide.
const deck = SlidesApp.openById(deckId);
const slides = deck.getSlides();
if (!slides.length) {
Logger.log('Deck has no slides — nothing to normalise.');
return;
}
// 3. Walk each slide, snapping every image to the target layout.
let count = 0;
for (const slide of slides) {
for (const image of slide.getImages()) {
image.setLeft(left).setTop(top).setWidth(width).setHeight(height);
count++;
}
}
Logger.log('Normalised ' + count + ' image(s) across ' + slides.length + ' slide(s).');
}
How it works
normaliseImagesstarts by merging any options the caller passed overDEFAULT_LAYOUT. Pass nothing and every image takes the defaults; pass{ width: 480 }and only the width changes.- It opens the deck by ID and reads every slide into an array. If the deck is empty it logs a message and stops.
- It loops over the slides, and within each slide loops over
slide.getImages()— the picture elements on that slide. - For each image it chains
setLeft,setTop,setWidth, andsetHeight, moving and resizing it to the exact target layout. All four values are in points, the same unit Slides uses internally. - A counter tracks how many images were touched, logged at the end so you can confirm the run did what you expected.
Example run
Take a six-slide deck where the team has dropped one photo on each slide, all at slightly different sizes and positions:
| Slide | Image before | Image after |
|---|---|---|
| 1 | left 62, 580×340 | left 50, 600×350 |
| 2 | left 48, 610×355 | left 50, 600×350 |
| 3 | left 70, 590×330 | left 50, 600×350 |
After normaliseImages('1abcDeckId'), every image sits at left 50, top 100,
sized 600×350. Flick through the deck and the photos no longer jump around
between slides.
Run it
This is an on-demand cleanup, run when a deck needs tidying:
- Add a wrapper that passes your deck ID, since the editor cannot call a function with arguments directly:
function runNormalise() {
normaliseImages('1abcDeckId');
}
- Select
runNormaliseand click Run. - Approve the Slides authorisation prompt the first time.
- Open the deck to check the result.
To use a custom layout, pass an options object: normaliseImages('1abcDeckId', { left: 80, top: 120, width: 480, height: 270 }).
Watch out for
- This is destructive. It overwrites position and size for every image — there is no undo from the script side. Run it on a copy first if the deck matters.
- It treats all images alike. A full-bleed background photo and a small inline logo both get forced to the same box, which is rarely what you want. If your deck mixes image roles, filter by current size before resizing.
- The script does not preserve aspect ratio. Forcing every image to 600×350 will stretch any photo that is not already that ratio. Crop or pre-size your images, or compute a height from each image’s own ratio.
- Images inside groups are not returned by
slide.getImages(). Ungroup them first if they also need aligning. - Logos placed on the slide master or layout, rather than on the slide itself, are not touched — that is usually correct, but worth knowing.
Related
Extract all deck text into a sheet
Pull text out of every slide for review, translation, or copy-editing.
Updated Jan 4, 2026
Generate sales-enablement decks per segment
Tailor Northwind's messaging slides by audience segment — fintech, healthcare, retail.
Updated Dec 28, 2025
Insert chapter divider slides from an outline
Add section-break slides between chapters in a Northwind deck.
Updated Dec 21, 2025
Build a deck accessibility checker
Flag missing alt text, low contrast, and tiny fonts across a Northwind deck.
Updated Dec 14, 2025
Drive menu and price-list signage from a Sheet
Generate display slides for a Northwind venue — menus or price lists driven by a Sheet.
Updated Dec 7, 2025