Skip to main content
Participant
July 26, 2026
Question

Photoshop: Convert all layers in each Artboard to a Smart Object automatically?

  • July 26, 2026
  • 2 replies
  • 21 views

 

Hi everyone,

I'm trying to automate part of my workflow in Photoshop and I'm wondering if there's a way to achieve this, either with an Action, a JSX/UXP script, or a plugin.

I have a PSD containing multiple Artboards. Each Artboard contains several layers (text, shapes, images, etc.).

For each Artboard, I'd like to:

  1. Select all layers inside that Artboard only (excluding hidden and locked layers).
  2. Convert those layers into a single Smart Object.
  3. Rename the Smart Object using the Artboard's name.
  4. Center the Smart Object horizontally and vertically within the Artboard.
  5. Repeat this process automatically for every Artboard in the document.

The final result would look like this:

Before:

 
Card 01 (Artboard)
Background
Title
Description

After:

 
Card 01 (Artboard)
Card 01 (Smart Object)

I'm using Photoshop 2025 on macOS.

I initially thought this could be done with an Action, but I couldn't find a way to select only the layers inside the current Artboard or loop through every Artboard automatically.

Has anyone achieved something similar, or knows of a script/plugin that can do this?

I'm also open to alternative workflows if there's a more efficient way to achieve the same result. My goal is to prepare hundreds of card designs as Smart Objects for use with batch mockup generation.

