TL;DR? Grab the code.
This week I was presented with an interesting CSS challenge. An image in the middle of a page, with text flowing around both sides of it.
When I first looked at the design comp (not pictured), the two columns around the text jumped out at me right away as one of those well-I’m-sure-that-can-be-solved-but-I-have-no-idea-how-yet kind of problems. I set to work slicing up the comp and building the site, all the while letting this challenge ruminate in the back of my head. After a couple of hours, the build was done save for this element. And I still only had a few rough ideas of how to attack it, because there are a few details that make it extra challenging. The obvious problem of course is how to get that float to span both columns, but the extra tricky bit, if you look closely, is that the image has to float a set distance from the top of the column, rather than being anchored to the top of an element such as a paragraph. The site is being built in Drupal, so I wanted to make sure that the client was able to edit the text of both columns without worrying about how it would affect the placement of the image. Brainstorming with a co-worker, we found a few solutions that came close:
This one has the basic idea right, but it requires that the image be aligned to the top of the two columns. It set us down the right path, though. Essentially, you’re showing half of the image in each column by floating a div of half the image width, and using the background-image and background-position properties to show the appropriate half of the image in each column.
This one gets a little closer to the solution in that it allows you to arbitrarily place the image in the text without having to anchor to the top of an element. However, this article is ten years old, from before the widespread use of content management systems, and advocates simply sticking the image into the text of the paragraph wherever you’d like it. That’s fine, but you also have to match the placement of the other half of the image with a trial-and-error method in the other column. As I said above, I want the client to be able to edit the text of both columns without worrying about the image placement.
The second solution was so close, but still not quite viable. So I did what I often do when presented with a difficult problem: I made my lunch and chewed on the problem while I chewed on a pastrami sandwich. I came back to my computer and looked at it for just a second longer, and the solution became clear. What I needed was a prop of constant dimension to anchor to the top of each column, then push the two halves of the image down the appropriate distance. Using a combination of floating and clearing, I was able to put a one-pixel-wide prop before the image in each column, putting each image at the top of its respective column and therefore separating the image from the text content. Relevant bits of code are below, full working example can be found on JSBin.
Hopefully this post will help someone else facing the same problem, but who may not have the aid of a pastrami sandwich.
1) Kudos to ALA for promoting the type of content on their blog that is still mostly relevant after ten years. Taken out of a CMS context, this method is still a totally viable, semantically correct solution to the problem. Three cheers for web standards!