How to create a custom resizable modal with scrollable and fixed content

Modal windows (aka modals) are everywhere in websites and web applications. They are the basic concept behind the so called pop-ups.

Modals are quite easy to develop and implement, but they come with an annoying problem: vertical resizing.

Use case

How the modal should be

Let’s suppose that you want to develop a simple modal that has 2 types of content:

  • fixed content (e.g. a title and a close button)
  • scrollable content (e.g. a long text)

In addition, the modal has to be vertically resizable.

As stated in this interesting article, the task is not so easy as you could initially think.

Basic structure

Every modal generally has a basic HTML structure like the following:

As you can see, main-container is the basically the page content and then we have two divs:

  • modal-overlay is an optional div that is used to add a kind of background layer between the page content and the modal;
  • modal-container is the div used for displaying the modal.
Basic structure for developing a modal

So, a specific event (e.g. user clicks on a button or user stays in the page for more than 15 secs) will add to the modal-overlay and to the modal-container a CSS class with properties that show the two divs.

The Overlay

As said before, modal-overlay is optional because maybe you don’t want to add an extra layer between main-content and modal-container.

Supposing that you want to add a semi-transparent background when a not-full-screen modal is opened, generally using a modal-overlay is a good idea.

Here modal-overlay is the semi-transparent black background that is ‘above’ the main-content of the page

To have that kind of modal-overlay, you could use some CSS properties similar to the following ones:

The modal-overlay by default has display property set to none. The value will change to block when a specific event occurs (e.g. when you want to open the modal) and the modal-overlay-visible class is added to the modal.

The Modal

Implementing a basic modal is not so difficult:

And the result is ok.

But what happens:

  • if the content exceeds the height of the modal and/or
  • if the browser window is resized?

Yes, right guess! Something awful…

When screen is resized and/or the modal content exceeds the height we have a bad behaviour

Luckily CSS has a good property called overflow-y that you can set to auto to prevent the previous behaviour.

Good, we are making some progress!

Overflow-y property applied to the modal

The modal is starting to look nice, but you’ll notice two things:

  1. all the modal content is scrollable, the close button too…
  2. you have the default scrollbar (that changes according to different OS)
Mmm, not so fancy
Default scrollbar generally sucks… And in this case it is hiding the modal rounded corner

The Solution

Considering that you want a fixed content for the title and the close button, you’ll need to create a substructure inside your modal-container.

Now modal-container-content will have 2 internal divs:

  • modal-container-content-no-scroll - the div dedicated for fixed content;
  • modal-container-content-scroll - the div dedicated for scrollable content.

Then, add the right CSS properties (and yes, also let’s add some styling for the close button):

Nice! ✨ Almost there…

Definitely better!

One last retouch about the vertical scrollbar… I bet you don’t like default things. So, let’s give your new modal a completely different and fancy scrollbar:

Et voilà! 🎉

Congratulations! You are the Michelangelo of modals

You can find all the code here in my repo. And here you can find a React example.

Obviously the general CSS style is not optimized, but my intent here is to help you not lose much time in finding the right HTML-CSS combination for having a good Y-axis resizable modal, without setting width and height in px.

🙏 Thank you for reading!

🔎 You can follow me on GitHub, Twitter and LinkedIn.

Web & Product Developer ~ R&D lover ~ Startup enthusiast