DEV Community

Cover image for Responsive text based on image size
Temani Afif
Temani Afif

Posted on • Updated on

Responsive text based on image size

We all face such a requirement where we need to make a title below (or above) an image to not exceed the width of the image. In most of the cases, we need them to have the same width.

The common solutions are:

  • Make the width of the title the same as the image: not a dynamic solution since we have to manually adjust the width each time we use a different image ❌
  • Manually insert line break inside the title: Nah! a very bad idea ❌
  • Make the title position:absolute to be able to use width:100% which will refer to a container that has the size of the image ... too complicated and it will make our text out of the flow ❌

Here is an easy solution to solve this task. No hardcoding width, no out of flow content and only few line of CSS:

<div class="box">
   <img>
   <h1>Lorem ipsum dolor ..</h1>
</div>
Enter fullscreen mode Exit fullscreen mode
.box {
  display: inline-block;
}
h1 {
  width: 0;
  min-width: 100%;
}
Enter fullscreen mode Exit fullscreen mode

Yes, that's it!

This trick relies on two things:

  1. We make the container (the box element) a shrink-to-fit element (its width is defined by its content). I used inline-block but it can be a float element, a table one, a flex item, etc.
  2. We make our title have a width equal to 0 so it will not contribute to the container width. Our container will have its width defined only by the image. We add min-width: 100% to resize our title and make its width equal to the container width (the one defined previously with the image!). Yes, it's a bit crazy or let's say magic πŸ˜‰

Some working examples

In all the above examples, the image will dictate the width of the title.


This trick is not only limited to image + title. It can work with any kind of configuration where we want an element A to define the width of an element B

The title defines the width of the image

The title defines the width of a paragraph

I think everyone got the idea. There is no restriction and any kind of element (even one with complex content) can be considered for this trick.


We can extend the same logic to a column configuration to have one column defining the height of another one. This time we will rely on height:0; min-height:100%.

This one is a bit tricky since the usage or percentage height is not trivial (we all know the prophecy that says: "the parent needs to have an explicit height defined")

To overcome this, I will consider a CSS grid configuration where I don't need any explicit height.

Below, the left column is defining the size of the right one. The latter will get a scrollbar when its content exceeded the defined height.

From the specification we can read:

Once the size of each grid area is thus established, the grid items are laid out into their respective containing blocks. The grid area's width and height are considered definite for this purpose.

A grid item can safely use height:100% inside its grid area and that grid area will have its height defined based on the content and since one of them is having height:0, it will not contribute to that height (yes, the same magic as above πŸ˜‰)

Flexbox can also be used here but we need an extra wrapper for the element that will use height:0;height:100%

We need the extra wrapper because we will rely on the stretch alignment of flex items to have our defined size that will be used as a reference for the percentage.

From the specification:

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.

One element will define the height of the parent, the other will get stretched by default to that height and the content inside will get sized to the same height.

Now, you have a magic trick to avoid unwanted overflow and keep elements equal in size even if they have different content.


Some StackOverflow posts where I am using this trick:

How to match width of text to width of dynamically sized image/title?

How can you set the height of an outer div to always be equal to a particular inner div?


You want to support me?

buy me a coffee

OR

Become a patron

Top comments (10)

Collapse
 
racketywater7 profile image
Haseeb Udeen

Thanks for the tip

Collapse
 
afif profile image
Temani Afif

you're welcome ;)

Collapse
 
simevidas profile image
Ε ime Vidas

There is also .box { width: fit-content } (Autoprefixer needed). I feel this is the most simple standard way to make an element shrink-to-fit.

Collapse
 
afif profile image
Temani Afif

You probably meant width:min-content ? fit-content won't work because the largest content will define the width in this case. Even min-content won't work in all the cases. It will do only in the case of image+text where the image need to define the size (for all the other examples it won't work)

Collapse
 
simevidas profile image
Ε ime Vidas • Edited

Yes, that’s the case that I meant. Image + heading. The heading has width: 0, and the image has a specific width. We want the container to be as wide as the image, so width: fit-content.

Collapse
 
magdasokolovic profile image
Magda Sokol(...)

wow, great tip, thanks!

Collapse
 
aravind13789216 profile image
Aravind Kumar

but how do i do it horizontally

Collapse
 
lelegm profile image
lelegm

Sounds great! Anyway, it doesn't work if I resize my image manually in CSS with max-width: 50%. In that case, is the paragraph/heading below to dictate div size.

Collapse
 
afif profile image
Temani Afif

you should not apply max-width:50% to the image. This doesn't make sense because the 50% will be the image size since it's inside a inline-block container. the max-width:50% should be applied to the parent element instead

Collapse
 
sayandcode profile image
sayandcode

A solution like no other