# sizing — how the platform sizes a control's box

> A control declares how the element it is mounted into should be sized — grow with its content, fill the box the app put it in, or keep a fixed ratio — and the platform sizes that element before the control mounts. A control never sets its own box's size, so the app's box and the control's box cannot disagree.

<!-- id: ui-control-sizing · area: ui · stability: stable · html: https://osysharp.com/reference/ui/control-sizing/ -->

## Summary        {#summary}
A control is mounted into an element the **platform** creates. What size that element is used to be nobody's job: it
was a plain block that grew with its content — right for a control that draws text, and wrong for one whose content is
all *positioned* (a canvas, a map, a camera viewfinder), which has no height of its own to grow to. Such a control
collapsed inside the app's box, and the only fix was for the control to reach out and style an element it does not
own.

**`sizing`** says it once, in the declaration, and the platform does the rest:

```osy syntax
control Map {
  contractVersion "1.1"
  participation headless
  sizing fill
  props { double lat; double lng; }
}
```

The app then decides how big the map is by sizing the box around it — never the control.

## Signature      {#signature}
```osy syntax
control <Name> {
  sizing content           // the default — the box grows with what the control draws
  sizing fill              // the box fills the space the app gave it
  sizing aspect <W> / <H>  // full width, height from the ratio — e.g. sizing aspect 16 / 9
}
```

## Description    {#description}

### The three rules   {#rules}

| `sizing` | the control's box is… | for |
|---|---|---|
| `content` *(default)* | a block that grows with what the control draws | a chart legend, a rich-text editor, a data grid |
| `fill` | 100% of a sized parent; in a stack, it grows into the space left | a canvas, a map, a viewfinder, a diagram |
| `aspect W / H` | the full width, with its height set by the ratio | a video frame, a chart that must keep its proportions |

`fill` also lets the box **shrink** inside a stack or grid track rather than forcing the track open, and in a stack
with no height of its own it keeps its content's height rather than collapsing to nothing.

### A control that fills the box you give it   {#fill}

```osy title="a canvas-like control, sized by the page around it" test app=ui-control-sizing
control Diagram {
  contractVersion "1.1"
  participation headless
  sizing fill
  props { string title; }
}

[Route("/diagram")] [AllowAnonymous]
component DiagramPage() {
  render {
    // The PAGE decides how big the diagram is — the control fills whatever this box is.
    Box(h: "480px", borderW: 1, rounded: "12px") {
      Diagram(title: "Order flow");
    }
  }
}
```

### Why the control may not size itself   {#why}

The element a control is mounted into sits in the app's layout — its parent is the app's `Box` or `Stack`, and its
size is a layout decision. A control that sets that element's height is making a layout decision about a page it has
never seen, and the two can silently disagree: measured on the flow canvas, a control that forgot to fill its host was
360px tall inside a 520px box, and a gesture that pans near the pane's edge panned the whole graph away because the
pane "ended" 160px early.

So the rule is structural rather than a convention: the platform styles the host from the declaration **before the
control's code runs**, and a control draws inside it. A control that needs a frame, a border or a background draws them
on an element of its own that fills the host.

### Diagnostics   {#diagnostics}

An unknown rule is refused with every legal form in the message:

```text
control 'Map': unknown sizing 'stretch'. A control's host is sized by one of `sizing content` (the default — the host
sizes to what the control draws), `sizing fill` (it fills the box the app put it in: a canvas, a map, a viewfinder) or
`sizing aspect W / H` (full width at a fixed ratio, e.g. `sizing aspect 16 / 9`).
```

Declaring `sizing` twice, or an aspect part that is not a positive number, is refused the same way.

## See also       {#see-also}
- [control — foreign UI controls (charts, grids, maps)](https://osysharp.com/reference/ui/controls/) — the `control` block and everything else it declares
- [The flow kit — a node-and-edge canvas whose nodes are your own Osy#](https://osysharp.com/reference/ui/flow-kit/) — a canvas that declares `sizing fill`
- [The barcode kit — a QR and barcode scanner you opt into](https://osysharp.com/reference/ui/barcode-kit/) — a viewfinder that declares `sizing fill`
- [layout primitives](https://osysharp.com/reference/ui/layout/) — how the app sizes the box around a control
