Looping a block
Start a loop
Select the block that should repeat. Usually that's a Group that already holds the layout of one item, such as a card with an image and two lines of text. Click Loop this block in the toolbar, or Alt+right-click the block (Option+right-click on a Mac). The Data Loop panel in the block settings has the same options.
Select loop source shows the lists you can loop over:
- Repeaters
- Field Tables
- Lists, and fields with several choices (Multiselect, Checkboxes)
- Galleries
- Files
- Select Post and Select User fields that allow several items
- Post and User Relations that allow several items
- Content sections
- A Recurring Date's entries, upcoming dates or previous dates
Then choose how many items to show:
- Items to show (0 = all)
- Skip first (offset): leave out the first few items, for example because the first photo is already shown as a hero image.
The panel shows how many items it found.
Design one item
The first item is the one you edit; the others are previews that update as you work. Click a preview item to make it the one you're editing, which helps when items look different.
Inside the loop, bind blocks with the normal paths: loop over @post(team), and a paragraph bound to @post(team.name) shows each member's name. There's no special "current item" syntax.
Show previewed items and Hide previewed items toggle the preview copies, which is useful when a long list makes the canvas hard to work with.
Loops inside loops
Loops can be nested. Loop over @post(team), then inside each card loop over @post(team.links): each member's links appear under that member, and @post(team.name) still refers to the member.
Don't nest two loops over the same list. The inner loop takes over, and the outer item can no longer be reached.
Numbering and separators
loop_index()gives the item's position, for a numbered list.is_first()andis_last()check the item's position, for example to add a separator after every item but the last:text@post(team.name)@post(team.name).is_last().then("").else(" · ")
The visibility rules Is first loop item and Is last loop item do the same for whole blocks.
Without a loop
You don't always need a loop. @post(team.name).list(", ") joins every name into one line, and @post(photos).count() counts the photos. See VX Script lists.
Limits
- One loop shows at most 200 items, whatever Items to show says.
- A loop and all the loops nested inside it show at most 5,000 items in total.
- A single image or a single relation isn't a list, so it can't be looped. Bind it directly.
- Query Loop can't use a VX list as its source. Inside a Query Loop, dynamic tags read the post the Query Loop is showing.
Technical details for LLMs
- Stored: the block's
vxframeworkLoopattribute (source expression, limit, offset). Any block can carry it; the loop renders the block once per item before visibility runs. - Sources: any catalog node with
loopable: true: list nodes (repeater,list,multiselect,checkboxes), multi-file media (gallery), and relations withmultiple. Single-value relations and single media aren't loopable. - Also loopable:
table,content_sections, recurringentries/upcoming/previous, andfiles. - Resolution: loop levels are keyed by source path; a tag resolves at the level it names. An aggregator inside a loop collapses only below the pinned item (
@post(team.links.url).count()in ateamloop counts this member's links). - Caps: 200 items per loop, 5,000 per loop tree, regardless of
limit. - Preview:
vx-framework/v1/dynamic-data/loop-preview. Block documents: an inner loop over the same source as its ancestor is flagged by document checks.