# Panels and layout

> Size the drawing, split a long well over several panels, choose each panel's depth window, repeat bands between pages, and handle casing stick-up.

A `WellRenderer` draws into one or more panels, each an `<svg>` element described by an `SvgInstance`:

```ts
type SvgInstance = {
  selector: string; // CSS selector of the <svg>
  width: number; // drawing width in px, without margins
  height: number; // drawing height in px, without margins
  margins: { top: number; right: number; bottom: number; left: number };
  depthRange?: [number, number]; // depth window in m
  repeatedTo?: number; // end of a band repeated from the previous panel, in m
};
```

The SVG element is sized to `width + left + right` by `height + top + bottom`. Keep about 40 to 50 px on the left for the depth scale.

## One panel

With one panel and no `depthRange`, the whole well is drawn to fit the height. The depth scale is linear, so a 1561 m well and a 10 m well both fill the panel.

## Several panels

Long wells drawn in one panel lose detail. Give several panels and, by default, `draw()` splits the depth between them in proportion to their heights, back to back:

```ts
const margins = { top: 24, right: 16, bottom: 20, left: 48 };

new WellRenderer([
  { selector: '#part-1', width: 380, height: 700, margins },
  { selector: '#part-2', width: 380, height: 700, margins },
  { selector: '#part-3', width: 380, height: 700, margins },
]);
```

Place the three SVGs side by side to read the well as columns, as on a printed profile.

## Choosing depth windows

Give **every** panel a `depthRange` to choose the windows yourself. Panels may then overlap or skip depths:

```ts
new WellRenderer([
  { selector: '#p1', width: 480, height: 600, margins, depthRange: [0, 124] },
  {
    selector: '#p2',
    width: 480,
    height: 700,
    margins,
    depthRange: [116, 292],
    repeatedTo: 124,
  },
]);
```

`repeatedTo` marks the band `[116, 124]` of the second panel as a repetition of the end of the first. It is hatched and labelled using `renderConfig.overlap.label` (`{range}` becomes `116–124 m`). This is how paged PDF output repeats a few meters at the top of each page.

## Stick-up and the top of the drawing

Depth zero is the ground surface. A casing, screen or surface case with a negative `from` sticks up above it ([depths and intervals](/format/concepts/depths-and-intervals)), and the renderer draws it to scale above the wellhead pad. The default split therefore starts at the highest stick-up, not at 0. `getProfileTopDepth(well)` returns that depth, so you can start your first `depthRange` there:

```ts
import { getProfileTopDepth } from '@welldot/render';

const top = getProfileTopDepth(well); // e.g. -0.5
const ranges: [number, number][] = [
  [top, 120],
  [120, 265],
];
```

## Responsive width

The renderer does not observe its container. To follow the page width, create a new renderer when the container resizes (debounced), as the live previews on this site do:

```ts
const observer = new ResizeObserver(() => {
  clearTimeout(timer);
  timer = setTimeout(redraw, 150);
});
observer.observe(container);
```

where `redraw` builds a `WellRenderer` with the container's `clientWidth` minus the margins, calls `prepareSvg()` and draws.

## Column proportions

`renderConfig.layout` sets how much of the width the construction column takes (`pocoWidthRatio`) and where it sits (`pocoCenterRatio`); `renderConfig.geologic` sets the lithology column's insets. The two presets differ here: `INTERACTIVE_RENDER_CONFIG` is laid out for a screen, `STATIC_RENDER_CONFIG` leaves room on the right for description annotations, as in printed reports.
