Skip to content

Layouts ​

A layout places elements in the box. It gives each element a center, a width, a height and, for an oriented ring, a rotation. All lengths are fractions of the box side, and the box goes from 0 to 1 on both axes, with y pointing down.

Pick a layout kind and change its fields. The numbered boxes are the elements, in index order.

012(0, 0)(1, 1)
The unit box goes from (0, 0) at the top-left to (1, 1) at the bottom-right.
3
0.05

3 elements

"layout": {"type":"row","count":3,"gap":0.05}
LayoutFields (default)Elements
singlesize (1), width (size), height (size), x (0.5), y (0.5)one element centered at (x, y)
stackcount, and the same fields as singlecount elements at the same place
rowcount, gap, itemWidth, itemHeighta horizontal row, centered vertically
gridcolumns, rows, gapa grid that fills the box, row by row
ringcount, itemSize, itemWidth, itemHeight, startAngle (0), orient (false)elements on a circle, clockwise

Counts (count, columns, rows) are rounded to the nearest integer and are at least 1. Any number can be a $param.

single ​

One element. Without fields, it fills the box. Use width and height for a non-square element, and x and y to move its center.

json
{
  "$schema": "https://maitrungduc1410.github.io/loader-kit/schema/v1.json",
  "schemaVersion": 1,
  "name": "LayoutSingle",
  "duration": 1.2,
  "layout": { "type": "single", "width": 0.7, "height": 0.35 },
  "shape": { "type": "rect", "cornerRadius": 0.3 },
  "tracks": [
    { "property": "rotate", "keyTimes": [0, 1], "values": [0, 3.141592654], "easing": "easeInOut" }
  ]
}
null

stack ​

count elements on top of each other, all at the same place. A stack is useful with stagger, so each copy is at a different point of its cycle. This ripple uses negative stagger offsets, so the three circles are already spread through the cycle on the first frame instead of starting together (see Stagger).

json
{
  "$schema": "https://maitrungduc1410.github.io/loader-kit/schema/v1.json",
  "schemaVersion": 1,
  "name": "LayoutStack",
  "duration": 1.5,
  "layout": { "type": "stack", "count": 3 },
  "shape": { "type": "circle" },
  "stagger": [0, -0.5, -1],
  "tracks": [
    { "property": "scale", "keyTimes": [0, 1], "values": [0, 1], "easing": "easeOut" },
    { "property": "opacity", "keyTimes": [0, 0.1, 1], "values": [0, 0.8, 0] }
  ]
}
null

row ​

count elements side by side, with gap between two elements. The vertical center is always 0.5.

  • Without itemWidth, the elements and gaps fill the width of the box: each element is (1 - gap × (count - 1)) / count wide.
  • With itemWidth, the row has that element width and is centered.
  • itemHeight defaults to the element width, so elements are square. Set it for tall bars.
json
{
  "$schema": "https://maitrungduc1410.github.io/loader-kit/schema/v1.json",
  "schemaVersion": 1,
  "name": "LayoutRow",
  "duration": 1,
  "layout": { "type": "row", "count": 5, "gap": 0.08, "itemHeight": 0.7 },
  "shape": { "type": "line" },
  "stagger": { "each": 0.1 },
  "tracks": [
    { "property": "scaleY", "keyTimes": [0, 0.5, 1], "values": [1, 0.35, 1], "easing": "easeInOut" }
  ]
}
null

grid ​

columns × rows elements that fill the box, numbered row by row from the top-left. gap is the space between two cells, both across and down.

This example uses a stagger array (one offset per element) to start the wave from the bottom-left corner.

json
{
  "$schema": "https://maitrungduc1410.github.io/loader-kit/schema/v1.json",
  "schemaVersion": 1,
  "name": "LayoutGrid",
  "duration": 1.2,
  "layout": { "type": "grid", "columns": 3, "rows": 3, "gap": 0.1 },
  "shape": { "type": "rect", "cornerRadius": 0.2 },
  "stagger": [0.2, 0.3, 0.4, 0.1, 0.2, 0.3, 0, 0.1, 0.2],
  "tracks": [
    { "property": "scale", "keyTimes": [0, 0.35, 0.7, 1], "values": [1, 0, 1, 1], "easing": "easeInOut" }
  ]
}
null

ring ​

count elements on a circle, evenly spaced. Element 0 is at startAngle (0 is to the right of the center) and the others follow clockwise. The radius is 0.5 - itemSize / 2, so the outer edge of the elements touches the box.

json
{
  "$schema": "https://maitrungduc1410.github.io/loader-kit/schema/v1.json",
  "schemaVersion": 1,
  "name": "LayoutRing",
  "duration": 1,
  "layout": { "type": "ring", "count": 8, "itemSize": 0.2 },
  "shape": { "type": "circle" },
  "stagger": { "each": 0.125 },
  "tracks": [
    { "property": "opacity", "keyTimes": [0, 1], "values": [1, 0.15] },
    { "property": "scale", "keyTimes": [0, 1], "values": [1, 0.5] }
  ]
}
null

Oriented elements ​

itemWidth and itemHeight change the element size but not the radius, which still comes from itemSize. With orient: true, each element is rotated so its top points away from the center. Use it with the line shape for a classic spinner.

json
{
  "$schema": "https://maitrungduc1410.github.io/loader-kit/schema/v1.json",
  "schemaVersion": 1,
  "name": "LayoutRingOrient",
  "duration": 1.2,
  "layout": { "type": "ring", "count": 12, "itemSize": 0.26, "itemWidth": 0.07, "orient": true },
  "shape": { "type": "line" },
  "stagger": { "each": 0.1 },
  "tracks": [
    { "property": "opacity", "keyTimes": [0, 1], "values": [1, 0.15] }
  ]
}
LayoutRingOrientOpen in playground
null

Element order and colors

Element indices follow the layout order: left to right for a row, row by row for a grid, clockwise from startAngle for a ring. Stagger arrays, durations and the colors setting all use these indices.

Exact formulas ​

The specification gives the exact formula for each layout.

Released under the MIT License.