1 前言
在现代前端开发中,弹窗(Modal)是常见的交互组件,广泛应用于表单输入、信息提示和用户确认等场景。尽管框架和库提供了丰富的弹窗功能,但掌握原生 HTML 和 JavaScript 实现弹窗的技术,能帮助开发者深入理解 DOM 操作、事件绑定和样式控制等核心知识。
本篇文章将带您从零开始实现一个功能完善的弹窗组件,涵盖基础布局、交互逻辑以及样式优化,为您的开发技能打下扎实基础。
文章中设计到overlay遮罩层知识点可以参考另一篇文章:html+javascript原生语法实现遮罩层
在原理上,模态框Modal弹窗与这张层是一样的,通过display: none;
属性来控制元素是否显示,而且位置也是固定的,故实现固定样式,然后操作class属性,即可实现需求。
2 侧边弹窗实现
本案例是从左边弹出,如需其他方向弹出,可以通过left、right等参数自定义控制。
2.1 html元素
<aside id="menu_mobile" class="menu_mobile">
<div>
<div style="display: flex;flex-direction: column;justify-content: center;align-items: center">
<div id="phil" style="font-size: 20px"><b>有勇气的牛排</b></div>
<div class="author_desc">
CSDN全栈&网络安全领域优质创作者,阿里云社区博客专家。致力于输出体系化编程知识与解决方案,并助力软件行业发展与从业者学习减负,让编程产生更大价值。(欢迎热爱技术的朋友关注,交个朋友,一起探索未知)
</div>
<div style="display: flex;flex-direction: column;align-items: center;justify-content: center;">
<img style="width: 150px;" src="https://static.couragesteak.com/common/qrcode_cs.jpg">
<span>公众号</span>
</div>
</div>
</div>
</aside>
<div style="display: flex;justify-content: center;align-items: center">
<button onclick="PopupMenuMobile()">侧边弹窗</button>
</div>
2.2 css样式
<style>
.menu_mobile {
position: fixed;
top: 0;
left: -300px;
width: 300px;
height: 100%;
box-shadow: -2px 0 5px rgba(0, 0, 0, 0.5);
transition: left 0.3s ease;
padding: 20px;
box-sizing: border-box;
z-index: 101;
background-color: pink;
}
.menu_mobile.open {
left: 0;
display: block;
}
</style>
2.3 js事件处理
<script>
function PopupMenuMobile() {
const popup = document.getElementById('menu_mobile');
popup.classList.toggle('open');
}
</script>
由于加水印缘故,图片被加速了,凑活看😅

3 居中弹窗实现
3.1 html
说明:
onclick="event.stopPropagation()"
用于阻止父级别click事件穿透。
<div style="display: flex;justify-content: center;align-items: center">
<button onclick="PopupAlert()">居中弹窗</button>
</div>
<aside id="alert" class="alert" onclick="PopupAlert()">
<div class="alert_content" onclick="event.stopPropagation()">
有勇气的牛排
CSDN全栈&网络安全领域优质创作者,阿里云社区博客专家。致力于输出体系化编程知识与解决方案,并助力软件行业发展与从业者学习减负,让编程产生更大价值。(欢迎热爱技术的朋友关注,交个朋友,一起探索未知)
<div style="display: flex;flex-direction: column;align-items: center;justify-content: center;">
<img style="width: 150px;" src="https://static.couragesteak.com/common/qrcode_cs.jpg">
<span>公众号</span>
</div>
</div>
</aside>
<div id="overlay" class="overlay"></div>
3.2 css
<style>
.overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
display: none;
}
.overlay.active {
display: block;
z-index: 90;
}
.alert {
display: none;
width: 100%;
height: 100%;
position: fixed;
top: 0;
border-radius: 10px;
}
.alert.active {
display: flex;
left: 0;
z-index: 100;
justify-content: center;
align-items: center;
}
.alert_content {
width: 300px;
height: 300px;
background-color: white;
border-radius: 10px;
padding: 15px;
}
</style>
3.3 js事件处理
<script>
function PopupAlert() {
const overlay = document.getElementById('overlay');
overlay.classList.toggle('active');
const popup_alert = document.getElementById('alert');
popup_alert.classList.toggle('active');
}
</script>

