How to Align Text With a Diagonal Image

diagonal image text

One OSTraining customer asked for a way to align text next to a diagonal image, while keeping space between both elements.

My first thought was to add breaklines at specific points of the text, however that didn’t work because the site was responsive.

After talking with the customer we came up with a more elegant solution …

The use case

In this example, the text needs to be aligned to the left, and the image to the right. The real challenge here is that the text must not overlay the image. The result we want is shown below:

2

The solution

We can add empty divs floating on the right with dynamic width values to force the text not to overlay the image. Note, in this example the image is added as background with CSS.

1

The HTML

The HTML for this example looks this way:

<div id="container">
<div class="spacing"></div>
<div class="spacing"></div>
<div class="spacing"></div>
<div class="spacing"></div>
<div class="spacing"></div>
<div class="spacing"></div>
<div class="spacing"></div>
<div class="spacing"></div>
<div class="spacing"></div>
<div class="spacing"></div>
<div class="spacing"></div>
<div class="spacing"></div>
<div class="spacing"></div>
<div class="spacing"></div>
<p>A buch of dummy text goes here...</p>
</div>

You can noticed the multiple empty divs with spacing class. Those elements in combination with some CSS generate the spacing between text and the image.

The number of spacing divs is equal to the number of text lines required to fill the image’s height. In this example the image needs to be covered with 14 lines.

The CSS

I’ll split the required CSS into several parts for a better explanation.

#container {
background-image: url(bg.png);
background-repeat: no-repeat;
background-position: right top;
background-size: 300px auto;
min-height: 300px;
}

Defines the image as background with a specific position and size.

#container p {
line-height: 22px;
font-family: Arial, "Helvetica Neue", Helvetica, sans-serif;
font-size: 14px;
}

#container p selector makes reference to the text. It’s highly important to define the font-size and line-height to calculate the values of other properties later.

.spacing {
float: right;
clear: right;
height: 22px;
}

This properties tells the empty divs to float on the right. Note, the value for height is the same we use for line-height in the paragraphs.

.spacing:nth-child(1) {
width: 305px;
}
.spacing:nth-child(2) {
width: 283px;
}
.spacing:nth-child(3) {
width: 261px;
}
.spacing:nth-child(4) {
width: 239px;
}
.spacing:nth-child(5) {
width: 217px;
}
.spacing:nth-child(6) {
width: 195px;
}
.spacing:nth-child(7) {
width: 173px;
}
.spacing:nth-child(8) {
width: 151px;
}
.spacing:nth-child(9) {
width: 129px;
}
.spacing:nth-child(10) {
width: 107px;
}
.spacing:nth-child(11) {
width: 85px;
}
.spacing:nth-child(12) {
width: 63px;
}
.spacing:nth-child(13) {
width: 41px;
}
.spacing:nth-child(14) {
width: 19px;
}

The above code is the fun part that may require to use a calculator.

The width value choosen for .spacing:nth-child(1) will apply to the first div with spacing class, in same way .spacing:nth-child(2) define a slightly smaller width and so on until it reaches the spacing element number 14.

The reason to define dynamic values from higher to lower to each empty div on the right makes possible keep the text aligned to the left without overlaying the image.

4

That being said, how can we calculate the width of each of those empty divs? The answer requires a small formula based on the values of:

  • line-height for the text (22px in my example)
  • background-size (300px in this example)

The width for the first empty div is 305px, which is the value of the defined background’s width plus 5 extra pixels I decided to include to avoid the text be too closer to the image’s edge.

Responsive support

Using the example code the design will work fine in any screensize. Take a look at the demo and resize the browser to see it in action.

See a demo

Bonus: LESS

One alternative to going directly to CSS is LESS. We have a tutorial if you are new to LESS.

You can generate the same result using LESS to dynamically create the multiple width values for each div with spacing class easily without worrying about math.

@textHeight: 22px;
@backgroundWidth: 300px;
@extraSpacing: 5px;
@initialWidth: @backgroundWidth + @extraSpacing;
@textLines: @backgroundWidth / @textHeight;

Decide the height for the text and background width through the variables.

#container {
background-image: url(bg.png);
background-repeat: no-repeat;
background-position: right top;
background-size: @backgroundWidth auto;
min-height: @backgroundWidth;
}

The container’s properties.

#container p {
line-height: @textHeight;
font-family: Arial, "Helvetica Neue", Helvetica, sans-serif;
font-size: @textHeight - 8;
}
.spacing {
float: right;
clear: right;
height: @textHeight;
}

The text and spacing properties calculated dynamically based on some variables.

.generate-spacing(@i, @end) when (@i <= @end) {
.spacing:nth-child(@{i}) {
width: @initialWidth - ((@i - 1) * @textHeight);
}
.generate-spacing((@i + 1), @end);
}
.generate-spacing(1, @textLines);

The loop that generates the dynamic width for all the empty divs.

Test this code in Codepen

Author

  • Valentin Garcia

    Valentin discovered Joomla in 2010, and since then he has considered it as the best CMS. Valentin has been coding extensions and templates for Joomla for many years and truly enjoys helping people build their own websites with Open Source tools. He lives in San Julián, Jalisco, México.

    View all posts
0 0 votes
Article Rating
Subscribe
Notify of
guest

5 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
SheilaB
SheilaB
8 years ago

I’m the customer who presented this design problem to OSTraining. I would love to take credit for the spaced divs, but I found it on the net. Eight years ago Nate Weiner posted his code for diagonal text wrapping here:

[url=http://blog.ideashower.com/search/wrapper]http://blog.ideashower.com/…[/url]

and here
[url=http://www.csstextwrap.com/#export]http://www.csstextwrap.com/…[/url]
Now Valentin has made that code responsive. Way cool!
Thanks!

SheilaB

steve
steve
8 years ago
Reply to  SheilaB

Thanks Sheila! It’s great to work with customers like you are we really engaged in finding the solution.

Mark Conroy
Mark Conroy
8 years ago

I’ve a feeling the CSS “shape outside” property could do what you want in about three lines of code.
[url=https://css-tricks.com/almanac/properties/s/shape-outside/]https://css-tricks.com/alma…[/url]

SheilaB
SheilaB
8 years ago
Reply to  Mark Conroy

Much simpler but the shape-outside property is not supported by FireFox or IE:

[url=https://developer.mozilla.org/en-US/docs/Web/CSS/shape-outside]https://developer.mozilla.o…[/url]

Teddy
Teddy
5 years ago

Valentin, THANK YOU!!! VERY helpful

5
0
Would love your thoughts, please comment.x
()
x