A Responsive Modal With Flexbox and No Media Queries
Tags: html, css, showdev, beginners
Published: 2019-09-27 03:11:11

---
title: A Responsive Modal With Flexbox and No Media Queries
published: true
description: How to write a responsive modal using html and css (no bahavior added) using flexbox and no media queries
tags: #html #css #showdev #beginners
---

No bla bla bla, lets get things done. To a better comprehension of this post would be good for you to know something about HTML, SCSS and CSS Vars.

The ideia is to write a responsive modal front end structure using only flexbox and no media queries. A fluid modal. I'll try to highlight the key points of the (S)CSS style, anyway this is the result:

{% codepen https://codepen.io/felipperegazio/pen/LYPvQBe %}

Use this link to see on "full" screen:
https://codepen.io/felipperegazio/full/LYPvQBe

There is no behavior added on this modal, its Style Only. Do as you prefer or feel free to ask me in the comments how to add JS functions to open, close, callbacks etc.

So, lets start with the modal HTML. We gonna need a wrapper (which will also be our backdrop), and a content div to hold the header, main content and footer. Because we are using flexbox, this modal will be also dynamic, you could omit the header or the footer without break anything.

```html
<div class="container">
  <div class="simple-modal" tabindex="0">
		<div class="simple-modal__content">
			<header>
				<h4>Title</h4>
				<span>close</span>
			</header>
			<div class="modal-main">
                          <!-- Content goes here -->
			</div>
			<footer>
        <button>Ok</button>
			</footer>
		</div>
	</div>
</div>
```

Really simple, huhn? There is no much to say about it. The container could be anything in the page, its for eye candy purposes only (we'll add a background on it).

The modal starts in the `.simple-modal` div. This will be our wrapper and backdrop. This is also where you apply the visibility and display rules to show or hide the modal when adding behavior.

Then we add the `.simple-modal__content` div, which will be the content of our modal, containing the header, main-content and footer. 

So, lets start defining some CSS vars that we may need:

```scss
.simple-modal {
  --gutter: 14px; // spacing reference
  --modal-color: #800000; // just color
  --soft-color: #fafafa; // just another color
}
```

Then lets do our wrapper/backdrop:

```scss
.simple-modal {
  --gutter: 14px;
  --modal-color: #800000;
  --soft-color: #fafafa;
  top: 0;
  left: 0;
  width: 100vw;
  height: 100vh;
  z-index: 2000;
  position: fixed;
  background-color: rgba(0,0,0,.7);
  padding-top: 2%;
}
```

Key points: the `.simple-modal` div will be fixed on the screen, so will be where the modal content will be placed. The `z-index` will keep the modal always on front of the other page elements. The padding-top can be modified, but i think 2 or 3 percent scales really well from desk to mobo, this padding will determine how distant from the page top the modal content will be.

Now, lets add the content element, a blank square on the middle.
To do it we gonna use the `.simple-modal__content` div:

```scss
.simple-modal {
  /* ... previous stuff ... */
  &__content {
    width: 95vw;
    max-width: 600px;
    height: 90vh;
    max-height: 700px;
    position: relative;
    overflow: hidden;
    border-radius: 4px;
    margin: 0 auto;
    background-color: #ffffff;
    display: flex;
    flex-direction: column;
  }
}
```

Key points: We start given the modal a `width: 95vw` and `max-width: 600px`. So, we get a decent content width on desktop which also fits well on mobile, cuz on < 600px screens, the width will be 95vh, or 95% of the viewport, given 5% of space to emulate the padding. The height and max-height here will do the same thing with the height.

Then at last not least, the `display: flex` will give a fluid behavior for our modal content elements. But flex is horizontal driven by default, so we use `flex-direction: column` to change it to vertical. Now, things will be vertically stretched on our modal content. Dont forget the `margin:0 auto` to centralize and `overflow:hidden` to prevent unwanted scroll bars.

Its time to add the modal elements:
Header, Main Content and Footer

```scss
   header {
      min-height: 60px;
      height: 60px;
      color: #ffffff;
      background-color: var(--modal-color);
      display: grid;
      padding-left: var(--gutter);
      align-items: center;
      grid-template-columns: auto 60px;
      h4 {
        margin: 0;
        text-align: left;
      }
      span {
        display: flex;
        align-items: center;
        justify-content: center;
        height: 100%;
        width: 100%;
        font-size: 20px;
        opacity: .8;
        cursor: pointer;
        &:hover {
          opacity: 1;
        }
      }
    }
    .modal-main {
      flex: 1;
      text-align: left;
      overflow: auto;
      padding: var(--gutter);
    }
    footer {
      height: auto;
      text-align: right;
      border-top: solid 1px #cccccc;
      padding: var(--gutter);
      background-color: #ffffff;
      background-color: var(--soft-color);
      button, input {
        margin: 0;
        &:not(:last-child) {
          margin-right: var(--gutter);
        }
      }
    }
```

If you note, this part of the code its almost pure aesthetics. Almost no style behavior added, except for the `flex:1` on the `.modal-main`.

The flex 1 tells to the `.modal-main` to grow along the parent as much as possible, but it will be stopped by the `&__content` div limits. Then we add the `min-height` on the header. For the footer id prefer to not to given a height and let the children do it for me, then when the footer is empty, it will became just a cool border on the bottom.

## Conclusion

Because our modal content holder is `display:flex` with column direction, all the content will be vertically placed in a way that the main content (flex 1) will grow in a delimited size (&__content height and width) and without break its header, but will grow. Also important to add the `overflow:auto` on your main content `.modal-main`, so you can have large contents inside the `.modal-main`.

The final code must be like this:

```scss
.simple-modal {
  --gutter: 14px;
  --modal-color: #800000;
  --soft-color: #fafafa;
  top: 0;
  left: 0;
  width: 100vw;
  height: 100vh;
  z-index: 2000;
  position: fixed;
  background-color: rgba(0,0,0,.7);
  padding-top: 2%;
  &__content {
    width: 95vw;
    height: 90vh;
    max-height: 700px;
    max-width: 600px;
    position: relative;
    overflow: hidden;
    border-radius: 4px;
    margin: 0 auto;
    background-color: #ffffff;
    display: flex;
    flex-direction: column;
    header {
      min-height: 60px;
      height: 60px;
      color: #ffffff;
      background-color: var(--modal-color);
      display: grid;
      padding-left: var(--gutter);
      align-items: center;
      grid-template-columns: auto 60px;
      h4 {
        margin: 0;
        text-align: left;
      }
      span {
        display: flex;
        align-items: center;
        justify-content: center;
        height: 100%;
        width: 100%;
        font-size: 20px;
        opacity: .8;
        cursor: pointer;
        &:hover {
          opacity: 1;
        }
      }
    }
    .modal-main {
      flex: 1;
      text-align: left;
      overflow: auto;
      padding: var(--gutter);
    }
    footer {
      height: auto;
      text-align: right;
      border-top: solid 1px #cccccc;
      padding: var(--gutter);
      background-color: #ffffff;
      background-color: var(--soft-color);
      button, input {
        margin: 0;
        &:not(:last-child) {
          margin-right: var(--gutter);
        }
      }
    }
  }
}
```

You can use the `.container` div to add a cool background:

```scss
// just an eye candy
.container {
  width: 100vw;
  height: 100vh;
  background-size: cover;
  background-repeat: no-repeat;
  background-image: url(http://picsum.photos/2000);
}
```

Thats all folks :)