Skip to main content
Known Participant
June 24, 2025
Answered

Resize layer to match key object height or width, whichever is greater

  • June 24, 2025
  • 1 reply
  • 420 views

So I found this simple script:

https://community.adobe.com/t5/illustrator-discussions/illustrator-cc-how-to-manually-resize-one-object-to-match-another/m-p/11057446#M173293

//by Ray Craighead
//Select 2 objects. Script will scale top object to match bottom object.

function scaleTopObject( ){
    var aDoc = app.activeDocument;
    var sel = aDoc.selection;
    var topObj = sel[0];
    var botObj = sel[1];
    topObj.width = botObj.width;
    topObj.height = botObj.height;
    }

if (selection.length == 2) {
  scaleTopObject( );
} else alert ("Select 2 object. Top object will scale to match bottom object.");

 

And that is great, but I'm wondering how to modify it, or if its even possible, to determine if the width or height of the bottom object is greater, then resize the top object using either the width or height, but scaled proportionately?

Is this an over the top idea or possible using percentages?

Thanks!

Correct answer jduncan

Hey, here's an updated version of the script that is a bit more robust and also moves the top object to match the location of the bottom object. You just need to decide where you want the object to align at. There is a settings section at the top of the script where you can change the "anchor alighment". Also note, this script uses geometricBounds to determine the movement. Try it out and let me know what you think?

(function () {
    //@target illustrator

    // script settings

    // where should to top object align to the bottom object when moved
    // options (default is center-center): top-left, top-center, top-right, center-left, center-right, bottom-left, bottom-center, bottom-right, top-edge, bottom-edge, left-edge, right-edge, horizontal-center, vertical-center
    var alignObjectsAt = "center-center";

    // sanity checks

    // no need to continue if there is no active document
    if (!app.documents.length) {
        alert("No active document.");
        return;
    }

    // grab document and selection info
    var doc = app.activeDocument;
    var sel = doc.selection;

    // no need to continue if there is no active selection (or less than 2 objects are selected)
    if (sel.length < 2) {
        alert("No active selection.\nSelect at least two objects.");
        return;
    }

    // 1. first we grab reference to the "top" and "bottom" objects

    // grab the top (0th index) and bottom (1st index) objects (all else ignored)
    var topObject = sel[0];
    var bottomObject = sel[1];

    // 2. next we scale the object to match the bottom object

    // determine greater of width vs. height of bottom object
    // then calculate proportional scale matrix for top object
    var ratio = 100;
    if (bottomObject.width >= bottomObject.height) {
        ratio = (bottomObject.width / (topObject.width || 1)) * 100;
    } else {
        ratio = (bottomObject.height / (topObject.height || 1)) * 100;
    }
    var scaleMatrix = app.getScaleMatrix(ratio, ratio);
    topObject.transform(scaleMatrix, true, false, false, false, false, undefined);

    // 3. finally, we move the top object to match the location of the bottom object
    var moveMatrix = getMoveMatrix(
        bottomObject.geometricBounds,
        topObject.geometricBounds,
        alignObjectsAt
    );
    topObject.transform(
        moveMatrix,
        true, // objects
        true, // patterns
        true, // gradients
        true // stroke patterns
    );

    // helper functions

    /**
     * Extracts geometric information from Illustrator object bounds.
     *
     * @9397041 {Array<number>} bounds - Illustrator object bounds: [left, top, right, bottom].
     * @Returns {{left: number, top: number, right: number, bottom: number, width: number, height: number, centerX: number, centerY: number}} - An object containing geometric details of the bounds.
     */
    function getObjectPlacementInfo(bounds) {
        if (!bounds || typeof bounds !== "object" || bounds.length !== 4) {
            throw new Error("Invalid bounds: Expected [left, top, right, bottom]");
        }

        // Normalize for safety since occasionally Illustrator can return
        // inverted bounds (e.g., top < bottom due to transformations).
        var left = Math.min(bounds[0], bounds[2]);
        var right = Math.max(bounds[0], bounds[2]);
        var top = Math.max(bounds[1], bounds[3]);
        var bottom = Math.min(bounds[1], bounds[3]);

        var width = right - left;
        var height = top - bottom;
        var centerX = left + width / 2;
        var centerY = top - height / 2;

        return {
            left: left,
            top: top,
            right: right,
            bottom: bottom,
            width: width,
            height: height,
            centerX: centerX,
            centerY: centerY,
        };
    }

    /**
     * Creates a translation matrix to align the target object relative to the source object.
     *
     * @9397041 {Array<number>} sourceBounds - Bounds of source object to move to.
     * @9397041 {Array<number>} targetBounds - Bounds of target object to be moved.
     * @9397041 {string} anchor - Alignment of target object in relation to the source object.
     * @Returns {Matrix} - A translation matrix for aligning the target object to the source object.
     */
    function getMoveMatrix(sourceBounds, targetBounds, anchor) {
        anchor = typeof anchor !== "undefined" ? anchor : "center-center";
        var sourceInfo = getObjectPlacementInfo(sourceBounds);
        var targetInfo = getObjectPlacementInfo(targetBounds);

        switch (anchor.toLowerCase()) {
            case "top-left":
                return app.getTranslationMatrix(
                    sourceInfo.left - targetInfo.left,
                    sourceInfo.top - targetInfo.top
                );
            case "top-center":
                return app.getTranslationMatrix(
                    sourceInfo.centerX - targetInfo.centerX,
                    sourceInfo.top - targetInfo.top
                );
            case "top-right":
                return app.getTranslationMatrix(
                    sourceInfo.right - targetInfo.right,
                    sourceInfo.top - targetInfo.top
                );
            case "center-left":
                return app.getTranslationMatrix(
                    sourceInfo.left - targetInfo.left,
                    sourceInfo.centerY - targetInfo.centerY
                );
            case "center-right":
                return app.getTranslationMatrix(
                    sourceInfo.right - targetInfo.right,
                    sourceInfo.centerY - targetInfo.centerY
                );
            case "bottom-left":
                return app.getTranslationMatrix(
                    sourceInfo.left - targetInfo.left,
                    sourceInfo.bottom - targetInfo.bottom
                );
            case "bottom-center":
                return app.getTranslationMatrix(
                    sourceInfo.centerX - targetInfo.centerX,
                    sourceInfo.bottom - targetInfo.bottom
                );
            case "bottom-right":
                return app.getTranslationMatrix(
                    sourceInfo.right - targetInfo.right,
                    sourceInfo.bottom - targetInfo.bottom
                );
            case "top-edge":
                return app.getTranslationMatrix(0, sourceInfo.top - targetInfo.top);
            case "bottom-edge":
                return app.getTranslationMatrix(
                    0,
                    sourceInfo.bottom - targetInfo.bottom
                );
            case "left-edge":
                return app.getTranslationMatrix(sourceInfo.left - targetInfo.left, 0);
            case "right-edge":
                return app.getTranslationMatrix(sourceInfo.right - targetInfo.right, 0);
            case "horizontal-center":
                return app.getTranslationMatrix(
                    sourceInfo.centerX - targetInfo.centerX,
                    0
                );
            case "vertical-center":
                return app.getTranslationMatrix(
                    0,
                    sourceInfo.centerY - targetInfo.centerY
                );
            default:
                // fallback to center alignment
                return app.getTranslationMatrix(
                    sourceInfo.centerX - targetInfo.centerX,
                    sourceInfo.centerY - targetInfo.centerY
                );
        }
    }
})();

