Ymotion
Help
Dashboard
All pages

Guides

Formats and layout

Choosing a canvas shape, safe areas on vertical video, margins and hierarchy, and placing layers exactly by measuring them.

This page is about where things go: the canvas's shape, the parts of a vertical frame that apps cover, margins, hierarchy, and the After Effects tools for placing layers exactly. Every position is a fraction of the canvas, so a layout scales with the canvas when its size changes.

Choosing a shape

A film started with no size takes the width, height and frame rate of the first video placed in it, so place footage before laying anything out over it: once a title or a shape is in, a video arriving after it fits into the frame that's already there rather than reshaping it. When the person asks for a particular shape, give it when the film is made, by preset or by width and height:

ymotion_doc {"action":"new","preset":"vertical1080"}

The presets are:

  • uhd4k — 3840x2160 at 30 fps
  • hd1080 — 1920x1080 at 30 fps
  • hd720 — 1280x720 at 30 fps
  • square1080 — 1080x1080 at 30 fps
  • portrait1080 — 1080x1350 at 30 fps
  • vertical1080 — 1080x1920 at 30 fps
  • vertical2160 — 2160x3840 at 30 fps

The shape can change at any time:

ymotion_edit {"label":"make it 4:5","ops":[
  {"verb":"setCanvas","args":{"patch":{"width":1080,"height":1350}}}
]}

Placed footage keeps its scale. A shot as wide as a vertical film still fills it at 4:5 or square of the same width, and a fit that would change nothing is refused with its whole batch. Footage that doesn't cover the new frame is fitted again, in a call of its own, such as landscape footage that was a band across a vertical film, or a vertical shot once the film is made landscape. Read its box first; it covers while onCanvas.fraction starts at or before 0 and reaches 1 or past on both axes:

ymotion_read {"what":"box","layerId":"<footage layer id>"}

Then fit what doesn't: "contain" shows the whole shot with bars, "cover" fills the frame and crops what overflows:

ymotion_edit {"ops":[{"verb":"fitToComp","args":{"layerId":"<footage layer id>","how":"cover"}}]}

After a cover fit, x and y choose what the crop keeps (positive x slides the footage right, showing more of its left side) and scale zooms in further. Judge a crop by rendering it; Footage, images and the library has more.

Adapting a reference video

A supplied reference guides the style, hierarchy and animation. Its dimensions, text sizes, boxes and transform values are not settings to copy: the user's source resolution, aspect ratio, subject and available space can differ. Keep the requested or existing output shape; a reference alone is not a request to change it. With no chosen size, let the user's first source video establish the canvas.

Recalculate text sizes, wrapping, graphics, spacing and placement for that canvas and footage, keeping the reference's visual hierarchy. Measure the actual text and inspect the whole frame through motion; ordinary captions still belong below the face.

Preserve the user's video proportions. Use contain when the whole shot matters and cover only for an intentional crop that keeps the important action visible. Do not use fill, copy reference scale values, or stretch width and height independently to force a match. Preserve the fit computed for this source and use transform.scale for a proportional zoom. When the aspect ratios differ, adapt the layout or use deliberate padding instead of distorting the footage.

How a position works

transform.x and transform.y are measured from the canvas's centre, +y down, x as a fraction of the width and y of the height. A shape's width and height are fractions of those same two lengths, so a square on a vertical canvas has two different numbers. Type size is a percentage of the short edge, from 0.5 to 120.

Type is set inside a frame the size of the canvas: align (left, centre, right, justify) places the block across it and anchor (top, middle, bottom) up and down, flush to its edges, and transform.x and y move it from there. A new text layer is left-aligned, anchored to the middle and allowed the full width (maxWidth 1). So left-aligned type with x 0.08 starts about 8% in from the left, and type anchored to the top with y 0.2 starts about a fifth of the way down.

Layers on screen at the same time need tracks of their own: a second layer added to a track over the same seconds, in the default "overwrite" mode, cuts those seconds out of the first. Make the tracks first, in one batch:

ymotion_edit {"ops":[{"verb":"addTrack","args":{"kind":"visual","name":"Kicker"}},{"verb":"addTrack","args":{"kind":"visual","name":"Subline"}}]}

Safe areas on vertical video

Short-video apps draw their own interface over a vertical film: roughly the bottom fifth holds the description and account name, and a column about an eighth of the width down the right edge holds the buttons. They vary by app, so treat them as approximate and leave a little room.

A temporary shape makes a guide. Put a translucent rectangle over the bottom fifth on a track of its own, render, and remove the track when you're done:

ymotion_edit {"ops":[{"verb":"addTrack","args":{"kind":"visual","name":"Guide"}}]}
ymotion_edit {"ops":[{"verb":"addLayer","args":{"trackId":"<guide track id>","start":0,"duration":6,"name":"guide",
  "content":{"kind":"shape","shape":{"kind":"rect","width":1,"height":0.2,"radius":0,"fill":"#FF0000@35"}}}}]}
