Creating a Modal Popup Window with HTML, CSS, and JavaScript

Understanding the "Build" Setting and Element Properties

How to Build a Modal Popup Window in HTML, CSS, and JS

Understanding the "Build" Setting Building your Custom Modal Popup Window from Scratch

The "build" setting, as a modal application setting, is used to change the way HTML structure is created. If the option is enabled - the application structure is created using the JS document.createElement() method. Changing the value to "false" (disabling the option) changes the way the modal is constructed. Instead of creating new elements - the application searches for existing ones based on the settings, specifically based on the values of all properties with the "element" prefix, which include:

  • elementContainer - the parent element of the application.
  • elementMain - the element that stores the content of the modal.
  • elementContent - the element that stores the content of the modal.
  • elementTimer - the element responsible for displaying the animation responsible for automatically closing the application.
  • elementClose - the element used to close the application.
  • elementPrev - the element used to change the slide to the next one.
  • elementNext - the element used to change the slide to the previous one.

Not all the elements listed are mandatory. The application only requires one element to work correctly in mode other than "build": elementContainer. Each of the elements should be on the page and belong to the structure of the main application element, that is elementContainer. The application mode with the "build" option turned off is perfect for creating non-fullscreen modals. Below we can check an example of such a solution:

<div class="modal-demo-content modal-demo-container">
  <button class="modal-box-open modal-demo-button">Click to activate the box</button>

  <aside class="modal-box">
    <div class="modal-box-content content">
      Box content visible after clicking the button. <a class="modal-box-close">Click</a> to close the window.
    </div>
  </aside>
</div>
.compsoul-modal-container {
  background: #000000BF;
  bottom: 0;
  left: 0;
  opacity: 0;
  pointer-events: none;
  position: fixed;
  right: 0;
  top: 0;
  transition: opacity 0.4s;
  will-change: opacity;
  z-index: 6;
}

.compsoul-modal-container.modal-active {
  opacity: 1;
  pointer-events: auto;
}

.compsoul-modal-container.modal-close {
  pointer-events: auto;
}

.modal-unset, .modal-unset:before, .modal-unset:after, .compsoul-modal-container.modal-unset, .compsoul-modal-main.modal-unset {
  animation: unset !important;
  transition: none !important;
}

.compsoul-modal-container:before {
  animation: compsoul-modal-loading 1s infinite;
  border-bottom: 0.5em solid #ffffff00;
  border-left: 0.5em solid #ffffff;
  border-right: 0.5em solid #ffffff;
  border-top: 0.5em solid #ffffff00;
  border-radius: 100%;
  box-sizing: content-box;
  content: "";
  font-size: 4px;
  height: 6em;
  left: 50%;
  opacity: 1;
  position: absolute;
  top: 50%;
  transform: translate3d(-50%, -50%, 0);
  transition: opacity 0.4s;
  will-change: opacity;
  width: 6em;
}

.compsoul-modal-container.modal-ready:before, .compsoul-modal-container.modal-error:before {
  animation-play-state: paused;
  opacity: 0;
}

@keyframes compsoul-modal-loading {
  from {
    transform: translate3d(-50%, -50%, 0) rotate(0deg);
  }

  to {
    transform: translate3d(-50%, -50%, 0) rotate(360deg);
  }
}

.compsoul-modal-container:after {
  color: #ffffff;
  content: "\26A0";
  font-size: 42px;
  font-weight: 200;
  left: 50%;
  margin: -6px 0 0 0;
  opacity: 0;
  position: absolute;
  top: 50%;
  transform: translate3d(-50%, -50%, 0);
  transition: opacity 0.4s;
  will-change: opacity;
}

.compsoul-modal-container.modal-error:after {
  opacity: 1;
}

.compsoul-modal-main {
  left: 50%;
  max-height: calc(2 * 40vh);
  opacity: 0;
  position: absolute;
  top: 50%;
  transform: translate3d(-50%, calc(-50% - 100px), 0);
  transition: transform 0.4s 0.4s, opacity 0.4s 0.4s;
  width: 800px;
  z-index: 1;
  will-change: transform, opacity;
}

.modal-ready.modal-active .compsoul-modal-main {
  opacity: 1;
  transform: translate3d(-50%, -50%, 0);
}

.modal-change .compsoul-modal-main {
  transition: transform 0.4s, opacity 0.4s;
}

.compsoul-modal-main:before {
  background: #fff;
  border-radius: 8px;
  bottom: -32px;
  box-shadow: 0 5px 26px 0 rgba(0, 0, 0, 0.22), 0 20px 28px 0 rgba(0, 0, 0, 0.30);
  content: "";
  left: -32px;
  position: absolute;
  right: -32px;
  top: -32px;
  z-index: -1;
}

