Extending the content area using calc(...)
Most website layouts use a .content1 class with a fixed max-width to keep
text content readable on larger screens. The area grows from mobile viewport
sizes up to some maximum, usually around 768px. While this is perfect for text
content, other elements, like images, benefit from more width.
One approach to solving this is to wrap only elements that should stay within
the max-width with .content.
<main>
<h1 class="content">About my best friend</h1>
<img src="..." alt="My cat Dorothy" />
<p class="content">
My cat Dorothy has been by my side for well over 13 years, ...
</p>
</main>
However, using .content on individual paragraphs has its limitations. If
.content defines a patterned background, it won't work anymore. Even if it's
only a background color, you must be careful and use padding instead of
margin, as you'll get gaps otherwise.
I also find it unlikely that you'll want to manually annotate all your content
with .content, which might be impossible anyhow if a CMS serves it. You can't
simply apply the style to all p elements either, since others, like figure
or even regular divs, might also be top-level content.
Using calc(...)
A better way that semantically aligns with extending the content is applying
.content to the whole block2 and using a negative margin-inline3 to
pull the images or figures outward. Intuitively, you'd apply some fixed negative
margin, but this will increase the width to over 100% of the viewport width on
viewports smaller than 768px + 2* <your negative margin>, making the page
scroll horizontally and clipping your image.
The width of the space around your .content is 100% of the viewport width
minus the current width of your .content element. Therefore, the negative
margin you need to apply is exactly half of that. Fortunately, calc(...) is
widely supported in browsers now, so all you need is
margin-inline: calc((100vw - 100%) / -2). This will extend the element all the
way to the edges without clipping or scrolling.
This is an interactive demonstration of the involved measurements. My site has a minimum margin, so bear that slight behavioral difference in mind. The demo displays rounded values; the browser uses floats.
<main class="content">
<h1>About my best friend</h1>
<img class="extend-full" src="..." alt="My cat Dorothy" />
<p>My cat Dorothy has been by my side for well over 13 years, ...</p>
</main>
.extend-full {
margin-inline: calc((100vw - 100%) / 2 * -1);
}
Most of the content you'll want to expand shouldn't stretch to the entire width of the page, though, because the image to text width ratio can look out of place on big or ultra-wide displays.
The min(...) function gives you the smaller of two values. Limiting the extent
to 32px extent looks like this:
.extend-a-bit {
margin-inline: calc(
-1 *
min(
(100vw - 100%) / 2,
32px
)
);
}
Finished result
If you want to clean up a bit or need multiple extension widths, I recommend using CSS variables to set the maximum extent. Using font-size relative units so margins scale appropriately is also a good idea.
.extend {
margin-inline: calc(
-1 *
min(
(100vw - 100%) / 2,
var(--maximum-extent, 0)
)
);
}
.extend-full {
--maximum-extent: Infinity;
}
.extend-a-bit {
--maximum-extent: 8em;
}
Bonus tip: Centered content and minimum margins
Before display: flex was a thing, web developers used margin: 0 auto to
center content. Using auto has the drawback that content will touch the edges
whenever the max-width exceeds the current viewport width. You can apply
padding-inline or set fixed widths based on @media (max-width: ...). Both
have their own drawbacks4, and I prefer to use display: flex. Wrapping your
.content in a centering flex container will honor the minimum margin.
<div class="content-wrapper">
<main class="content">
<!-- ... -->
</main>
</div>
.content-wrapper {
display: flex;
justify-content: center;
}
.content {
max-width: 768px;
margin-block: 8px;
}
This only works with a flex container. Using margin: 0 auto on
.content-wrapper won't collapse the margins and thus have the same effect as
padding-inline on .content.
Footnotes
-
A typical
.contentdefinition might look like this:↩CSSblog.CSS.content { position: relative; max-width: 768px; margin: 0 auto; } -
Make sure your
.contentclass is set toposition: relative. ↩ -
Please review whether writing-mode-aware properties (like
margin-inline) are appropriate for your page and usemargin-leftandmargin-rightotherwise. ↩ -
It's generally less flexible, and padding must be compensated. For example, with modern
max-widthsettings, likemax-width: 65ch, used by.prosefrom Tailwind. You'd have to usecalc(...)to determine how much bigger your container needs to be. ↩