<h2><a id="1__0"></a>1 前言</h2>
<p>在现代前端开发中,弹窗(Modal)是常见的交互组件,广泛应用于表单输入、信息提示和用户确认等场景。尽管框架和库提供了丰富的弹窗功能,但掌握原生 HTML 和 JavaScript 实现弹窗的技术,能帮助开发者深入理解 DOM 操作、事件绑定和样式控制等核心知识。</p>
<p>本篇文章将带您从零开始实现一个功能完善的弹窗组件,涵盖基础布局、交互逻辑以及样式优化,为您的开发技能打下扎实基础。</p>
<p>文章中设计到overlay遮罩层知识点可以参考另一篇文章:<a href="https://www.couragesteak.com/article/549" target="_blank">html+javascript原生语法实现遮罩层</a></p>
<p>在原理上,模态框Modal弹窗与这张层是一样的,通过<code>display: none;</code>属性来控制元素是否显示,而且位置也是固定的,故实现固定样式,然后操作class属性,即可实现需求。</p>
<h2><a id="2__10"></a>2 侧边弹窗实现</h2>
<p>本案例是从左边弹出,如需其他方向弹出,可以通过left、right等参数自定义控制。</p>
<h3><a id="21_html_14"></a>2.1 html元素</h3>
<pre><div class="hljs"><code class="lang-html"><span class="hljs-tag"><<span class="hljs-name">aside</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"menu_mobile"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"menu_mobile"</span>></span> <span class="hljs-comment"><!-- 右侧边栏 --></span>
<span class="hljs-tag"><<span class="hljs-name">div</span>></span>
<span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"display: flex;flex-direction: column;justify-content: center;align-items: center"</span>></span>
<span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"phil"</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"font-size: 20px"</span>></span><span class="hljs-tag"><<span class="hljs-name">b</span>></span>有勇气的牛排<span class="hljs-tag"></<span class="hljs-name">b</span>></span><span class="hljs-tag"></<span class="hljs-name">div</span>></span>
<span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"author_desc"</span>></span>
CSDN全栈&网络安全领域优质创作者,阿里云社区博客专家。致力于输出体系化编程知识与解决方案,并助力软件行业发展与从业者学习减负,让编程产生更大价值。(欢迎热爱技术的朋友关注,交个朋友,一起探索未知)
<span class="hljs-tag"></<span class="hljs-name">div</span>></span>
<span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"display: flex;flex-direction: column;align-items: center;justify-content: center;"</span>></span>
<span class="hljs-tag"><<span class="hljs-name">img</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"width: 150px;"</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://static.couragesteak.com/common/qrcode_cs.jpg"</span>></span>
<span class="hljs-tag"><<span class="hljs-name">span</span>></span>公众号<span class="hljs-tag"></<span class="hljs-name">span</span>></span>
<span class="hljs-tag"></<span class="hljs-name">div</span>></span>
<span class="hljs-tag"></<span class="hljs-name">div</span>></span>
<span class="hljs-tag"></<span class="hljs-name">div</span>></span>
<span class="hljs-tag"></<span class="hljs-name">aside</span>></span>
<span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"display: flex;justify-content: center;align-items: center"</span>></span>
<span class="hljs-tag"><<span class="hljs-name">button</span> <span class="hljs-attr">onclick</span>=<span class="hljs-string">"PopupMenuMobile()"</span>></span>侧边弹窗<span class="hljs-tag"></<span class="hljs-name">button</span>></span>
<span class="hljs-tag"></<span class="hljs-name">div</span>></span>
</code></div></pre>
<h3><a id="22_css_44"></a>2.2 css样式</h3>
<pre><div class="hljs"><code class="lang-css"><style>
<span class="hljs-comment">/* ============ 手机菜单 ============ */</span>
<span class="hljs-selector-class">.menu_mobile</span> {
<span class="hljs-comment">/*display: none;*/</span>
<span class="hljs-comment">/*padding: 25px;*/</span>
<span class="hljs-attribute">position</span>: fixed;
<span class="hljs-attribute">top</span>: <span class="hljs-number">0</span>;
<span class="hljs-comment">/*right: -300px; !* 默认隐藏,右侧位置 *!*/</span>
<span class="hljs-attribute">left</span>: -<span class="hljs-number">300px</span>; <span class="hljs-comment">/* 默认隐藏,右侧位置 */</span>
<span class="hljs-attribute">width</span>: <span class="hljs-number">300px</span>; <span class="hljs-comment">/* 弹窗宽度 */</span>
<span class="hljs-attribute">height</span>: <span class="hljs-number">100%</span>;
<span class="hljs-comment">/*background-color: white;*/</span>
<span class="hljs-attribute">box-shadow</span>: -<span class="hljs-number">2px</span> <span class="hljs-number">0</span> <span class="hljs-number">5px</span> <span class="hljs-built_in">rgba</span>(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0.5</span>);
<span class="hljs-attribute">transition</span>: left <span class="hljs-number">0.3s</span> ease; <span class="hljs-comment">/* 动画效果 */</span>
<span class="hljs-attribute">padding</span>: <span class="hljs-number">20px</span>;
<span class="hljs-attribute">box-sizing</span>: border-box;
<span class="hljs-attribute">z-index</span>: <span class="hljs-number">101</span>;
<span class="hljs-comment">/*scrollbar-width: 3px;*/</span>
<span class="hljs-comment">/*scrollbar-color: red transparent;*/</span>
<span class="hljs-attribute">background-color</span>: pink;
}
<span class="hljs-selector-class">.menu_mobile</span><span class="hljs-selector-class">.open</span> {
<span class="hljs-attribute">left</span>: <span class="hljs-number">0</span>;
<span class="hljs-attribute">display</span>: block;
}
</style>
</code></div></pre>
<h3><a id="23_js_78"></a>2.3 js事件处理</h3>
<pre><div class="hljs"><code class="lang-javascript"><script>
<span class="hljs-keyword">function</span> <span class="hljs-title function_">PopupMenuMobile</span>(<span class="hljs-params"></span>) {
<span class="hljs-keyword">const</span> popup = <span class="hljs-variable language_">document</span>.<span class="hljs-title function_">getElementById</span>(<span class="hljs-string">'menu_mobile'</span>);
popup.<span class="hljs-property">classList</span>.<span class="hljs-title function_">toggle</span>(<span class="hljs-string">'open'</span>);
}
</script>
</code></div></pre>
<p>由于加水印缘故,图片被加速了,凑活看😅</p>
<p><img src="https://static.couragesteak.com/article/10d11c7af276ccafdb7e602fe42dc920.gif" alt="前端html+javascript实现侧边弹窗.gif" /></p>
<h2><a id="3__95"></a>3 居中弹窗实现</h2>
<h3><a id="31_html_97"></a>3.1 html</h3>
<p>说明:</p>
<p><code>onclick="event.stopPropagation()"</code> 用于阻止父级别click事件穿透。</p>
<pre><div class="hljs"><code class="lang-html"><span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"display: flex;justify-content: center;align-items: center"</span>></span>
<span class="hljs-tag"><<span class="hljs-name">button</span> <span class="hljs-attr">onclick</span>=<span class="hljs-string">"PopupAlert()"</span>></span>居中弹窗<span class="hljs-tag"></<span class="hljs-name">button</span>></span>
<span class="hljs-tag"></<span class="hljs-name">div</span>></span>
<span class="hljs-tag"><<span class="hljs-name">aside</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"alert"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"alert"</span> <span class="hljs-attr">onclick</span>=<span class="hljs-string">"PopupAlert()"</span>></span> <span class="hljs-comment"><!-- 右侧边栏 --></span>
<span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"alert_content"</span> <span class="hljs-attr">onclick</span>=<span class="hljs-string">"event.stopPropagation()"</span>></span>
有勇气的牛排
CSDN全栈&网络安全领域优质创作者,阿里云社区博客专家。致力于输出体系化编程知识与解决方案,并助力软件行业发展与从业者学习减负,让编程产生更大价值。(欢迎热爱技术的朋友关注,交个朋友,一起探索未知)
<span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"display: flex;flex-direction: column;align-items: center;justify-content: center;"</span>></span>
<span class="hljs-tag"><<span class="hljs-name">img</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"width: 150px;"</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://static.couragesteak.com/common/qrcode_cs.jpg"</span>></span>
<span class="hljs-tag"><<span class="hljs-name">span</span>></span>公众号<span class="hljs-tag"></<span class="hljs-name">span</span>></span>
<span class="hljs-tag"></<span class="hljs-name">div</span>></span>
<span class="hljs-tag"></<span class="hljs-name">div</span>></span>
<span class="hljs-tag"></<span class="hljs-name">aside</span>></span>
<span class="hljs-comment"><!--遮罩层--></span>
<span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"overlay"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"overlay"</span>></span><span class="hljs-tag"></<span class="hljs-name">div</span>></span>
</code></div></pre>
<h3><a id="32_css_123"></a>3.2 css</h3>
<pre><div class="hljs"><code class="lang-css"><style>
<span class="hljs-comment">/* ============ 遮罩层 ============ */</span>
<span class="hljs-selector-class">.overlay</span> {
<span class="hljs-attribute">position</span>: fixed;
<span class="hljs-attribute">top</span>: <span class="hljs-number">0</span>;
<span class="hljs-attribute">left</span>: <span class="hljs-number">0</span>;
<span class="hljs-attribute">width</span>: <span class="hljs-number">100%</span>;
<span class="hljs-attribute">height</span>: <span class="hljs-number">100%</span>;
<span class="hljs-attribute">background-color</span>: <span class="hljs-built_in">rgba</span>(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0.5</span>);
<span class="hljs-attribute">display</span>: none; <span class="hljs-comment">/* 默认隐藏 */</span>
}
<span class="hljs-selector-class">.overlay</span><span class="hljs-selector-class">.active</span> {
<span class="hljs-attribute">display</span>: block; <span class="hljs-comment">/* 显示遮罩层 */</span>
<span class="hljs-attribute">z-index</span>: <span class="hljs-number">90</span>;
}
<span class="hljs-comment">/* ============ 居中弹窗 ============ */</span>
<span class="hljs-selector-class">.alert</span> {
<span class="hljs-attribute">display</span>: none;
<span class="hljs-attribute">width</span>: <span class="hljs-number">100%</span>;
<span class="hljs-attribute">height</span>: <span class="hljs-number">100%</span>;
<span class="hljs-attribute">position</span>: fixed;
<span class="hljs-attribute">top</span>: <span class="hljs-number">0</span>;
<span class="hljs-attribute">border-radius</span>: <span class="hljs-number">10px</span>;
}
<span class="hljs-selector-class">.alert</span><span class="hljs-selector-class">.active</span> {
<span class="hljs-attribute">display</span>: flex;
<span class="hljs-attribute">left</span>: <span class="hljs-number">0</span>;
<span class="hljs-attribute">z-index</span>: <span class="hljs-number">100</span>;
<span class="hljs-attribute">justify-content</span>: center;
<span class="hljs-attribute">align-items</span>: center;
}
<span class="hljs-selector-class">.alert_content</span> {
<span class="hljs-attribute">width</span>: <span class="hljs-number">300px</span>;
<span class="hljs-attribute">height</span>: <span class="hljs-number">300px</span>;
<span class="hljs-attribute">background-color</span>: white;
<span class="hljs-attribute">border-radius</span>: <span class="hljs-number">10px</span>;
<span class="hljs-attribute">padding</span>: <span class="hljs-number">15px</span>;
}
</style>
</code></div></pre>
<h3><a id="33_js_179"></a>3.3 js事件处理</h3>
<pre><div class="hljs"><code class="lang-javascript"><script>
<span class="hljs-keyword">function</span> <span class="hljs-title function_">PopupAlert</span>(<span class="hljs-params"></span>) {
<span class="hljs-keyword">const</span> overlay = <span class="hljs-variable language_">document</span>.<span class="hljs-title function_">getElementById</span>(<span class="hljs-string">'overlay'</span>);
overlay.<span class="hljs-property">classList</span>.<span class="hljs-title function_">toggle</span>(<span class="hljs-string">'active'</span>);
<span class="hljs-keyword">const</span> popup_alert = <span class="hljs-variable language_">document</span>.<span class="hljs-title function_">getElementById</span>(<span class="hljs-string">'alert'</span>);
popup_alert.<span class="hljs-property">classList</span>.<span class="hljs-title function_">toggle</span>(<span class="hljs-string">'active'</span>);
}
</script>
</code></div></pre>
<p><img src="https://static.couragesteak.com/article/e0e2be3a4ecb77c9b90f4d03ad71cfb5.gif" alt="前端html+javascript实现居中弹窗.gif" /></p>
留言