.compsoul-modal-content {
  background: #fff;
  line-height: 1.2;
  overflow-y: auto;
  max-height: calc(2 * 40vh);
  padding: 0 32px 0 0;
  position: relative;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

.compsoul-modal-content:after {
  content: "";
  display: table;
  clear: both;
}

.compsoul-modal-close {
  right: 8em;
  position: absolute;
  top: 8em;
  z-index: 2;
}

.compsoul-modal-next {
  right: 8em;
  position: absolute;
  top: 50%;
  transform: translate3d(0, -50%, 0);
  z-index: 2;
}

.compsoul-modal-prev {
  left: 8em;
  position: absolute;
  top: 50%;
  transform: translate3d(0, -50%, 0);
  z-index: 2;
}

.compsoul-modal-close, .compsoul-modal-next, .compsoul-modal-prev {
  background: #000000;
  border: none;
  cursor: default;
  font-size: 2.6px;
  height: 16em;
  opacity: 0;
  outline: 1px solid #e7a14f00;
  padding: 0;
  text-align: center;
  transition: opacity 0.4s, outline 0.4s;
  width: 16em;
}

.compsoul-modal-close:focus, .compsoul-modal-close:focus-within, .compsoul-modal-next:focus, .compsoul-modal-next:focus-within, .compsoul-modal-prev:focus, .compsoul-modal-prev:focus-within {
  outline: 1px solid #e7a14fff;
}

.compsoul-modal-close, .compsoul-modal-next.modal-active, .compsoul-modal-prev.modal-active {
  cursor: pointer;
  opacity: 1;
}

.compsoul-modal-close:before, .compsoul-modal-close:after, .compsoul-modal-next:before, .compsoul-modal-prev:before {
  border-top: 1em solid #ffffff;
  border-right: 1em solid #ffffff;
  box-sizing: content-box;
  content: "";
  cursor: pointer;
  display: inline-block;
  height: 4em;
  padding: 0 0 1em 1em;
  transform: rotate(45deg) translate3d(-25%, 25%, 0);
  transition: opacity 0.4s, border 0.4s;
  width: 4em;
}

.compsoul-modal-close:before, .compsoul-modal-close:after {
  height: 3em;
  width: 3em;
}

.compsoul-modal-close:hover:before, .compsoul-modal-close:hover:after, .compsoul-modal-next:hover:before, .compsoul-modal-prev:hover:before {
  border-top: 1em solid #e7a14f;
  border-right: 1em solid #e7a14f;
}

.compsoul-modal-close:after, .compsoul-modal-prev:before {
  transform: rotate(-135deg) translate3d(-25%, 25%, 0);
}

.compsoul-modal-close:before {
  transform: rotate(45deg) translate3d(-7%, 7%, 0);
}

.compsoul-modal-close:after {
  transform: rotate(-135deg) translate3d(-7%, 7%, 0);
}

.compsoul-modal-timer {
  height: 3px;
  left: 0;
  position: absolute;
  top: 0;
  z-index: 5;
  width: 100%;
}

.compsoul-modal-timer:before {
  animation: compsoul-slide-timeline 8s linear forwards;
  animation-play-state: paused;
  background: #e7a14f;
  content: "";
  display: block;
  height: 100%;
  transform: translate3d(-100%, 0, 0);
  width: 100%;
}

.modal-ready .compsoul-modal-timer:before {
  animation-play-state: running;
}

.compsoul-modal-container:hover .compsoul-modal-timer:before {
  animation-play-state: paused;
}

@keyframes compsoul-slide-timeline {
  from {
    transform: translate3d(-100%, 0, 0);
  }

  to {
    transform: translate3d(0, 0, 0);
  }
}

@media only screen and (max-width: 1060px) {
  .compsoul-modal-main {
    width: calc(100% - 94px);
  }

  .compsoul-modal-main:before {
    bottom: -12px;
    left: -12px;
    right: -12px;
    top: -12px;
  }

  .compsoul-modal-close, .compsoul-modal-next, .compsoul-modal-prev {
    font-size: 2px;
  }

  .compsoul-modal-close {
    right: 0;
    top: 0;
  }

  .compsoul-modal-next {
    right: 0;
  }

  .compsoul-modal-prev {
    left: 0;
  }
}

.modal-box {
  background: #fff;
  border-radius: 5px;
  box-shadow: 0 0 32px 0 rgba(0, 0, 0, 0.2);
  box-sizing: border-box;
  display: block;
  font-family: Calibri, Candara, Segoe, Segoe UI, Optima, Arial, sans-serif;
  height: 0;
  margin: 32px auto;
  overflow: hidden;
  transition: height 0.4s;
  width: 264px;
}

.modal-box.modal-active {
  height: 180px;
}

.modal-box-content {
  padding: 24px 32px;
}

.modal-box-open {
  margin: 21px auto;
}
<script src="https://compsoul.dev/uploads/js/compsoul.js"></script><script src="https://compsoul.dev/uploads/js/modal.js"></script><script>
  new Modal(".modal-box").options({
    elementContainer: ".modal-box",
    elementClose: ".modal-box-close",

    open: ".modal-box-open",

    build: false,
    overflow: false,
    popup: false
  }).init();
</script>

The proper setting of the application has caused the code added above to be downloaded and assigned to the modal elements. After clicking on the button that launches the modal, an animated window is activated, which is not displayed in full-screen mode. Let's look at the settings: non-full-screen mode of the application is possible due to the build option being turned off, responsible for creating the HTML structure from the JS level, although turning off this option is not required. In this case, it was only used as an example of application. The next two options, overflow and popup, must be turned off for the modal to work correctly in non-full-screen mode. The reason for deactivating the mentioned settings is the possibility of multiple modals appearing at the same time, which is not possible in the case of full-screen instances.

Analyzing the above instance, we can notice the properties of elementContainer and elementClose, whose values indicate HTML elements created in the HTML structure of the page. The last option in our sample instance is open, the setting used to launch the modal. I encourage you to experiment with different settings and share the results in the comments.

Thank You for Reading

We hope you enjoyed this post! If you did, please consider following us on Facebook and leaving a like and a comment. If you have any questions or need assistance, feel free to use our contact form or email us at daniel@compsoul.dev. For urgent inquiries, you can reach us by phone at +48 732 846 416.