Any suggestions would be greatly appreciated. Thanks!

    2 replies

    Stephen Marsh
    Community Expert
    Community Expert
    July 27, 2026

    @andgartis 

     

    You can try the following script:


     

    /*
    Artboard Content to Centered Smart Object
    https://community.adobe.com/questions-712/photoshop-convert-all-layers-in-each-artboard-to-a-smart-object-automatically-1633971
    Stephen Marsh
    27th July 2026 - v1.0: Initial release

    For every artboard in the active document:
    1. Collects the parent artboard's child layers, skipping any that are hidden or locked
    2. Selects those layers and converts them into a single Smart Object
    3. Renames the Smart Object to match the artboard's name
    4. Centers the Smart Object horizontally and vertically within the artboard's bounds
    */

    #target photoshop

    (function () {

    var interactiveDebug = false;

    if (!app.documents.length) {
    alert("A document must be open to run this script!");
    return;
    }

    // Preserve user settings
    var originalRulerUnits = app.preferences.rulerUnits;
    var originalDisplayDialogs = app.displayDialogs;
    // Configure user settings
    app.preferences.rulerUnits = Units.PIXELS;
    app.displayDialogs = DialogModes.NO;
    var doc = app.activeDocument;
    var processedCount = 0;
    var skippedArtboards = [];

    try {
    var artboards = collectArtboards(doc);

    if (artboards.length === 0) {
    alert("No artboards were found in this document.");
    } else {
    for (var i = 0; i < artboards.length; i++) {
    var artboard = artboards[i];
    var result = processArtboard(doc, artboard);
    if (result.success) {
    processedCount++;
    } else {
    skippedArtboards.push(artboard.name + " (" + result.reason + ")");
    }
    }

    var summary = "Processed " + processedCount + " of " + artboards.length + " artboard(s).";
    if (skippedArtboards.length > 0) {
    summary += "\n\nSkipped:\n" + skippedArtboards.join("\n");
    }
    alert(summary);
    }
    } catch (e) {
    alert("Script error: " + e.message + (e.line ? " (line " + e.line + ")" : ""));
    } finally {
    // Restore user settings
    app.preferences.rulerUnits = originalRulerUnits;
    app.displayDialogs = originalDisplayDialogs;
    }


    // Main processing function
    function processArtboard(doc, artboard) {
    // Loop over artboards and collect the appropriate layers
    var candidates = [];
    for (var j = 0; j < artboard.layers.length; j++) {
    var child = artboard.layers[j];
    if (child.visible && !isLayerLocked(child)) {
    candidates.push(child);
    }
    }
    if (candidates.length === 0) {
    return { success: false, reason: "no eligible visible/unlocked layers" };
    }
    // Process the layers...
    // 1. Select all eligible layers inside this artboard
    selectLayersByID(getLayerIDs(candidates));
    // 2. Convert the current selection into a Smart Object
    convertSelectedLayersToSmartObject();
    var smartObject = doc.activeLayer;
    // 3. Rename it to match the artboard
    smartObject.name = artboard.name;
    // 4. Center it within the artboard bounds
    centerLayerInBounds(smartObject, getArtboardBounds(doc, artboard));
    return { success: true };
    }


    ///// Helper Functions /////

    function collectArtboards(doc) {
    var result = [];
    for (var i = 0; i < doc.layers.length; i++) {
    var lyr = doc.layers[i];
    if (lyr.typename === "LayerSet" && isArtboard(lyr)) {
    result.push(lyr);
    }
    }
    return result;
    }

    function isArtboard(layerSet) {
    try {
    if (layerSet.artboardEnabled === true) return true;
    } catch (e) {
    // Ignore DOM call and use the AM check
    }
    try {
    var key = stringIDToTypeID("artboardEnabled");
    var ref = new ActionReference();
    ref.putProperty(charIDToTypeID("Prpr"), key);
    ref.putIdentifier(charIDToTypeID("Lyr "), layerSet.id);
    var desc = executeActionGet(ref);
    return desc.hasKey(key) && desc.getBoolean(key);
    } catch (e2) {
    return false;
    }
    }

    function isLayerLocked(layer) {
    try {
    if (layer.typename === "LayerSet") {
    return layer.allLocked === true;
    }
    return (
    layer.allLocked === true ||
    layer.pixelsLocked === true ||
    layer.positionLocked === true ||
    layer.transparentPixelsLocked === true
    );
    } catch (e) {
    return false;
    }
    }

    function getLayerIDs(layers) {
    var ids = [];
    for (var i = 0; i < layers.length; i++) {
    ids.push(layers[i].id);
    }
    return ids;
    }

    function selectLayersByID(ids) {
    var ref = new ActionReference();
    for (var i = 0; i < ids.length; i++) {
    ref.putIdentifier(charIDToTypeID("Lyr "), ids[i]);
    }
    var desc = new ActionDescriptor();
    desc.putReference(charIDToTypeID("null"), ref);
    executeAction(charIDToTypeID("slct"), desc, DialogModes.NO);
    }

    function convertSelectedLayersToSmartObject() {
    executeAction(stringIDToTypeID("newPlacedLayer"), undefined, DialogModes.NO);
    }


    function getArtboardBounds(doc, layerSet) {
    /*
    active artboard dimensions, by Rune L-H
    https://community.adobe.com/t5/photoshop-ecosystem-discussions/photoshop-2015-artboards-in-scripting/m-p/7276275
    */
    var previousActive = doc.activeLayer;
    try {
    doc.activeLayer = layerSet;

    var ref = new ActionReference();
    ref.putEnumerated(charIDToTypeID("Lyr "), charIDToTypeID("Ordn"), charIDToTypeID("Trgt"));
    var desc = executeActionGet(ref);

    var artboardKey = stringIDToTypeID("artboard");
    if (desc.hasKey(artboardKey)) {
    var artboardDesc = desc.getObjectValue(artboardKey);
    var rectKey = stringIDToTypeID("artboardRect");
    if (artboardDesc.hasKey(rectKey)) {
    var rectDesc = artboardDesc.getObjectValue(rectKey);

    if ( interactiveDebug) alert("Artboard bounds source: artboardRect (correct path)");
    return {
    left: getDescNumber(rectDesc, "left"),
    top: getDescNumber(rectDesc, "top"),
    right: getDescNumber(rectDesc, "right"),
    bottom: getDescNumber(rectDesc, "bottom")
    };
    }
    }
    } catch (e) {
    // fall through to bounds-based fallback
    } finally {
    try { doc.activeLayer = previousActive; } catch (e2) {}
    }
    var b = layerSet.bounds;
    if ( interactiveDebug) alert("Artboard bounds source: layerSet.bounds FALLBACK (artboardRect lookup failed)");
    return {
    left: b[0].value,
    top: b[1].value,
    right: b[2].value,
    bottom: b[3].value
    };
    }

    function getDescNumber(desc, keyName) {
    var key = stringIDToTypeID(keyName);
    var type = desc.getType(key);
    switch (type) {
    case DescValueType.INTEGERTYPE:
    return desc.getInteger(key);
    case DescValueType.DOUBLETYPE:
    return desc.getDouble(key);
    case DescValueType.UNITDOUBLE:
    return desc.getUnitDoubleValue(key);
    default:
    return desc.getDouble(key);
    }
    }

    function centerLayerInBounds(layer, rect) {

    var artboardCenterX = (rect.left + rect.right) / 2;
    var artboardCenterY = (rect.top + rect.bottom) / 2;
    var b = layer.bounds; // pixel units (ruler set above)
    var layerCenterX = (b[0].value + b[2].value) / 2;
    var layerCenterY = (b[1].value + b[3].value) / 2;
    var deltaX = artboardCenterX - layerCenterX;
    var deltaY = artboardCenterY - layerCenterY;

    if ( interactiveDebug) {
    alert(
    "Artboard rect: L" + rect.left + " T" + rect.top + " R" + rect.right + " B" + rect.bottom +
    "\nArtboard center: " + artboardCenterX + ", " + artboardCenterY +
    "\n\nLayer bounds: L" + b[0].value + " T" + b[1].value + " R" + b[2].value + " B" + b[3].value +
    "\nLayer center: " + layerCenterX + ", " + layerCenterY +
    "\n\nDelta to apply: " + deltaX + ", " + deltaY
    );
    }

    if (deltaX !== 0 || deltaY !== 0) {
    layer.translate(deltaX, deltaY);
    }

    if ( interactiveDebug) {
    var after = layer.bounds;
    alert(
    "Layer bounds AFTER translate: L" + after[0].value + " T" + after[1].value +
    " R" + after[2].value + " B" + after[3].value
    );
    }
    }

    })();

     

    1. Copy the code text to the clipboard
    2. Open a new blank file in a plain-text editor (not in a word processor)
    3. Paste the code in
    4. Save as a plain text format file – .txt
    5. Rename the saved file extension from .txt to .jsx
    6. Install or browse to the .jsx file to run (see below)

    https://prepression.blogspot.com/2017/11/downloading-and-installing-adobe-scripts.html

    Stephen Marsh
    Community Expert
    Community Expert
    July 27, 2026

    @andgartis I can help, I think that I have most of the required components in other scripts.