1 reply

jduncan
Community Expert
Community Expert
June 24, 2025

Here's a script that will resize the top object proportionally to the larger of the width or height of the bottom object. Try it out and let me know if you have any questions. And if you need more flexibility, take a look at my script MatchObjects.jsx. Cheers!

(function () {
    //@target illustrator

    // no need to continue if there is no active document
    if (!app.documents.length) {
        alert("No active document.");
        return;
    }

    // grab document and selection info
    var doc = app.activeDocument;
    var sel = doc.selection;

    // no need to continue if there is no active selection (or less than 2 objects are selected)
    if (sel.length < 2) {
        alert("No active selection.\nSelect at least two objects.");
        return;
    }

    // grab the top (0th index) and bottom (1st index) objects (all else ignored)
    var topObject = sel[0];
    var bottomObject = sel[1];

    // determine greater of width vs. height of bottom object
    // then calculate proportional scale matrix for top object
    var widthProp, heightProp, scaleMatrix;
    if (bottomObject.width >= bottomObject.height) {
        widthProp = (bottomObject.width / topObject.width) * 100;
        heightProp = (bottomObject.width / topObject.width) * 100;
    } else {
        widthProp = (bottomObject.height / topObject.height) * 100;
        heightProp = (bottomObject.height / topObject.height) * 100;
    }
    scaleMatrix = app.getScaleMatrix(widthProp, heightProp);

    /**
     * docs: https://ai-scripting.docsforadobe.dev/jsobjref/PageItem/#pageitemtransform
     * app.activeDocument.pageItems[index].transform(
     *     transformationMatrix     Transformation matrix to apply
     *     [,changePositions]       Whether to change Positions
     *     [,changeFillPatterns]    Whether to change Fill Patterns
     *     [,changeFillGradients]   Whether to change Fill Gradients
     *     [,changeStrokePattern]   Whether to change Stroke Pattern
     *     [,changeLineWidths]      The amount to scale line widths
     *     [,transformAbout]        The point to use as anchor, to transform about
     * )
     */
    topObject.transform(scaleMatrix, true, false, false, false, false, undefined);
})();

 

Known Participant
June 24, 2025

Thank you! I think that works. I'm going to play around with it with a few different shapes to make sure. I was using your Match Objects script, which is great but I needed to be able to to do it without the prompt so I can use it with batch processing.
If I wanted to also have it align to the bottom object, where would I need to add that?

jduncan
Community Expert
Community Expert
March 19, 2026

@JustMeTrying5564, hey I don’t quite follow and think we are referencing different things so let me break down the steps I think you want and you can correct me wherever I’m wrong.

 

Objects of Interest:

Top Object  = White square with black outline

Third Object = Blue rounded rectangle

Bottom Object = Red star

 

Originally the script was setup to scale the top object (white square) of the selection (based on the layers palette position) to match the size of the bottom object (red star) but in your picture if seems you are:

  1. Scaling the bottom object (red star) to match the size of the top object (white square).
  2. Placing the bottom object (red star) centered on and 2.25” down from the top of the middle/third object (blue rectangle).
  3. Ensuring that the newly scaled and moved bottom object (red star) is no closer than 2.25” from the bottom of the top object (white star).

And if you want to send a sample files, one with the starting state, and one with the ending state (how you want to result to be after the script), that would help as well.