Extending the content area using calc(...)
Most website layouts use a .content
1 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 div
s, 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-inline
3 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.
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
.content
definition might look like this:↩CSS.content { position: relative; max-width: 768px; margin: 0 auto; }
-
Make sure your
.content
class is set toposition: relative
. ↩ -
Please review whether writing-mode-aware properties (like
margin-inline
) are appropriate for your page and usemargin-left
andmargin-right
otherwise. ↩ -
It's generally less flexible, and padding must be compensated. For example, with modern
max-width
settings, likemax-width: 65ch
, used by.prose
from Tailwind. You'd have to usecalc(...)
to determine how much bigger your container needs to be. ↩