Yet another take on layout breakouts

ankitg123 pts0 comments

Noah Liebman | Yet another take on layout breakouts

Microphone logo

Noah Liebman

UX<br>audio<br>data<br>code

Yet another take on layout breakouts

May 30, 2024

I have now implemented a much more powerful and flexible version of this approach as Mathy Margins. Check it out!

A common design pattern is content that fills the screen with some gutter on small viewports, then has some maximum width to keep things readable. Sometimes, though, you want something that’s wider than that maximum width, either full screen width (edge-to-edge), or that breaks out, where it’s wider by some amount when there’s enough space.

How to implement these “layout breakouts” is very well worn territory, but here’s my take. Is it novel in 2024? I have no idea.

:where(.max-inline-size-padded) {<br>& > * {<br>/* default configuration */<br>--max-inline-size: 50rem;<br>--gutter: 16px;

max-inline-size: var(--max-inline-size);<br>margin-inline: max((100% - var(--max-inline-size)) / 2, var(--gutter));<br>Walking through this, it starts by setting up a utility class. I called it max-inline-size-padded because I’m a big fan of logical properties; inline-size is width in horizontal languages like English.

Then, using native CSS nesting, it sets some properties on & > *, which means all direct children of an element with the max-inline-size-padded class. The first couple of declarations set custom properties for the default configuration. --max-inline-size is how wide the content is allowed to get, and --gutter is how much space to leave on the left and right (aka inline-start and inline-end) when the container is smaller than the maximum width.[1]

The next two lines are the heart of this approach. Remember, these apply not to the container, but to its immediate children. The first declaration caps that inline size at the value we provided.

The second line centers the content by calculating the margin. The first argument to the max() function handles the case when the container is wide enough that the max size gets imposed. It takes the full width of the container and subtracts out the max width of the content, leaving the remaining available space. Then, it divides that in half because half of margin-inline is applied to the left (inline-start) and half is applied to the right (inline-end). This has the same effect as the typical way you’d center something with margin-inline: auto. The problem with that is that you can’t do math on auto[2]. Since we need to use max(), we need to do the calculation that comes up with the value that auto would normally give us for free.

The second argument to max() is the gutter. When the container is large enough that there’s more than --gutter remaining after subtracting/halving --max-inline-size out of 100% of the inline size, the first argument is larger so that’s the value of margin-inline. But when the container is smaller than that, the first argument is small (usually negative), so --gutter is greater and that gets applied. That ensures that there’s always at least --gutter of margin on each side.

So far so good, but we haven’t talked about breakouts yet. Here’s what I like about this technique: any child can override either or both of the configuration properties (--max-inline-size and --gutter). Items could do that as one-offs, but we can also provide additional utilities like these for common cases:

:where(.max-inline-size-padded) {<br>/* ✂️ */

& > .breakout {<br>--max-inline-size: 54rem;

& > .edge-to-edge {<br>--max-inline-size: 100%;<br>--gutter: 0px;<br>Here, any child of our .max-inline-size-padded container with a breakout class is allowed to get wider than regular content (54rem as opposed to 50rem), and any child with the edge-to-edge class goes, well, edge to edge.

Additionally, this technique works well when nested, so you can do things like make an edge-to-edge child element be a container for additional content at the same time.

main class="max-inline-size-padded">

div class="special-block edge-to-edge max-inline-size-padded"><br>p>This is some text that's nested inside an edge-to-edge element and that is a `max-inline-size-padded` container itself. Lorem ipsum dolor, sit amet consectetur adipisicing elit. Tenetur recusandae a et ea! Cumque, magnam quod. Maiores illo esse tenetur eligendi nisi incidunt adipisci odio cupiditate possimus, laudantium obcaecati iste!p>

aside class="breakout">Lorem ipsum dolor sit amet consectetur adipisicing elit. Odio illo, autem fugiat labore eius dolorem cupiditate commodi maiores consequatur aspernatur neque voluptas eligendi beatae praesentium ut, nostrum nemo, quod nesciunt?aside><br>div><br>main><br>This technique is similar to Solution 3(b) in Michelle Barker’s summary of layout breakout implementations. In her example, there’s a simple margin-inline: auto, which introduces a problem that she details: you can’t adjust an item’s size without having it centered.

This solution doesn’t have that issue. Setting max-inline-size (not --max-inline-size) on a content element will limit its...

inline size edge gutter container padded

Related Articles