---
title: "Item Size and Position"
index: 2
---
# {frontmatter.title}

> [!TIP]
> Read the entire page, understanding this is critical to building a well designed shell.

@@QtQuick.Item has two sets of size properties, actual size (@@QtQuick.Item.width and @@QtQuick.Item.height)
and implicit / desired (@@QtQuick.Item.implicitWidth and @@QtQuick.Item.implicitHeight).

Container items, such as layouts and wrappers, use the implicit size of their children to determine
their own implicit size, and their actual size to detetermine the actual size of their children.
If managed by a container, an Item should not set its own size, and should instead allow
the container to determine it based on its implicit size.

Put simply, implicit size should flow from children to parents, while actual size should flow from
parent to children.

In addition to size, Items also have position properties (@@QtQuick.Item.x and @@QtQuick.Item.y).
Similarly to actual size, (actual) position should not be set directly if your item is managed
by a container, though there is no such thing as implicit position.

> [!WARNING]
> Many QtQuick Items have *zero size* by default (both implicit and actual).
>
> An invisible zero sized item (usually a custom container without implicit size set)
> is a common bug and often manifests as an item being laid out as if it took no space.
>
> Quickshell will attempt to detect zero sized items when a window is initially made visible
> and log a warning, but it cannot detect all cases. Please be aware these exist.

## Container Items
Below is an example container which adds a margin to a rectangle, and interacts properly
with other container types.

```qml
@@QtQuick.Item {
  property real margin: 5
  
  // Set the implicit size of the containing item to the size of
  // the contained item, plus the margin on each side.
  implicitWidth: child.implicitWidth + margin * 2
  implicitHeight: child.implicitHeight + margin * 2

  @@QtQuick.Rectangle {
    id: child

    // Set the size of the child item relative to the actual size
    // of the parent item. If the parent item is constrained
    // or stretched the child's position and size will be similarly
    // constrained.
    x: parent.margin
    y: parent.margin
    width: parent.width - parent.margin * 2
    height: parent.height - parent.margin * 2
    
    // The child's implicit / desired size, which will be respected
    // by the container item as long as it is not constrained
    // or stretched.
    implicitWidth: 50
    implicitHeight: 50
  }
}
```

If we were to write this as a reusable component, we could use @@QtQml.Binding
to control the child item's actual size and position.
```qml
@@QtQuick.Item {
  id: wrapper
  property real margin: 5
  required default property Item child

  // Set the item's visual children list to just the passed item.
  children: [child]

  implicitWidth: child.implicitWidth + margin * 2
  implicitHeight: child.implicitHeight + margin * 2

  // Bind the child's position and size.
  // Note that this syntax is exclusive to the Binding type.
  @@QtQuick.Binding { wrapper.child.x: wrapper.margin }
  @@QtQuick.Binding { wrapper.child.y: wrapper.margin }
  @@QtQuick.Binding { wrapper.child.width: wrapper.width - wrapper.margin * 2 }
  @@QtQuick.Binding { wrapper.child.height: wrapper.height - wrapper.margin * 2 }
}
```
Note: @@Quickshell.Widgets.WrapperItem is a builtin component that adds margins similarly to this.

### Reducing boilerplate with Anchors
We can reduce the amount of boilerplate we have to write using
[QtQuick Anchors](https://doc.qt.io/qt-6/qtquick-positioning-anchors.html).

Anchors exist as a shorthand way to achieve many common position and size bindings.
See the linked qt documentation for more details on how to use them.

The following example is equivalent to the one above, but uses anchors instead of setting
position and size directly. A similar change can be made to the `Binding` example.
```qml
@@QtQuick.Item {
  property real margin: 5
  
  implicitWidth: child.implicitWidth + margin * 2
  implicitHeight: child.implicitHeight + margin * 2

  @@QtQuick.Rectangle {
    id: child

    // "Fill" the space occupied by the parent, setting width
    anchors.fill: parent
    // Add a margin to all anchored sides.
    anchors.margins: parent.margin
    
    implicitWidth: 50
    implicitHeight: 50
  }
}
```

### childrenRect and binding loops
The most common mistake made when creating container items is trying to use @@QtQuick.Item.childrenRect
to determine the size of a child item, such as in the example below:

```qml
@@QtQuick.Item {
  implicitWidth: childrenRect.width
  implicitHeight: childrenRect.height
  
  @@QtQuick.Rectangle {
    anchors.fill: parent

    implicitWidth: 50
    implicitHeight: 50
  }
}
```

While the snippet above might look like it should work, it is actually hiding a nasty bug.

As stated at the top of the page, an item's implicit size should be used to determine
its parent's implicit size, and the parent's actual size should be used to determine
the child's actual size. **`childrenRect` breaks this pattern.**

`childrenRect` encompasses the geometry of all child items, meaning their *actual* geometry,
not their *implicit* geometry. This results in the container item's size having an indirect
dependency on itself, in what is known as a *binding loop*.

If we were to try to figure out what implicitWidth is by hand, it would look something like this:

*container.implicitWidth = container.childrenRect.width = child.width = container.width (via anchor)
= container.implicitWidth = ... (repeats forever)*

which isn't a valid definition.

### MarginWrapper components
To solve the boilerplate problem that often leads users to `childrenRect`, Quickshell comes with
@@Quickshell.Widgets.MarginWrapperManager and a set of components based on it.

@@Quickshell.Widgets.MarginWrapperManager automatically handles the size and position relationship
between a container item and a single child item, skipping most of the boilerplate in the above
examples. See its linked documentation for more information on how to use it.

Rewriting the examples from the top of the page:
```qml
@@QtQuick.Item {
  @@Quickshell.Widgets.MarginWrapperManager { margin: 5 }
  
  // Automatically detected by MarginWrapperManager as the
  // primary child of the container and sized accordingly.
  @@QtQuick.Rectangle {
    implicitWidth: 50
    implicitHeight: 50
  }
}
```

Or as a reusable component:
```qml
@@QtQuick.Item {
  // A bidirectional binding to manager.margin,
  // where the default value is set.
  property alias margin: manager.margin
  
  // MarginWrapperManager tries to automatically detect
  // the primary child of the container, but exposing the
  // child property allows us to both access the child
  // externally and override it if automatic detection fails.
  property alias child: manager.margin

  // MarginWrapperManager automatically manages the implicit size
  // of the container and actual size of the child.
  @@Quickshell.Widgets.MarginWrapperManager {
    id: manager
    margin: 5 // the default value of margin
  }
}
```

Quickshell bundles three of the most commonly used wrappers, which are implemented similarly
to the example above:
- @@Quickshell.Widgets.WrapperItem
- @@Quickshell.Widgets.WrapperRectangle
- @@Quickshell.Widgets.WrapperMouseArea

## Layouts

QtQuick comes with a set of layout types in the
[QtQuick.Layouts](https://doc.qt.io/qt-6/qtquicklayouts-overview.html) module.

Layouts, such as the Row, Column and Grid layout, are extremely useful for positioning
items adjacent to eachother. See the linked qt documentation for more details.

> [!NOTE]
> Layouts have a default spacing of 5 pixels between items, not zero.
