Combining elements

How to combine multiple elements into a single element.

Under the hood, app elements are group elements with some additional features. This means apps can create new types of elements by arranging existing types of elements into new combinations.

For example, an app element could be made up of multiple image elements, or an embed element and a shape element, or all of the different types of elements.

To make an app element that's made up of multiple elements, return one or more elements from the app element renderer callback:

designInteraction.registerRenderAppElement((data) => {
return [
{
type: "EMBED",
url: "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
width: 400,
height: 400,
top: 0,
left: 0,
},
{
type: "EMBED",
url: "https://www.youtube.com/watch?v=o-YBDTqX_ZU",
width: 400,
height: 400,
top: 0,
left: 400,
},
];
});

Each element in this callback:

  • Must have width and height properties
  • Must have top and left properties
  • Can have a rotation property

The one exception is text elements, which don't require a width and can't have a height.

You can arrange elements by adjusting their dimensions, positions, rotations, and the order in which they're rendered, but there's a number of nuances that you should be aware of.

Box model

You can think of an app element as a box.

By default:

  • The box doesn't have a width or height
  • The size of the box is calculated based the elements it contains — specifically, the dimensions of the elements and the spacing between them

The box behaves almost identically to that of group elements. The one exception is that app elements are allowed to have a single child, whereas group elements must have at least two.

Dimensions

The child elements inside an app element must have a width and a height. (The one exception is native text elements, which can't have a predefined height.)

When the width is defined as a number, the height can be set to "auto" (and vice versa). At runtime, Canva replaces "auto" with a value that maintains the aspect ratio of the element.

Positioning

Within an app element, elements must be positioned with top and left coordinates. These coordinates are relative to the element's origin — that is, the top-left corner of the element.

The origin is determined by the element's topmost and leftmost elements, which may or may not be the same element. For example, if the topmost element has a top position of 50 and the leftmost element has a left position of 100, then:

  • The top and left coordinates of the element start from 50 and 100
  • The top and left coordinates of all other elements are relative to 50 and 100

To illustrate, here's a diagram:

This can be confusing — especially if negative values are used for positions — so we recommend treating the top and left coordinates as 0 and 0, even though this isn't strictly required or enforced.

Spacing

Elements can be positioned to overlap or to have spacing between them. The size of the element then grows or shrinks to accommodate for the combined size of the elements.

When elements overlap, the ordering of the elements is determined by the order in which the elements are returned in the app element renderer callback. Elements returned later in the callback are rendered in front of elements returned earlier.

Padding

App elements do not have padding. There's always at least one element positioned against each edge of the element.

Units of measurement

Within an app element, dimensions and coordinates are defined with relative units, not absolute units. This means 200 is always twice as large as 100, but these numbers don't correspond to pixel values.

The end result is that, if a design is 1920 × 1280, setting the dimensions of an app element's elements to a combined size of 1920 × 1280 will not necessarily result in the element extending to the edges of the design. Instead, the element will be scaled to a sized that's calculated by Canva.

How Canva determines the absolute size of elements depends on a variety of factors that may change over time and is beyond the scope of this documentation.

The key takeaway is to never treat dimensions or coordinates within an app element as absolute values.