# Layout helpers — fit text, equal heights and sizes from other elements

> CSS Post Processor layout helpers: fit text to its box with font-size: fit(), equal heights with height: same, sizes from other elements and clamped spacing.

Source: https://csspp.dev/docs/layout-helpers/


The first two helpers, new in 3.1, solve problems CSS still can't. The rest have shipped since the library's first versions, before CSS had `aspect-ratio`, `clamp()` or flexbox everywhere. They still work and are handy when a value has to come from another element, but for new code the native alternative listed for each is usually better.

## Fit text to its box: font-size: fit() {#fit}

```css
.hero h1 { font-size: fit(24px, 120px); }
```

The text is sized to fill the element's width on one line, between the two limits. css-pp adds `white-space: nowrap` for you. **Native alternative:** none that works in every browser.

## Equal heights: height: same {#same}

```css
.card h3 { height: same; }
.card p  { min-height: same; }
```

Every element the selector matches gets the height of the tallest one. Unlike flexbox and grid alignment, it works across rows and separate containers. **Native alternative:** `grid-template-rows: subgrid`, when the elements share one grid.

Both helpers are recalculated after the page loads, when web fonts finish loading and when the window resizes. If a script changes a container's width, call [`css.update_vars()`](/docs/javascript-api/#css-update-vars) afterwards.

## Sizes from other elements: width() and height()

Use `width(...)` or `height(...)` as a property value to read an element's current size in pixels. `&self` means the element being styled, and you can add arithmetic:

```css
/* 16:9 box whose height follows its own width */
.video { width: 100%; height: width(&self*0.5625)px; }

/* match the height of another element */
.sidebar { height: height('#content')px; }

/* center a fixed-size popup */
.popup { position: fixed; left: 50%; margin-left: width(&self/-2)px; }
```

`width()` with nothing inside returns the viewport width. The values update when the window is resized.

**Native alternative:** `aspect-ratio: 16 / 9` for proportional boxes; `translate: -50% -50%` for centering.

## Vertical centering: vertical-align: middle!

On a block element, `vertical-align: middle!` positions the children in the vertical middle of the box. `vertical-align: bottom!` aligns them to the bottom. The `!` keeps them aligned when the element changes size.

```css
.hero { height: 100vh; vertical-align: middle!; }
```

**Native alternative:** `display: grid; place-items: center;` or `display: flex; align-items: center;`.

## Clamped margins and padding

`min-` and `max-` prefixes on margin and padding properties keep the computed value at or above, or at or below, a number of pixels. Every side is supported: `min-margin-left`, `max-padding-top` and the rest.

```css
.content { margin-left: 5%; min-margin-left: 20px; max-margin-left: 120px; }
```

**Native alternative:** `margin-left: clamp(20px, 5%, 120px);`

## Inline styles from an attribute: attr()

A standalone `attr(name)` declaration copies the CSS text in that attribute into the element's inline style. It is useful when a CMS stores a per-item background in markup:

```html
<div class="person" data-style="background-image:url(/img/team/anna.jpg)"></div>
```

```css
.person { width: 340px; height: 440px; background-size: cover; attr(data-style); }
```

`$attr(name)` is accepted too. Native `attr()` used inside a value, such as `content: attr(data-label)`, is left alone for the browser to handle.
