手把手教你手撸一个模态框

123 阅读5分钟

前言

大家在平时开发中都用过类似Modal这样的组件吧,这次带大家来手撸一个类似效果的模态框,纯JS实现,效果百分之九十复刻。话不多说,咱们直接进入主题。

效果预览

效果如下所示。

HTML部分

首先我们看到HTML部分,这里实现了一个简单的对话框功能。相关代码如下。

  <a href="#" class="open" onclick="openTest(1);return false;">打开</a>
    <div class="shadow" id="model" onclick="closeTest(1);">
      <div class="model" onclick="event.stopPropagation();">
        <nav>
          <span>对话框标题</span>
          <a href="#" class="close" onclick="closeTest(1);return false;">X</a>
        </nav>
        <section>对话框的内容</section>
        <footer>
          <div class="buttons">
            <a href="#" class="button ok">确定</a>
            <a href="#" class="button" onclick="closeTest(1);return false;"
              >取消</a
            >
          </div>
        </footer>
      </div>

<a href="#" class="open" onclick="openTest(1);return false;">打开</a>当点击时,会调用openTest函数来打开对话框,并且通过return false来阻止默认的链接行为。

<div class="shadow" id="model" onclick="closeTest(1);">这个div元素通过CSS的样式创建了一个半透明的遮罩层,用于遮盖页面内容以实现模态对话框的效果。当这个遮罩层被点击时,会调closeTest函数来关闭对话框。

<div class="model" onclick="event.stopPropagation();">使用event.stopPropagation()函数用于阻止事件冒泡,这样点击对话框内容区域时不会触发遮罩层上的关闭事件。

<a href="#" class="close" onclick="closeTest(1);return false;">X</a>在对话框的标题栏中,这是用于关闭对话框的链接。点击时会调用closeTest函数来关闭对话框,并通过return false来阻止默认的链接行为。

综上所述,这里实现一个简单的打开对话框、关闭对话框的效果。

JS部分

接着我们看到JS部分,通过操作元素的样式和添加动画来实现动态效果。相关代码如下。

    <script>
      function openTest(time) {
        document.getElementById("model").style.display = "block";
        document.getElementsByClassName(
          "model"
        )[0].style = `animation: show ${time}s linear`;
      }
      function closeTest(time) {
        document.getElementsByClassName(
          "model"
        )[0].style = `animation: hide ${time}s linear`;
        setTimeout(function () {
          document.getElementById("model").style.display = "none";
        }, time * 1000);
      }
    </script>
  1. function openTest(time):

    • 当调用openTest函数时,它首先通过document.getElementById("model").style.display = "block";id 为 "model" 的元素显示出来。
    • 紧接着它通过 document.getElementsByClassName("model")[0].style = animation: show ${time}s linear; 给类名为 "model" 的第一个元素添加一个显示动画,持续时间为 time 秒。
  2. function closeTest(time):

    • 当调用 closeTest 函数时,它首先通过 document.getElementsByClassName("model")[0].style = animation: hide ${time}s linear; 给类名为 "model" 的第一个元素添加一个隐藏动画,持续时间为 time 秒。
    • 然后它使用 setTimeout 函数在动画执行完成后(time * 1000 毫秒后)将 id 为 "model" 的元素隐藏。

这里实现了一个简单的模态对话框的打开和关闭功能,通过修改元素的 display 属性来控制元素的可见性,并通过设置动画来实现渐入渐出的效果

CSS部分

最后我们看到CSS部分。这里定义了一些样式,用于创建一个模态对话框的外观和动画效果。相关代码如下。

 * {
        margin: 0;
        padding: 0;
      }

这个规则确保了文档中的所有元素都没有默认的外边距和内边距。

  nav {
        background: #29abf5;
        padding: 10px;
        color: #fff;
        border-top-left-radius: 5px;
        border-top-right-radius: 5px;
      }

这里定义了对话框标题栏的样式,包括背景颜色、内边距和文字颜色等。

  .close {
        float: right;
        text-decoration: none;
        color: #fff;
      }

这里定义了关闭按钮的样式,包括浮动到右侧、无下划线、颜色等。

      section {
        height: 100px;
        padding: 10px;
      }

定义了对话框内容区域的样式,包括高度和内边距。

 footer {
        position: absolute;
        width: 100%;
        padding: 20px 0;
        bottom: 0px;
        background: #f9f9f9;
      }

这里定义了页脚区域的样式,包括绝对定位、宽度、内边距、下边距、背景色等。

 .buttons {
        width: 150px;
        margin: 0 auto;
      }

这里定义了按钮区域的样式,包括宽度和居中排列。

 .shadow {
        position: fixed;
        display: block;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        background: rgba(0, 0, 0, 0.2);
      }

这里定义了遮罩层的样式,包括固定定位、全屏宽高、半透明背景。

  .model {
        position: absolute;
        width: 600px;
        height: 200px;
        background: #fff;
        top: 50%;
        left: 50%;
        margin-top: -100px;
        margin-left: -300px;
        border-radius: 5px;
        border: solid 1px #ccc;
      }

这里定义了对话框主体的样式,包括绝对定位、宽高、背景、居中显示、圆角边框等。

    .button {
        display: inline-block;
        width: 70px;
        height: 30px;
        background: #fff;
        color: #ccc;
        text-align: center;
        text-decoration: none;
        line-height: 30px;
        border-radius: 5px;
        border: solid 1px #ccc;
      }

这里定义了按钮的公共样式,包括宽高、背景色、文字颜色、文本居中、圆角边框、边框等。

  .ok {
        background: #29abf5;
        color: #fff;
        border: none;
      }

这里定义了确定按钮的特殊样式,覆盖了一般按钮的背景色和文字颜色。

这些样式的集合通过 classid 绘制出一个包含标题、内容以及按钮的模态对话框,并且定义了对话框打开和关闭时相应的动画效果。

我们来看到showhide这两个动画,它们被用于模态对话框的显示和隐藏。相关代码如下。

 @keyframes show {
        0% {
          top: 0;
        }
        100% {
          top: 50%;
        }
      }
      @keyframes hide {
        0% {
          top: 50%;
        }
        100% {
          top: 0;
        }
      }

@keyframes show { ... }:

  • 这段动画规则定义了一个名为 show 的动画。在这个动画中,元素从初始状态(0%)开始,top 属性值为 0,逐渐过渡到结束状态(100%),top 属性值为 50%。这表示元素在垂直方向上从顶部向中间的移动,实现了模态对话框打开时的渐入效果。

@keyframes hide { ... }:

  • 这段动画规则定义了一个名为 hide 的动画。在这个动画中,元素从初始状态(0%)开始,top 属性值为 50%,逐渐过渡到结束状态(100%),top 属性值为 0。这表示元素在垂直方向上从中间向上方的移动,实现了模态对话框关闭时的渐出效果。

在这两个动画中,使用了top属性来控制元素在垂直方向上的位移,从而实现了模态对话框打开和关闭时的渐入渐出效果。

总结

以上就是整个效果的实现过程了,CSS结合 JS 实现,代码简单易懂。另外,感兴趣的小伙伴们还可以在现有基础上发散思维,比如增加点其他效果,或者更改颜色等等。关于该效果如果大家有更好的想法欢迎在评论区分享,互相学习。最后,完整代码在码上掘金里可以查看,如果有什么问题大家在评论区里讨论~