ymotion_edit {"ops":[{"verb":"setTransform","args":{"layerId":"<guide id>","patch":{"y":0.4}}}]}

Centred at y 0.4, it covers 0.8 to 1.0 of the height. Another on its own track, width 0.12 and height 0.5 at x 0.44 and y 0.1, marks the right-hand column. ymotion_edit {"ops":[{"verb":"removeTrack","args":{"trackId":"<guide track id>"}}]} takes a guide away with its track.

Margins

Margins are fractions too, so they keep their proportion when the canvas changes. Starting points:

  • Vertical: about 0.06–0.08 of the width at the sides, and about 0.08–0.1 of the height at the top.
  • Landscape: about 0.05 of the width and of the height.

Since x and y are fractions of different lengths, one number is a different distance on each axis of a non-square canvas. For equal margins in pixels, scale by the canvas's proportions: on 1080×1920, 0.08 of the width (86 pixels) matches 0.08 × 1080 / 1920 = 0.045 of the height.

Caption and title regions

Keep ordinary speech captions below the face; reserve headroom for hooks, titles and explanatory graphics. On a vertical frame, bottom-anchored text at y around −0.25 starts its bottom around 75% of the height. A long caption grows upward, so inspect its complete ink bounds and the face across its whole time, especially during zooms. The top of that box must remain below the lowest chin position you observed, with a visible gap.

When lower space is tight, shorten phrases, balance lines, reduce travelling entrances or create a lower band by reframing. Do not solve the collision by moving speech captions into the upper title region. A frame or geometry reading alone cannot establish both contrast and subject clearance; use the received images and measured box together.

Hierarchy

Hierarchy lets someone read a frame in the order you meant. Size does most of the work; weight, colour and spacing do the rest. Starting points on a vertical film:

  • Headline: size 10–14. The default face, Inter, is already a bold (800); weight 900 adds punch.
  • Supporting line: size 4–5, weight 400–500, in a quieter paint such as "#FFFFFF@70".
  • Label above a headline: size 2.5–3.5, "uppercase":true, with tracking 0.15–0.2 to open it up.

Keep related things close and separate groups with more space than sits within them. A label belongs nearer its headline than the headline is to the next block. Type and titles covers faces and the Character panel.

Compose the whole frame

A good layout has a reading order, not just several boxes that fit. Decide what owns attention at this moment: the speaker, a product detail, a control in use, or the text explaining it. Give that thing the clear space and strongest contrast. Supporting layers point toward it and settle while it is being examined. A large hook and an animated caption competing with a demonstration can both be legible while making the demonstration harder to follow.

Use shared margins and alignment edges for recurring roles, with consistent gaps inside a group and more space between groups. Align at a settled moment, then inspect the entrances and exits too: layers that align at rest can still collide while travelling. A template is part of this layout, so its placement, palette and type should agree with the surrounding captions and graphics rather than introduce a second design system.

Protect the subject in either cut-out state. Faces, hands in use, a product's detail, a control and a dancer's feet are part of what the viewer is reading. Clear space must remain clear across the text's whole span, including a punch-in or the subject's largest move. A cut-out gives depth; it does not justify hiding the important word behind a head or putting every caption across the body. Where space runs out, simplify the text or supporting decoration before shrinking its reading size. Look at the whole frame as well as each measured box.

Measuring a layer

ymotion_read {"what":"box","layerId":"<layer id>"} is After Effects' sourceRectAtTime: how big a layer really is and where it lands, in pixels and, under fraction, as fractions of the canvas:

  • letters: the geometry itself, the letterforms or the path, in the layer's own space.
  • ink: the letters plus what the layer's own stroke or shadow reaches past them; layer styles and filters aren't counted.
  • onCanvas: where the letters land on the frame after the layer's transform, and its parent's if it has one. This is the box alignment works with.
  • margin: how far the ink reaches past the letters on each side, in pixels only.

t picks the moment in seconds from the layer's start (default 0). Content and transform keys resolve there: type size, source words, shape dimensions and animator fields. Geometry and ink share animator position, scale and tracking; animator rotation and skew still need rendered-frame inspection. onCanvas adds parents and the source crop, so measure after any entrance has finished.

Type is measured with its real face, which box loads before measuring, as centerAnchor, alignLayers, distributeLayers, fitToComp and applyPreset do. If the face still can't be had, box answers not_observable rather than a stand-in's size.

Placing by measurement

To put a layer's top exactly at a fraction of the height, compare where it is with where you want it. For a layer that isn't parented or rotated, changing y by some amount moves its box by the same amount, so:

new y = current y + (target top − onCanvas.fraction.top)

For example, a line of size-10 capitals in the default face, anchored to the top with y 0.2, measures its letters' top at about 0.213 on a vertical canvas, because a line has a little room above its capitals (lowercase ascenders reach a little higher, so measure the actual text). To put the capitals at 0.2, set y to 0.2 + (0.2 − 0.213) = 0.187:

