This semester’s end-of-year work by my students often exhibited lengthy body copy creeping alongside and under images, or images that were far too large next to snippets of microcopy.
Part of a designer’s job is to balance text and images harmoniously: one should never overpower a web page at the expense of the other. This is most especially important in callouts - typically small runs of text with single illustrations - which must be fluid and adaptable to both changing screen sizes and an unpredictable or changing amount of content. After a little experimentation, I found a nice way to deal with the demands of both, using a combination of flexbox and background images.
Making Modules
The basic markup consists of a <figure>
element with two <div>
elements inside it. For the example above, those elements are inside an element with a class of column
. Just one of the modules is shown below:
<div class="column">
<figure class="flex">
<div></div>
<div>
<h3>Aloe polyphylla Schönland ex Pillans</h3>
<p>Endangered native of the Maluti Mountains…</p>
</div>
</figure>
</div>
The <figure>
element has the following CSS directly applied to it:
.flex {
margin: 0;
display: flex;
border: 5px solid #333;
margin-bottom: 2rem;
}
The first <div>
inside the module is empty, but will be “filled” with a background image:
.flex div:first-child {
flex: 1;
background-size: cover;
background-position: center;
}
The first div is given a “visual weight” of 1
. As the second div
is given a value of 2
, it will always be twice as wide as the first by default:
.flex div:last-child {
margin: 2rem;
flex: 2;
}
The text inside thefigure
is also styled:
.flex h3 {
font-size: 1.5rem;
margin-top: 0;
font-weight: 400;
}
.flex p {
font-size: 1rem;
line-height: 1.4;
font-weight: 400;
}
The last paragraph inside the div
is styled to have no margin-bottom
, to ensure that it does not contribute to the height of the element:
.flex p:last-of-type {
margin-bottom: 0;
}
The module elements are given their images via :first-of-type
or nth-of-type
pseudo-class selectors:
.flex:first-of-type div:first-child {
background-image: url("aloe-polyphylla.jpg");
}
Effect
As a result of the CSS, the photos will always fill the left side of the module from top to bottom, shrinking and expanding both with the horizontal size of the responsive container and with changing amounts of content. (You can experiment with this by adding and removing from the paragraph in each module on the associated CodePen demo.)
You could also reverse the layout of each module alternately with the following:
.flex:nth-child(odd) {
flex-direction: row-reverse;
}
Limits
Eventually, the images will become too tall as the modules narrow with the viewport. At that point, in addition to the standard breakpoint behaviours (reducing margin
, line-height
, font-size
, padding
, etc), you have two options:
- Change the balance of the image and text by equalizing the visual “weight” of both child elements in the module:
@media all and (max-width: 600px) { .flex div { flex: 1 !important; } }
- Change the arrangement of each module to a vertical layout:
@media all and (max-width: 400px) { .flex { flex-direction: column; } .flex div:first-child { min-height: 200px; } }
Too Big, Too Little
This approach assumes that there will always be at least some text content in each callout box, but not too much. A truly thorough system would check for both: you could use JavaScript (or in he future, element queries) to check the aspect ratio of each box, switching the flex-direction
of each early if the box was significantly taller than it was wide.
In principle, object-fit
should work in the same way for ordinary image elements next to text, but I found it problematic in the experiments I’ve created so far. It’s also likely the the CSS Grid specification would be useful; further experimentation is called for in both.
Images and text by Brewbooks and Jacinta Iluch Valero.
Enjoy this piece? I invite you to follow me at twitter.com/dudleystorey to learn more.
Check out the CodePen demo for this article at https://codepen.io/dudleystorey/pen/qqLxMz