Create automatic stack layouts in CE.SDK that arrange pages vertically or horizontally with consistent spacing. Build structured compositions like collages, catalogs, or carousels without manually positioning each element.
CE.SDK provides stack layouts that automatically arrange pages with consistent spacing. Vertical stacks arrange pages top-to-bottom, horizontal stacks arrange left-to-right. This eliminates manual positioning for compositions like photo collages, product catalogs, social media carousels, and magazine layouts.
This guide covers how to create vertical and horizontal stack layouts, add pages to stacks, configure spacing, reorder pages, and switch between automatic and manual positioning modes.
Setting Up the Engine#
We initialize the headless CE.SDK engine for server-side layout operations.
// Initialize CE.SDK engine in headless modeconst engine = await CreativeEngine.init({ // license: process.env.CESDK_LICENSE, // Optional (trial mode available)});Create a Vertical Stack Layout#
Vertical stack layouts arrange pages from top to bottom. When you add pages to the stack, they automatically position below each other with the configured spacing.
// Create a scene with vertical stack layout// Pages and blocks will arrange top-to-bottom automaticallyconst verticalScene = engine.scene.create('VerticalStack');console.log('Created VerticalStack scene:', verticalScene);
// Get the stack container to add pagesconst [stack] = engine.block.findByType('stack');
// Create first pageconst page1 = engine.block.create('page');engine.block.setWidth(page1, 400);engine.block.setHeight(page1, 300);engine.block.appendChild(stack, page1);
// Create second page - appears below page1const page2 = engine.block.create('page');engine.block.setWidth(page2, 400);engine.block.setHeight(page2, 300);engine.block.appendChild(stack, page2);
// Configure spacing between stacked pages (in screen space pixels)engine.block.setFloat(stack, 'stack/spacing', 20);engine.block.setBool(stack, 'stack/spacingInScreenspace', true);
const spacing = engine.block.getFloat(stack, 'stack/spacing');console.log(`Stack spacing: ${spacing}px`);Pages added with appendChild appear at the bottom of the stack. The stack/spacing property controls the gap between pages, and stack/spacingInScreenspace determines whether spacing is in screen pixels or design units.
Create a Horizontal Stack Layout#
Horizontal stack layouts arrange pages from left to right. Switch between layout types using engine.scene.setLayout().
// Switch to horizontal stack layout// Pages will now arrange left-to-rightengine.scene.setLayout('HorizontalStack');console.log('Changed to HorizontalStack layout');
// Verify the layout changeconst currentLayout = engine.scene.getLayout();console.log('Current layout:', currentLayout);
// Pages are automatically rearranged horizontally// Useful for carousels, timelines, or horizontal galleriesHorizontal layouts are useful for carousels, timelines, or horizontal galleries. The same spacing configuration applies—pages automatically reposition when you change the layout type.
Add Blocks to Pages#
Once you have pages in your stack, add graphic blocks to display content. Each block needs a shape and fill to be visible.
// Add graphic blocks to each page// Blocks must have a shape and fill to be visible
// Sample image URL for demonstrationsconst imageUri = 'https://img.ly/static/ubq_samples/sample_1.jpg';
// Add an image block to page 1const block1 = await engine.block.addImage(imageUri, { size: { width: 350, height: 250 }});engine.block.setPositionX(block1, 25);engine.block.setPositionY(block1, 25);engine.block.appendChild(page1, block1);console.log('Added image block to page 1');
// Add a colored rectangle to page 2const block2 = engine.block.create('graphic');const shape2 = engine.block.createShape('rect');engine.block.setShape(block2, shape2);engine.block.setWidth(block2, 350);engine.block.setHeight(block2, 250);engine.block.setPositionX(block2, 25);engine.block.setPositionY(block2, 25);const fill2 = engine.block.createFill('color');engine.block.setColor(fill2, 'fill/color/value', { r: 0.3, g: 0.6, b: 0.9, a: 1.0});engine.block.setFill(block2, fill2);engine.block.appendChild(page2, block2);console.log('Added colored block to page 2');Position blocks within their parent page using setPositionX() and setPositionY(). The block’s position is relative to the page’s top-left corner.
Add Pages to an Existing Stack#
After creating a composition, you can add more pages to the stack. New pages automatically appear at the end.
// Add a new page to the existing stack layout// The page automatically appears at the end of the stackconst page3 = engine.block.create('page');engine.block.setWidth(page3, 400);engine.block.setHeight(page3, 300);engine.block.appendChild(stack, page3);console.log('Added page 3 to stack');
// Add content to page 3const block3 = engine.block.create('graphic');const shape3 = engine.block.createShape('rect');engine.block.setShape(block3, shape3);engine.block.setWidth(block3, 350);engine.block.setHeight(block3, 250);engine.block.setPositionX(block3, 25);engine.block.setPositionY(block3, 25);const fill3 = engine.block.createFill('color');engine.block.setColor(fill3, 'fill/color/value', { r: 0.9, g: 0.5, b: 0.3, a: 1.0});engine.block.setFill(block3, fill3);engine.block.appendChild(page3, block3);
// Count pages in stackconst pages = engine.block.getChildren(stack);console.log(`Stack now has ${pages.length} pages`);Use getChildren() to see all pages in the stack. The insertion order determines the visual order in the layout.
Reorder Pages in the Stack#
Change the position of pages using insertChild(). This lets you move pages to any position in the stack.
// Reorder pages using insertChild// Move page3 to the first position (index 0)engine.block.insertChild(stack, page3, 0);console.log('Moved page 3 to first position');
// Verify the new order by listing childrenconst reorderedPages = engine.block.getChildren(stack);console.log('Page order after reordering:', reorderedPages);The second parameter specifies the target index. Index 0 places the page first, and higher indices move it further down (or right in horizontal layouts).
Change Stack Spacing#
Adjust the spacing between pages at any time. Changes apply immediately and pages reposition automatically.
// Update spacing between stacked pagesengine.block.setFloat(stack, 'stack/spacing', 40);const newSpacing = engine.block.getFloat(stack, 'stack/spacing');console.log(`Updated stack spacing to: ${newSpacing}px`);
// Spacing updates immediately - pages reposition automaticallyUse getFloat() to read the current spacing value. Larger spacing creates more separation between pages; zero spacing creates a seamless grid.
Switch to Free Layout#
Stack layouts automatically position pages. For manual control, switch to Free layout.
// Check current layout typeconst layoutBefore = engine.scene.getLayout();console.log('Current layout:', layoutBefore);
// Convert to free layout for manual positioningengine.scene.setLayout('Free');console.log('Switched to Free layout');
// In free layout, pages keep their positions but stop auto-arranging// Now you can position pages manuallyconst [firstPage] = engine.block.findByType('page');engine.block.setPositionX(firstPage, 50);engine.block.setPositionY(firstPage, 50);console.log('Manually positioned first page');
// Verify layout changeconst layoutAfter = engine.scene.getLayout();console.log('Layout after switch:', layoutAfter);In Free layout, pages keep their current positions but stop auto-arranging. You can then use setPositionX() and setPositionY() to position pages manually.
Build a Photo Collage#
This practical example creates a vertical photo collage with three images and tight spacing.
// Create a new vertical stack scene for a photo collageengine.scene.create('VerticalStack', { page: { size: { width: 600, height: 200 } }});
// Get the new stackconst [collageStack] = engine.block.findByType('stack');
// Set tight spacing for collage effectengine.block.setFloat(collageStack, 'stack/spacing', 10);engine.block.setBool(collageStack, 'stack/spacingInScreenspace', true);
// Get the first page created with the sceneconst [collagePage1] = engine.block.findByType('page');
// Create additional pages for the collageconst collagePage2 = engine.block.create('page');engine.block.setWidth(collagePage2, 600);engine.block.setHeight(collagePage2, 200);engine.block.appendChild(collageStack, collagePage2);
const collagePage3 = engine.block.create('page');engine.block.setWidth(collagePage3, 600);engine.block.setHeight(collagePage3, 200);engine.block.appendChild(collageStack, collagePage3);
// Add images to each collage pageconst imageUrls = [ 'https://img.ly/static/ubq_samples/sample_1.jpg', 'https://img.ly/static/ubq_samples/sample_2.jpg', 'https://img.ly/static/ubq_samples/sample_3.jpg'];
const collagePages = [collagePage1, collagePage2, collagePage3];
for (let i = 0; i < collagePages.length; i++) { const photoBlock = await engine.block.addImage(imageUrls[i], { size: { width: 580, height: 180 } }); engine.block.setPositionX(photoBlock, 10); engine.block.setPositionY(photoBlock, 10); engine.block.appendChild(collagePages[i], photoBlock);}
console.log('Created photo collage with 3 images');The collage uses a vertical stack with 10px spacing. Each page contains an image that fills most of the page area, creating a cohesive photo strip effect.
Exporting the Result#
After building the layout, export pages as images to verify the composition.
// Export the collage result to PNGconst outputDir = './output';if (!existsSync(outputDir)) { mkdirSync(outputDir, { recursive: true });}
const blob = await engine.block.export(collagePage1, { mimeType: 'image/png'});const buffer = Buffer.from(await blob.arrayBuffer());writeFileSync(`${outputDir}/layout-collage.png`, buffer);
console.log('\nExported collage to output/layout-collage.png');Troubleshooting#
Pages not arranging automatically: Verify the scene layout type is VerticalStack or HorizontalStack using engine.scene.getLayout().
Spacing not applying: Check the spacing value with engine.block.getFloat(stack, 'stack/spacing'). Ensure you’re setting spacing on the stack block, not the scene.
Pages overlapping: Ensure pages are direct children of the stack block. Use engine.block.findByType('stack') to get the correct parent.
Can’t position pages manually: Stack layouts override manual positions. Switch to Free layout with engine.scene.setLayout('Free').
Wrong page order: Child order determines visual position. Use insertChild(stack, page, index) to move pages to specific positions.
API Reference#
| Method | Description |
|---|---|
engine.scene.create(layout, options) | Create a scene with specified layout type |
engine.scene.getLayout() | Get the current scene layout type |
engine.scene.setLayout(layout) | Change the scene layout type |
engine.block.findByType('stack') | Find the stack container block |
engine.block.setFloat(id, 'stack/spacing', value) | Set spacing between stacked pages |
engine.block.getFloat(id, 'stack/spacing') | Get current spacing value |
engine.block.setBool(id, 'stack/spacingInScreenspace', value) | Set whether spacing is in screen pixels |
engine.block.appendChild(parent, child) | Add page to stack (positions automatically) |
engine.block.insertChild(parent, child, index) | Insert page at specific position in stack |
engine.block.getChildren(id) | Get all child pages of a stack |