ymotion_edit {"ops":[{"verb":"setTransform","args":{"layerId":"<headline id>","patch":{"y":0.187}}}]}

ymotion_read {"what":"layer","layerId":"<layer id>"} gives the current transform. For most placements, the commands below do this arithmetic for you.

Center anchor

A layer scales and rotates about its anchor point. For type, the anchor starts out in the middle of the canvas-sized frame the text is set in, so a scale or a turn swings the words around the frame's centre rather than their own. centerAnchor is After Effects' Center Anchor Point in Layer Content: it moves the anchor to the middle of what the layer draws and the position to match, so nothing shifts. Do it before animating scale or rotation:

ymotion_edit {"ops":[
  {"verb":"centerAnchor","args":{"layerId":"<headline id>"}},
  {"verb":"keyRamp","args":{"layerId":"<headline id>","path":"transform.scale","from":0.9,"to":1,"opts":{"start":0,"end":0.5,"ease":"cubicOut"}}}
]}

Align and distribute

alignLayers is After Effects' Align panel: "to":"comp" (the default) lines layers up against the frame, "to":"selection" against the box around all of them, with horizontal left, centre or right and vertical top, middle or bottom. Type at different sizes doesn't line up just because it shares an x, since the space beside each letter grows with the size; aligning to the selection lines up the letters themselves:

ymotion_edit {"label":"line up the card","ops":[
  {"verb":"alignLayers","args":{"layerIds":["<kicker id>","<headline id>","<subline id>"],"opts":{"horizontal":"left","to":"selection","at":1}}},
  {"verb":"distributeLayers","args":{"layerIds":["<item 1 id>","<item 2 id>","<item 3 id>"],"opts":{"axis":"vertical","at":1}}}
]}

distributeLayers is After Effects' Distribute: it evens the gaps between three or more layers, leaving the outermost two where they are, so a tall layer and a short one sit evenly. Equal gaps suit a list of peers; in a hierarchy, place a label against its headline yourself.

Both measure each layer at one moment, which "at" sets in timeline seconds. Without it, each layer is measured at its own first frame, the wrong moment for anything with an entrance: a headline still scaling in is narrower than it will be, and aligning that box leaves the finished one out of line. Pick a moment when everything is at rest, as "at":1 does above.

Aligning to the comp puts a layer flush with the frame's edge. For a margin, align first, then read the layer's transform with ymotion_read {"what":"layer","layerId":"<layer id>"} and move it in by the margin: add it to x after aligning left or to y after aligning top, subtract it after aligning right or bottom.

Fitting type to the frame

fitToComp also works on type: it centres the anchor with position compensation, then scales the visible letters, keeping their existing content centre steady. It accounts for the layer's own rotation for contain/cover; align separately when that centre should move to the canvas centre. Together with centerAnchor, a scale and alignLayers, it sets a headline that fills the width with a margin each side:

ymotion_edit {"label":"fill the width","ops":[
  {"verb":"setText","args":{"layerId":"<headline id>","patch":{"point":true}}},
  {"verb":"centerAnchor","args":{"layerId":"<headline id>"}},
  {"verb":"fitToComp","args":{"layerId":"<headline id>","how":"contain"}},
  {"verb":"setTransform","args":{"layerId":"<headline id>","patch":{"scale":0.84}}},
  {"verb":"alignLayers","args":{"layerIds":["<headline id>"],"opts":{"horizontal":"centre","vertical":"middle"}}}
]}

point makes it one line that breaks only at a newline. fitToComp writes scaleX and scaleY, and scale multiplies both, so 0.84 leaves 8% of the width on each side. That holds while the width is what stops the fit, as it is for almost any line on a vertical canvas; on a landscape frame a short word can reach the top and bottom first, and then the 8% is of the height.

Keeping a group together

To move a block of layers as one, parent them to a null, a layer that only carries a transform; each child keeps its own animation. Give the null its own track, then parent the block with "keep":true so nothing jumps:

ymotion_edit {"ops":[{"verb":"addLayer","args":{"trackId":"<rig track id>","start":0,"duration":4,"name":"Card rig","content":{"kind":"null"}}}]}
ymotion_edit {"label":"move the card as one","ops":[
  {"verb":"parentAll","args":{"layerIds":["<kicker id>","<headline id>","<subline id>"],"parentId":"<rig id>","opts":{"keep":true}}},
  {"verb":"keyRamp","args":{"layerId":"<rig id>","path":"transform.y","from":0.05,"to":0,"opts":{"start":0,"end":0.6,"ease":"cubicOut"}}}
]}

A parent passes on position, scale and rotation but not opacity, as in After Effects. To fade a block as one picture, pre-compose it; see Compositions and nesting.

Good to know

  • A command that changes nothing is reported as an error. Aligning a layer that's already aligned says so, and because a batch is atomic, nothing else in that batch is applied either.
  • Render to check. Measuring gives the numbers; a frame shows whether the layout reads: ymotion_render {"t":1}.

See also