random image

Josh Comeau’s full bleed CSS Grid layout

This layout is created from a markdown file with all of the limitations that markdown comes with. No class names have been added to the markdown elements (which include the top image.)

There are several versions of this type of layout though Josh Comeau’s is beautifully simple, thus easiest to try first.

The CSS for this is very simple. Assume all the markdown is output as HTML directly into a main tag:

main {
    display: grid;
    grid-template-columns: 1fr min(60ch, calc(100% - 2em)) 1fr;
    gap: 1em;
}

main > * {
    grid-column: 2;
    margin: 0;
}
main > p:has(img) {
    grid-column: 1 / -1;
}
img {
    width: 100%;
}

Non-collapsing margins

When a paragraph or other element is a grid cell it’s top and bottom margin’s don’t collapse into one the way they normally do. So you’d get a margin that is twice as big as normal with this method. There are several fixes possible. Here the margins are removed with margin: 0; and replaced with the gap value from the grid layout. Another way would be to remove one of the paragraph’s (or other element’s) top margin.

Note that the gap property also adds some padding for smaller screen sizes where the text is at full width. Because the width of this column is 100% the value of gap (1em here) is added to that 100% which introduces horizontal scrollbars. The fix is to add a calc function to subtract the 2ems (one from each side).

Targetting the image

Because a new line in markdown means a new paragraph AND we want to target an image the parent selector has been used like so: p:has(img)

If other elements need to be spread right across the page then a full-bleed utility class could be added provided it can be added to the markdown.

.full-bleed {
    grid-column: 1 / -1;
}