Work in progress — this reference is being written in the open. Unfinished pages are excluded from search engines.
Paged · IDML Reference
Frames & paths

Groups

How an IDML Group clusters page items, how its transform and transparency reach the members, and what the renderer does inside one.

Intermediate· explanation

A Group is the one page item that holds no marks of its own — it is a container that clusters other page items so they move as one.

In short: A Group is the IDML page item that holds no marks of its own. It is a container: its children are the page items it clusters so they can be moved, scaled, rotated, or made translucent as a single object. On disk a group's members are written as child elements of the <Group>, and the group's ItemTransform composes onto each of them. This page explains how membership and the composed transform work, how group-level transparency is captured, and what our renderer does inside a group today.

A Group is the one page item that holds no marks of its own. It is a container: its children are the page items it clusters so they can be moved, scaled, rotated, or made translucent as a single object. In the IDML on disk a group's members are written as child elements of the <Group>, exactly the way the page-item reference shapes appear as children of a <Spread>.

The example below is the smallest meaningful group: two filled rectangles wrapped so a single transform places the pair.

A Group around two rectangles. The group's ItemTransform moves both at once.

Spreads/Spread_uspread.xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<idPkg:Spread xmlns:idPkg="http://ns.adobe.com/AdobeInDesign/idml/1.0/packaging" DOMVersion="20.0">
  <Spread Self="uspread" PageCount="1" BindingLocation="0" ShowMasterItems="true" AllowPageShuffle="true" ItemTransform="1 0 0 1 0 0">
    <Page Self="upage" Name="1" AppliedMaster="umaster" ItemTransform="1 0 0 1 0 0" GeometricBounds="0 0 841.89 595.276" MasterPageTransform="1 0 0 1 0 0"/>
    <Group Self="ugroup" ItemTransform="1 0 0 1 100 120" AppliedObjectStyle="ObjectStyle/$ID/[None]" Visible="true" Name="$ID/">
      <Rectangle Self="urect1" ContentType="GraphicType" AppliedObjectStyle="ObjectStyle/$ID/[None]" Visible="true" Name="$ID/" ItemTransform="1 0 0 1 0 0" FillColor="Color/Red" StrokeColor="Swatch/None" StrokeWeight="0">
        <Properties>
          <PathGeometry>
            <GeometryPathType PathOpen="false">
              <PathPointArray>
                <PathPointType Anchor="0 0" LeftDirection="0 0" RightDirection="0 0"/>
                <PathPointType Anchor="0 180" LeftDirection="0 180" RightDirection="0 180"/>
                <PathPointType Anchor="180 180" LeftDirection="180 180" RightDirection="180 180"/>
                <PathPointType Anchor="180 0" LeftDirection="180 0" RightDirection="180 0"/>
              </PathPointArray>
            </GeometryPathType>
          </PathGeometry>
        </Properties>
      </Rectangle>
      <Rectangle Self="urect2" ContentType="GraphicType" AppliedObjectStyle="ObjectStyle/$ID/[None]" Visible="true" Name="$ID/" ItemTransform="1 0 0 1 220 80" FillColor="Color/Blue" StrokeColor="Swatch/None" StrokeWeight="0">
        <Properties>
          <PathGeometry>
            <GeometryPathType PathOpen="false">
              <PathPointArray>
                <PathPointType Anchor="0 0" LeftDirection="0 0" RightDirection="0 0"/>
                <PathPointType Anchor="0 180" LeftDirection="0 180" RightDirection="0 180"/>
                <PathPointType Anchor="180 180" LeftDirection="180 180" RightDirection="180 180"/>
                <PathPointType Anchor="180 0" LeftDirection="180 0" RightDirection="180 0"/>
              </PathPointArray>
            </GeometryPathType>
          </PathGeometry>
        </Properties>
      </Rectangle>
    </Group>
  </Spread>
</idPkg:Spread>

Membership and the composed transform

When the parser meets a <Group> it records the group and then walks its children. Each member — Rectangle, Oval, GraphicLine, Polygon, TextFrame, or a nested Group — is lifted out onto the spread's normal page-item lists, but with the group's ItemTransform already composed onto the member's own transform. Nesting composes through every level: a member two groups deep ends up with outer ∘ inner ∘ member.

The upshot is that downstream layers do not have to special-case groups to place things correctly — every member already carries its final transform. The original Group record is kept alongside (with its member list and its own un-composed transform) so a renderer that wants to bracket the cluster — for a shared opacity, blend mode, or drop shadow — still can. Both rectangles in the example paint at their composed positions; nothing is dropped.

Group-level transparency

A group can carry a transparency block that applies to all of its members at once — the reason to group shapes in the first place is often a single uniform effect:

Attribute · Group transparency (from BlendingSetting / DropShadowSetting)Type / valuesSupportNotes
Opacitydouble (0–100)Parsed, not yet renderedFrom a <BlendingSetting> attached to the Group. Captured for a whole-group composite.
BlendModeNormal | Multiply | Screen | …Parsed, not yet renderedBlend mode for the group as a unit.
DropShadow<DropShadowSetting>Parsed, not yet renderedA shadow cast by the flattened group, captured against the group rather than each child.

The parser routes a <DropShadowSetting> or <BlendingSetting> that sits directly under a <Group> (not under a StrokeTransparencySetting or ContentTransparencySetting wrapper) into that group's transparency record, so the renderer can one day bracket the member range with a single transparency group instead of compositing each shape independently.

What the renderer does inside a group today

Group members render: the lift-and-compose pass means each shape paints at its correct place, as the example proves. What is not yet honoured is the group-level transparency block — opacity, blend mode, and the group drop shadow are parsed and attached to the Group record but the whole-group composite that would apply them is still on the roadmap.

Parsed, not yet renderedGroup-level transparency (Opacity / BlendMode / DropShadow on a <Group>) is parsed and recorded but not yet composited as a whole-group effect (spread.rs:207–224).

One historical note for readers of the parser: a skipped_nested_frames counter exists on the spread record and is surfaced by paged-inspect. It dates from an earlier pass that dropped group-nested text frames; the current parser lifts those frames out instead, so the counter stays 0 (spread.rs:116–119). If you see it report a non-zero value, that is a signal worth investigating, not the expected case.

Frequently asked questions

What does a Group do in IDML? A Group clusters several page items so a single transform, opacity, or effect can apply to all of them at once. It holds no fill or stroke of its own — its only content is the members written as child elements of the <Group>.

How does a group's transform reach its members? When the parser meets a <Group> it lifts each member out onto the spread's normal page-item lists with the group's ItemTransform already composed onto the member's own transform. Nesting composes through every level, so a member two groups deep ends up with outer ∘ inner ∘ member — and downstream layers never have to special-case groups to place things correctly.

Does the renderer apply group-level opacity and drop shadows? Not yet. A group's Opacity, BlendMode, and drop shadow are parsed and attached to the Group record, but the whole-group composite that would apply them is still on the roadmap; the members themselves render at their correct composed positions today.

On this page