How to Align Text With a Diagonal Image

| Web Design
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


About the author

Valentín creates beautiful designs from amongst the tequila plants of Jalisco, Mexico. You can see Valentín's design work all over this site and you can often find him helping members in support.