DEV Community

loading...

Auto-sizing element to fit inside flexbox

valyouw profile image Yuval Originally published at thecodingnotebook.com ・2 min read

Intro

We have given a task to build a screen, for mobile devices, which is a single column, with a header, text, image and an action button. The "catch" is that all elements must fit into the screen with NO scrolling, where the image is the "responsive" element that should shrink/expand according to available space.

Here is a schema of the design on 2 different screens:
Alt Text

What we should note here:

  1. The image shrinks on the small device so the "GO" button is not "pushed" out of the screen
  2. On larger screens the "GO" button is adjacent to the image, and the image takes the entire width available.
  3. IMPORTANT: We are guaranteed that the text won't be too long (so there will always be some space left for the image) and we should support "portrait only".

Initial Layout

The first implementation direction that comes to mind is using a "flex" column design, this is the html structure:

<div class="box">
    <div class="title">
        This is some long header?
    </div>
    <div class="text">
        Lorem ipsum dolor sit amet...
    </div>
    <img src="https://via.placeholder.com/600x400.png">
    <button>Open</button>
</div>
Enter fullscreen mode Exit fullscreen mode

our container class, box, is a flex column:

<style>
    .box {
        display: flex;
        flex-direction: column;
        width: 100%;
        height: 100%;
        padding: 10px;
        box-sizing: border-box;
    }
</style>
Enter fullscreen mode Exit fullscreen mode

Inside our "column" we have 4 items: title, text, image and button. The title, text and button just render "as-is" taking as much space as needed, where the <img> will have to adjust to the remaining space.

Currently the result looks as follow, "small" device on the left, "large" device on the right:
Alt Text

Sizing inside flex

The first issue that we see is the <button>, which stretches to fill the entire width, this is the default behavior of elements inside a flex container, to fix this we can just apply align-self: center to the <button>, we'll apply this also to the <img>, and voila:
Alt Text

OK, while the <button> is now centered and not stretched anymore, the <img> has lost its bounds... well this can easily be fixed by specifying max-width: 100% on the <img>:
Alt Text

Now we are really close to achieving our goal, we just need to tell the image: "don't push", and the/one way to do it inside a flex container is by setting overflow: auto on the misbehaving element, at this point we'll also set some margin-top to the <button> and <img>:

<style>
    .box img {
        align-self: center;
        max-width: 100%;
        overflow: auto; /* do NOT push others*/
        margin-top: 10px;
    }

    .box button {
        align-self: center;
        margin-top: 30px;
    }
</style>
Enter fullscreen mode Exit fullscreen mode

Alt Text

The END

The key takeaways, inside flex container:

  1. Use align-self to prevent from an element to stretch.
  2. Use overflow: auto to prevent from an element to "push" other elements (assuming of course the element is "allowed" to shrink).

Discussion (2)

pic
Editor guide
Collapse
afif profile image
Temani Afif

It's more logical to use min-height:0 instead of overflow: auto. What you face is due to the default min-height/min-width setting applied by flexbox: w3.org/TR/css-flexbox-1/#min-size-...

overflow:auto will also disable the automatic minimum (w3.org/TR/css-flexbox-1/#change-20...) size but it's more suitable when you want to have a scrollbar.

Collapse
valyouw profile image
Yuval Author

Thanks!