Auto-sizing element to fit inside flexbox
Tags: webdev, html, css
Published: 2021-03-13 18:23:23

# 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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/aavolpl1awdq56addczj.png)

What we should note here:
1. The image shrinks on the small device so the "GO" button is not "pushed" out of the screen
1. On larger screens the "GO" button is adjacent to the image, and the image takes the entire width available.
1. 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:
```html
<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>
```

our container class, `box`, is a flex column:
```html
<style>
	.box {
		display: flex;
		flex-direction: column;
		width: 100%;
		height: 100%;
		padding: 10px;
		box-sizing: border-box;
	}
</style>
```

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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1z67hx7o1nsqry8iyr9c.png)

# 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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a76t0h7rrubahhpylh76.png)

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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/13fipdjj465c4opayhhn.png)

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>`:
```html
<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>
```
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l5jb0jy5wdatucbaddkw.png)

# The END
The key takeaways, inside flex container:
1. Use `align-self` to prevent from an element to stretch.
1. Use `overflow: auto` to prevent from an element to "push" other elements (assuming of course the element is "allowed" to shrink).