# Spacing (Gap)

> How to space components without Spacer — using Gap, ingap/outgap and layout fractions.

Source: https://crossfly.dev/docs/ui/widgets/spacing — CrossFly documentation. Full docs as one file: https://crossfly.dev/llms-full.txt

# Spacing (Gap)

> ⚠️ **`Spacer` was removed** in the 2026 modernization. There is no longer a spacing widget. To separate components use, in order of preference: **layout fractions** (`LAY_AUTO`/`LAY_FILL`/fraction), the components' **`ingap`/`outgap`**, or the `Gap` value directly.

`Gap` represents spacing values (left, top, right, bottom) with optional scaling. It is used throughout the UI as **padding** (`ingap`), **margin** (`outgap`), and as internal spacing for layouts. A `Gap` can be:

- **fixed pixels** — `Gap.ofPixels(...)`
- **font-relative** — `Gap.ofFont(...)` (scales with `font.scaledHeight()`, ideal for responsiveness)
- **screen-relative** — `Gap.ofScreen(...)` (percentage of the screen dimensions)

> 🟢 · **Package:** `dev.crossfly.ui` · **Extends:** `Component` · **Related:** `ComponentStyle.ingap`/`outgap`, layouts

## When to use
- Define a component's internal padding (`ingap`) or external margin (`outgap`).
- Pass spacing to a layout (e.g. gaps between cells).
- Replace the old `Spacer` with proportional space.

## When NOT to use
- To "push" a component and absorb the leftover → use a `LAY_FILL` row in the `VerticalLayout`/`HorizontalLayout` (see [`layouts/`](/docs/ui)), not a fixed `Gap`.

## Complete example (copy, paste and run)
```java
package com.exemplo;

import dev.crossfly.ui.*;
import dev.crossfly.ui.layout.*;
import dev.crossfly.ui.style.*;   // Styles, ButtonRole, State

/** Runnable main screen. Point the launcher (classname) and run: gradlew :lwjgl3:run */
public class MainWindow extends Window
{
   @Override
   public void onShow() throws Exception
   {
      super.onShow();
      setLayout(new VerticalLayout());

      // Header with natural height
      add(LAY_AUTO, new Label("Cabeçalho"));

      // Button spaced from its neighbors via outgap (margin relative to the font)
      Button b = new Button("Enviar").style(
         Styles.theme().button(ButtonRole.PRIMARY, State.NORMAL)
            .pressable()
            .outgap(Gap.ofFont(0.5f)));   // 0.5 × font height on all sides
      add(LAY_AUTO, b);

      // Footer pushed down: the LAY_FILL row absorbs the vertical slack
      add(LAY_FILL, new Label("(espaço que sobra)"));
      add(LAY_AUTO, new Label("Rodapé"));
   }
}
```

> The snippets below show **only the core** (what goes inside `onShow()`). To run them, place them in the `MainWindow` skeleton above.

### 1. Layout fractions (preferred)
```java
VerticalLayout col = new VerticalLayout();
col.add(LAY_AUTO, cabecalho);   // natural height
col.add(LAY_FILL, conteudo);    // absorbs the slack (pushes the footer down)
col.add(LAY_AUTO, rodape);
```

### 2. `ingap` / `outgap` in the style
```java
// External margin (spaces this component from its neighbors) via font-relative outgap
Button b = new Button("Enviar").style(
   Styles.theme().button(ButtonRole.PRIMARY, State.NORMAL)
      .pressable()
      .outgap(Gap.ofFont(0.5f)));   // 0.5 × font height on all sides
container.add(LAY_AUTO, b);
```

### 3. `Gap` as internal padding
```java
Label card = new Label("Conteúdo do cartão").style(
   Styles.theme().label(LabelRole.BODY)
      .ingap(Gap.ofFont(1f, 0.5f, 1f, 0.5f)));  // L,T,R,B in font units
container.add(LAY_AUTO, card);
```

## Factories (`Gap`)
| Factory | Scale | Use |
|---|---|---|
| `Gap.ofPixels(float all)` / `ofPixels(l, t, r, b)` | fixed pixels | absolute values |
| `Gap.ofFont(float all)` / `ofFont(l, t, r, b)` | × default font height | **responsive** (recommended) |
| `Gap.ofFont(Font, l, t, r, b)` | × height of the given font | rebased to a specific font |
| `Gap.ofScreen(float all)` / `ofScreen(l, t, r, b)` | % of the screen dimensions | spacing proportional to the screen |
| `Gap.none()` / `Gap.ZERO` | zero | no spacing |

## Properties and methods
| Method | Type | What it does |
|---|---|---|
| `left()` / `top()` / `right()` / `bottom()` | `int` | value resolved in pixels (scaling already applied) |
| `width()` / `height()` | `int` | horizontal sum (`left+right`) / vertical sum (`top+bottom`) in pixels |
| `withFont(Font)` | `Gap` | rebases the factors to another font (if font-relative) |
| `isFontRelative()` / `font()` | `boolean` / `Font` | queries the scaling base |

## Best practices
- For the "leftover space", use **a single** `LAY_FILL` row in the layout, not several gaps.
- Reuse `Gap.ZERO` to zero out padding without allocating objects.

## Common mistakes
- **Looking for the `Spacer` class:** it no longer exists. Use layout fractions / `Gap` / `ingap`/`outgap`.
- **Using `Gap.ofPixels` for everything:** on screens of different densities the spacing becomes inconsistent; prefer `ofFont`/`ofScreen`.
- **Trying to center with two fixed gaps:** use the layout alignment or `LAY_FILL` on both sides.

## See also
- Area guide: [`ui/`](/docs/ui) · Recipes: [`cookbook/`](/docs/cookbook)
- Concept (constraints, responsiveness): [`concepts/`](/docs/concepts)
- Related components: [`Label`](/docs/ui/widgets/label) · [`Button`](/docs/ui/widgets/button)
