DEV Community

Cover image for Build a Responsive Modal using CSS πŸš€
Aniket
Aniket

Posted on

Build a Responsive Modal using CSS πŸš€

πŸ‘‹ Hello, Dear developers πŸ‘©β€πŸ’»
Today we will be lookup on how to build a responsive modal using CSS, so stay tunnedπŸ”₯

Introduction

Modal Popups are used very often in modern websites or Apps, to display notifications or alerts, handle user's sign up or login forms, newsletters & much more ✨


I created this tutorial, on how to create a responsive modal popup box with a clean design, with the help of HTML as markup, CSS for styling and vanilla javascript for adding functionality πŸ§ πŸš€


Here's how it will look once we are finished in the below GIF⬇️

Final Output


But Before that, You can view the code tutorial of the finished product before continuing this blog ⬇️

Code Tutorial


You can also view a live demo πŸ“Ί of it as well.


Now Let's start on building this from scratch !

HTML Markup ⬇️

Let's start with html markup for the modal

<div class="container">
    <button class="share__modal_btn">share</button>

    <main class="share__modal">
        <div class="share__modal_content">
            <div class="share__modal__header">
                <span>share</span>
                <button class="close_modal_btn">
                    <i class="bx bx-x bx-sm"></i>
                </button>
            </div>
            <div class="share__modal__options">
                <ul class="list">
                    <li class="list__item">
                        <div class="icon_holder" data-icon="twitter">
                            <img
                                class="social__logo"
                                src="./img/twitter-logo.png"
                                alt="twitter-logo"
                            />
                        </div>
                        <span>twitter</span>
                    </li>

                    <li class="list__item">
                        <div class="icon_holder" data-icon="facebook">
                            <img
                                class="social__logo"
                                src="./img/facebook-logo.png"
                                alt="facebook-logo"
                            />
                        </div>
                        <span>facebook</span>
                    </li>

                    <li class="list__item">
                        <div class="icon_holder" data-icon="reddit">
                            <img
                                class="social__logo"
                                src="./img/reddit-logo.png"
                                alt="reddit-logo"
                            />
                        </div>
                        <span>reddit</span>
                    </li>

                    <li class="list__item">
                        <div class="icon_holder" data-icon="discord">
                            <img
                                class="social__logo"
                                src="./img/discord-logo.png"
                                alt="discord-logo"
                            />
                        </div>
                        <span>discord</span>
                    </li>

                    <li class="list__item">
                        <div class="icon_holder" data-icon="whatsapp">
                            <img
                                class="social__logo"
                                src="./img/whatsapp-logo.png"
                                alt="whatsapp-logo"
                            />
                        </div>
                        <span>whatsapp</span>
                    </li>

                    <li class="list__item">
                        <div class="icon_holder" data-icon="messenger">
                            <img
                                class="social__logo"
                                src="./img/messenger-logo.png"
                                alt="messenger-logo"
                            />
                        </div>
                        <span>messenger</span>
                    </li>

                    <li class="list__item">
                        <div class="icon_holder" data-icon="telegram">
                            <img
                                class="social__logo"
                                src="./img/telegram-logo.png"
                                alt="telegram-logo"
                            />
                        </div>
                        <span>telegram</span>
                    </li>

                    <li class="list__item">
                        <div class="icon_holder" data-icon="wechat">
                            <img
                                class="social__logo"
                                src="./img/wechat-logo.png"
                                alt="wechat-logo"
                            />
                        </div>
                        <span>wechat</span>
                    </li>
                </ul>
            </div>

            <div class="share__modal_link">
                <span>page link</span>
                <div class="share__modal_input">
                    <input
                        type="text"
                        placeholder="https://www.sharethispage.io"
                    />
                    <i class="bx bx-copy copy_icon"></i>
                </div>
            </div>
        </div>
    </main>
</div>

Enter fullscreen mode Exit fullscreen mode

So here, we have a few components added to our markup.

First, we have a simple open modal button which is named a share button, when clicked on, it triggers the function of opening the modal, then we have the close modal button which performs the opposite operation/function to the open button to close modal, then we have few social sharing option's and at last, we have the input box with just fake placeholder value in it.


for images, please follow my GitHub repository inorder to use them.


CSS Styles 🎨

Let's add the styles stepwise to understand what we're doing,

First of all, we will look at making some basic changes in our CSS file which includes resets of the root, HTML & variables.

@import url("https://fonts.googleapis.com/css2?family=Inter:wght@200;300;400;600&display=swap");
*,
*::before,
*::after {
  box-sizing: border-box;
}
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  font-family: "Inter", sans-serif;
}

