# How to build a responsive label:field form

> Align labels and fields in proportional columns with GridLayout.

Source: https://crossfly.dev/docs/cookbook/forms/formulario-responsivo — CrossFly documentation. Full docs as one file: https://crossfly.dev/llms-full.txt

# How to build a responsive label:field form

**Purpose.** Align label + field pairs in two proportional columns (e.g., 35% for the label, 65% for the field) that adapt to the screen width, using `GridLayout`.

## APIs used
- `new GridLayout(Position h, Position v)` — creates the grid with horizontal and vertical alignment of the rows (`START`, `CENTER`, `END`). The no-argument constructor uses `START, START`.
- `grid.add(Object... v)` — adds a row. **Format: all widths first, then all components.** The widths are fractions of the total width (`0.35f` = 35%); `0f` = auto-width (the component decides). The number of widths must equal the number of components.
- Each row computes its own height from that of the tallest component; the rows stack vertically.

> Argument order in `add`: `add(0.35f, 0.65f, label, campo)` — the two widths come **before** the two components, not interleaved. Passing `add(label, 0.35f, campo, 0.65f)` throws a `UIException`.

> Responsiveness: since the widths are fractions, the layout adjusts itself when the screen changes size. Use `Screen` (not `Gdx.graphics`) if you need absolute measurements.

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

import dev.crossfly.ui.*;
import dev.crossfly.ui.layout.*;
import dev.crossfly.ui.style.*;   // TextFieldStyle (config on the style)

/** 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();

      GridLayout form = new GridLayout(Position.START, Position.START);
      setLayout(form);

      // Row: label (35%) + field (65%)
      TextField nome  = new TextField("");
      TextField email = new TextField("");
      form.add(0.35f, 0.65f, new Label("Nome"),  nome);
      form.add(0.35f, 0.65f, new Label("Email"), email);

      // Masked field in the same structure
      TextField cpf = new TextField("");
      cpf.<TextFieldStyle>getStyle()
         .mask("999.999.999-99".toCharArray())
         .mode(EditMode.NUMERIC, true);
      form.add(0.35f, 0.65f, new Label("CPF"), cpf);

      // Result row
      Label resultado = new Label("");
      form.add(0.35f, 0.65f, new Label(""), resultado);

      // Auto-width row: two buttons sized by content
      Button salvar = new Button("Salvar");
      salvar.onAction(o ->
         resultado.setText(nome.getText() + " · " + cpf.getTextWithoutMask()));
      form.add(0f, 0f, new Button("Cancelar"), salvar);
   }
}
```

> The snippet below shows **only the core**. To run it, place it in the `MainWindow` skeleton above.

## Minimal snippet
```java
import dev.crossfly.ui.*;
import dev.crossfly.ui.layout.*;
import dev.crossfly.ui.style.*;
import static dev.crossfly.ui.UIConstants.Position;
import static dev.crossfly.ui.UIConstants.EditMode;

GridLayout form = new GridLayout(Position.START, Position.START);

// Row: label (35%) + field (65%)
form.add(0.35f, 0.65f, new Label("Nome"),  new TextField(""));
form.add(0.35f, 0.65f, new Label("Email"), new TextField(""));

// Masked field in the same structure
TextField cpf = new TextField("");
cpf.<TextFieldStyle>getStyle()
   .mask("999.999.999-99".toCharArray())
   .mode(EditMode.NUMERIC, true);
form.add(0.35f, 0.65f, new Label("CPF"), cpf);

// Auto-width row: two buttons sized by content
form.add(0f, 0f, new Button("Cancelar"), new Button("Salvar"));
```

Add the `GridLayout` to the screen's container/window following the pattern of your parent component.

## Dig deeper
- [Text fields](/docs/ui/forms-and-input/text-fields) · [Focus and validation](/docs/ui/forms-and-input/focus-and-validation)
- Sibling recipes: [CPF/ZIP/date mask](/docs/cookbook/forms/mascara-cpf) · [Password field](/docs/cookbook/forms/campo-de-senha)
