Float an Element to the Bottom Corner
Tags: css, html, webdev, tutorial
Published: 2021-04-22 11:36:42

Need to lay out an element to the right or the left, such that text wraps around it? That's an easy task for the float property. But what about if you also want to push that element (let's call it an image) to one of the bottom corners while we’re at it? Sounds a bit tricky, right? We probably need JavaScript?

Nope, few lines of (tricky) CSS can do it! Here's the CSS-only solution that will make your image to stick to the bottom corner, regardless of the size and content.

Resize the wrapper element and see the magic at work:

{% codepen https://codepen.io/t_afif/pen/JjbEXYm %}


Let's dissect the code.

### Markup and layout

We'll need a wrapper element to contain everything, and we'll be using flexbox on it. Flexbox allows us to rely on the default stretch alignment to be able to later use `height: 100%.`

```html
<div class="wrapper">
  <div class="box">
    <div class="float"><img></div>
    Lorem ipsum dolor ...
  </div>
</div>
```
```css
.wrapper {
  display: flex;
}
.float {
  float: right;
  height: 100%;
  display: flex;
  align-items: flex-end;
  shape-outside: inset(calc(100% - 100px) 0 0);
}
```

The `.box` within the `.wrapper` is our flex item. We don't need any particular CSS applied to the box. It defines the height of the wrapper and, at the same time, is stretched to the same height. This behavior will give us a "reference height" that can be used by the child elements.

From [the specification](https://www.w3.org/TR/css-flexbox-1/#algo-stretch):

>If the flex item has `align-self: stretch`, redo layout for its contents, treating this used size as its definite cross size so that percentage-sized children can be resolved.

The keyword is the **definite** which allows us to safely use a percentage (%) height inside the box element.

### Now for the floated element

Our `.float` element will take the entire height next to the text content, thanks to the height calculation we detailed above. Inside this element we push the image to the bottom using flexbox alignment.

![Float image to right](https://i1.wp.com/css-tricks.com/wp-content/uploads/2021/04/q0prkg5dsvplig90u78x.png?w=836&ssl=1)

Now for the real trickery, using the `shape-outside` property. Here’s how [MDN defines it](https://developer.mozilla.org/en-US/docs/Web/CSS/shape-outside):

>The shape-outside CSS property defines a shape—which may be non-rectangular—around which adjacent inline content should wrap. By default, inline content wraps around its margin box; shape-outside provides a way to customize this wrapping, making it possible to wrap text around complex objects rather than simple boxes.

In other words, shape-outside sets the way content flows around an element's bounding box.

It takes a number of values. One of those is the `inset()` function which, again, [according to MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/basic-shape#inset()):

>Defines an inset rectangle. When all of the first four arguments are supplied they represent the top, right, bottom and left offsets from the reference box inward that define the positions of the edges of the inset rectangle.

So, with `shape-outside: inset(calc(100% - X) 0 0)` we can create an inset rectangle that starts exactly at the top of the image. And the top is equal to `100% - X`, where `X` is the image height and `100%` is the height of the `.float` element. This allows the text to wrap within the free space on the top of the image. This is responsive, plus we can easily switch between left and right (by adjusting the float property)

That's it! The only major caveat is that you need to know the image height.

----

## Want more?

We can extend this concept a little further to account for fancier situations. For example, we can float the image to the right, but pin it to the middle of the box with `justify-content: center` and also adjust our inset rectangle to the middle by changing the shape-outside from `inset(calc(100% - X) 0 0)` to `inset(calc(50% - X/2) 0)`

{% codepen https://codepen.io/t_afif/pen/PoWEYmX %}

We can also float two images at both bottom corners:

{% codepen https://codepen.io/t_afif/pen/WNRdeqr %}

Nothing complex here. I am simply using the same floating element twice, once on the right, and again on the left. And why stop at two corners when we can place images at all four corners:

{% codepen https://codepen.io/t_afif/pen/qBRpWPV %}

The same basic idea is at play here, but we're are also relying on the common float feature for the top images. However, you'll notice that this is where the concept starts to break down a bit, and we get some unwanted overflow depending on the size of the containing box. We can make the height of the `.float` element greater than 100% and apply somewhat "magic numbers" that smooth things out by adjusting the padding and margin of the images.

Did you know that `shape-outside` accepts `radial-gradient()` as a value? We can use that to place rounded images like below:

{% codepen https://codepen.io/t_afif/pen/ExZoYEX %}

The transparent part of the gradient is the *free* space where the text can go. You may have noticed that we applied a `border-radius` to the image as well. The `shape-outside` property will simply affect the `.float` element and we need to manually adjust the shape of the image to follow the shape defined by `shape-outside`.

While we're at it, let's combine this with our earlier example that pins the image to the vertical center of the box using `justify-content: center`:

{% codepen https://codepen.io/t_afif/pen/dyNJbeK %}

Another `radial-gradient()` and also another `border-radius` configuration.

We could have used a `linear-gradient()` instead to make a triangular shape for the wrapping area:

{% codepen https://codepen.io/t_afif/pen/GRryKGz %}

This is the same idea that we used for the `radial-gradient()`. The big difference is that we're using `clip-path` instead of `border-radius` to cut our image.

And, since we did it for the others, let's use the `justify-content: center` idea to pin the image to the vertical center of the box's right edge:

{% codepen https://codepen.io/t_afif/pen/abpEoaV %}

We used a `conic-gradient()` in the above demo with `shape-outside` to define the triangular shape and `clip-path` to get a similar shape on the image

All of these examples can still be optimized using less of code in the case that the image is decorative (when it's not needed inside the HTML for SEO purposes). Let's replace the `.float` element with a pseudo-element and apply the image as background instead:

{% codepen https://codepen.io/t_afif/pen/XWpYVVz %}

We're using mask to show just the portion of the image that we need and, guess what, it uses the same value as `shape-outside`! So, all we had to do is define one value for the shape.

### That's it!

There are a lot of possibilities here to place not just rectangles in corners, but any kind of shape at any position, using largely the same code structure. We only need to:

 * Adjust the `shape-outside` property to define the shape
 * Apply some styling to the image to follow the previously defined shape or apply the same value to mask in case we are using the pseudo element version

Then everything holds it place, even in responsive designs.