:root {
  /*========== Colors ==========*/

  --first-color: #373d46;
  --modal-bg-color: #fff;
  --text-input-bg: #f8f9fa;
  --text-color: #95989d;
  --container-bg: #c7ad91;
  --btn-color: #ddc0a1;

  /* ===== SOCIAL ICONS BACKGROUND COLOR =====  */
  --twitter: #e8f6fe;
  --whatsapp: #e9fbf0;
  --facebook: #e8f1fe;
  --reddit: #ffece6;
  --discord: #f1f3fb;
  --messenger: #e6f3ff;
  --telegram: #e6f3fa;
  --wechat: #f2f7ea;

  /*========== Font and typography ==========*/

  --normal-font-size: 0.88rem;
  --large-font-size: 1.25rem;
  --share-link-span: 0.9869em;
  --share-input-font-size: 0.8em;

  /*========== z index ==========*/
  --z-modal: 1000;
}

@media screen and (min-width: 991px) {
  :root {
    --large-font-size: 1.5rem;
    --normal-font-size: 1rem;
    --share-link-span: 1.1em;
    --share-input-font-size: 1em;
  }
}

/*=============== BASE ===============*/
body{
  font-weight: 500;
  background-color: var(--btn-color);
}
button{
  background-color: transparent;
  outline: none;
  border: none;
  cursor: pointer;
  font-family: inherit;
}

img{
  max-width: 100%;
  height: auto;
}
ul li {
  margin: 0;
  padding: 0;
  list-style-type: none;
}
.container{
  height: 100vh;
  display: grid;
  place-items: center;
  background-color: var(--container-bg);
}
Enter fullscreen mode Exit fullscreen mode

Okay Nice ! we are moving further πŸƒβ€β™€οΈπŸƒβ€β™‚οΈ

So after adding those base styles, we look up our markup and use the classes that we have given to each component (tag) in order to add them styles individually.

1. Share modal button


.share__modal_btn {
  background-color: #857361;
  padding: 0.9em 1.5em;
  font-size: var(--share-link-span);
  text-transform: capitalize;
  border-radius: 0.7em;
  box-shadow: 0 10px 10px -2px rgba(0, 0, 0, 0.1);
  color: #eee;
  letter-spacing: 0.25px;
}
.share__modal_btn:hover {
  background-color: #6f6051;
}

Enter fullscreen mode Exit fullscreen mode

The styles for the share modal button are background color, font size along with visual goodies like padding, border-radius & pseudo hover class on background color.

Result ⬇️

share-modal-button


2. Share modal

The share modal is the most important, where all of the content is situated

we added an absolute position on it at the bottom with a 0% percentage value along the visual goodies like box shadow, border radius, opacity, and extra white space by using padding and transition property as well.


.share__modal {
  background-color: var(--modal-bg-color);
  position: absolute;
  bottom: 0;
  width: 100%;
  height: 50%;
  display: grid;
  align-items: flex-end;
  overflow: auto;
  box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.2);

  border-radius: 1.3em 1em 0 0;
  z-index: var(--z-modal);
  opacity: 0;
  transition: 0.5s ease;
  visibility: hidden;
}

.share__modal_content {
  padding: 1.5em;
  display: flex;
  flex-direction: column;
  row-gap: 2.6em;
}

.share__modal__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.share__modal__header span {
  font-size: var(--large-font-size);
  font-weight: 600;
  color: var(--first-clr);
  text-transform: capitalize;
  opacity: 0.88;
}
.close_modal_btn {
  color: var(--first-clr);
}

Enter fullscreen mode Exit fullscreen mode

Result ⬇️

Open State


3. Social sharing options

These options are structured with the help of CSS Grid, for the background color of social sharing options, we used the data-icon attribute property on each tag in html file & added light color as a background to add contrast against the actual logo.


.list {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-gap: 1.125em;
}

.list__item {
  display: flex;
  flex-direction: column;
  row-gap: 0.5em;
  align-items: center;
  justify-content: center;
  text-transform: capitalize;
  color: var(--first-clr);
  font-size: var(--normal-font-size);
  font-weight: 500;
  opacity: 0.9;
  cursor: pointer;
}
.icon_holder {
  width: 4.5em;
  height: 4.5em;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
}
.social__logo {
  width: 2em;
  height: 2em;
}

[data-icon="twitter"] {
  background-color: var(--twitter);
}
[data-icon="facebook"] {
  background-color: var(--facebook);
}
[data-icon="reddit"] {
  background-color: var(--reddit);
}
[data-icon="discord"] {
  background-color: var(--discord);
}
[data-icon="whatsapp"] {
  background-color: var(--whatsapp);
}
[data-icon="messenger"] {
  background-color: var(--messenger);
}
[data-icon="telegram"] {
  background-color: var(--telegram);
}
[data-icon="wechat"] {
  background-color: var(--wechat);

Enter fullscreen mode Exit fullscreen mode

4. Share link input

we use the input with the fake placeholder value to share the link of the current page, the style for these is pretty generic & straight forward.


.share__modal_link {
  display: flex;
  flex-direction: column;
  row-gap: 1.1em;
}
.share__modal_link span {
  font-weight: 500;
  font-size: var(--share-link-span);
  text-transform: capitalize;
  color: var(--first-clr);
}
.share__modal_input {
  position: relative;
}
.share__modal_input input {
  width: 100%;
  background-color: var(--text-input-bg);
  padding: 0.88em;
  border-radius: 0.5em;
  border: none;
  outline: none;
  font-size: var(--share-input-font-size);
}
.copy_icon {
  position: absolute;
  right: 1.5em;
  top: 1em;
  color: var(--first-clr);
  cursor: pointer;
}

Enter fullscreen mode Exit fullscreen mode

5. Show modal

Before moving to the final, here is the class that handles the styles when the modal is opened.


.show-modal {
  opacity: 1;
  visibility: visible;
}

Enter fullscreen mode Exit fullscreen mode

6. Media queries to make it responsive πŸ“±

Finally, we want to make it responsive or at least look good on both mobile and desktop, so below are the few breakpoints on the share modal button, modal, modal content, and list.

@media screen and (min-width: 768px) {
  .share__modal_btn {
    padding: 0.9em 1.75em;
    font-size: var(--share-link-span);
  }
  .share__modal {
    width: 28em;
    height: 30em;
    border-radius: 1.3em;
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    overflow: hidden;
  }
  .share__modal_content {
    padding: 2.5em;
  }
  .list {
    grid-template-columns: repeat(4, 1fr);
    row-gap: 1.5em;
    column-gap: 1em;
  }
}

Enter fullscreen mode Exit fullscreen mode

Desktop View

Desktop-view

Mobile View

mobile-view


😀 Finally, To make our modal popup box intractive or actually work, we will be using few lines of javascript logic 🧠

Javascript code ⬇️


/*=============== SHOW MODAL ===============*/

const openBtn = document.querySelector(".share__modal_btn");
const modalContainer = document.querySelector(".share__modal");

if (openBtn && modalContainer) {
  openBtn.addEventListener("click", () => {
    modalContainer.classList.add("show-modal");
  });
}

/*=============== CLOSE MODAL ===============*/

const closeBtn = document.querySelector(".close_modal_btn");

function closeModal() {
  const modalContainer = document.querySelector(".share__modal");
  modalContainer.classList.remove("show-modal");
}
closeBtn.addEventListener("click", closeModal);

/*====== ESC BUTTON TO CLOSE MODAL ======*/

document.addEventListener("keydown", (event) => {
  if (event.key === "Escape") {
    closeModal();
  }
});

Enter fullscreen mode Exit fullscreen mode

So here we have three event listeners who are adding or removing the show-modal class from the modalContainer :

  1. When OpenBtn is clicked, we want to add a show-modal class to modalContainer in order to show the modal to users.

  2. When closeBtn is clicked, we perform the opposite operation to open the button that is to remove the show-modal class & hide the modal.

  3. Escape key-down event listener on dom to hide the modal by simply calling the closeModal() function.


So, the end result will finally look like this ⬇️

Reupload-final-output

and that's what we wanted πŸ₯³πŸ€˜

I hope you find this post to be helpful and thanks for reading it πŸ˜‡

Conclusion
As always, I hope you found it interesting. If you noticed any
errors in this article, please mention them in the comments. πŸ§‘πŸ»β€πŸ’»

Hope you have a great day! ✌️

Thumbs meme

Top comments (2)

Collapse
 
gabrielmlinassi profile image
Gabriel Linassi • Edited

Although this is a good task to challenge yourself, I don't recommend you do this in business projects. Building a modal requires much attention, like locking the screen, close on clicking outside, beying responsive to keyboard events, having the correct aria, dynamic loading modal content, render it in a higher place in the DOM, etc.

Collapse
 
ananiket profile image
Aniket

Thank You & Yeah sure, I will definitely try to make it to the business level by considering the above suggestions. Thanks for reading this blog πŸ₯³πŸ€˜