HTMX + 原生 CSS 实现 HTML 模态弹出窗口
可能是因为开发习惯不同,很多小伙伴还没完全适应 htmx 带来的全新的交互方式,导致有时候一些交互操作不知道应该怎么处理,比如经常用到的模态弹出窗口。在使用 Vue 或 React 时,是直接接收后台传过来的 Json 数据,然后通过 JavaScript 代码实现窗口弹出效果。但如果在 htmx 也这么做的话,虽然也能实现,但这种做法就失去了 htmx 的灵魂。
下面就教大家怎么使用 htmx 实现地道的 html 模态弹出窗口及关闭。
htmx 完整项目源码
完整的 htmx 模态弹出窗口源码已经上传至 GitHub
使用到的 htmx 特性
htmx 属性
htmx API
项目结构
完整项目总共4个文件,按 Flask 默认的目录结构搭建。
- app.py
- templates/index.html
- templates/popup.html
- static/htmx.min.js
服务端
服务端使用 flask 实现,定义了两个路由,一个是首页:只有一个按钮用来控制弹出模态窗口;第二是弹出窗口的页面内容。
服务端源码
app.py
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/')
def index():
return render_template('index.html')
@app.route('/popup')
def popup():
return render_template('popup.html')
if __name__ == '__main__':
app.run(debug=True)
服务端只做了两件事:一个是返回首页的 html 内容;第二个就是返回模态弹出窗口的内容。
前端
前端的重点在于 index.html 的 CSS 样式代码。其实模态窗口的弹出、关闭都可以由 CSS 样式来控制的,所以只需要定义好 CSS 样式,然后给对应的内容添加 CSS 类名就能控制页面内容的展示方式,包括模态弹出窗口效果等等。
前端源码
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="/static/htmx.min.js"></script>
<title>htmx 中文网</title>
<style>
/** 这是弹出窗口的遮罩层 **/
.popup-container{
position: fixed;
left: 0;
top: 0;
width: 100%;
height: 100%;
background: #1c1c1c;
opacity: .9;
z-index: 100;
}
/** 这是弹出窗口的主体部分,内容都放到这里面 **/
.popup-box{
position: relative;/** 为了给 btn-close 定位 **/
margin: auto;
border-radius: 8px;
width: 380px;
height: 400px;
background: #fff;
padding: 0 10px;
}
/** 这是弹出窗口的关闭按钮 **/
.btn-close{
border-radius: 50%;
background: transparent;
position: absolute;
top: 5px;
right: 5px;
color: #1c1c1c;
width: 30px;
height: 30px;
text-align: center;
line-height: 30px;
cursor: pointer;
}
.btn-close:hover{
background: #1c1c1c;
color: #fff;
}
</style>
</head>
<body>
<div style="margin: auto;width: 200px;"><button hx-get="popup" hx-target="body" hx-swap="afterbegin">Popup</button></div>
</body>
<script>
function closePopup(){
const popup_container = htmx.find(".popup-container");
if(popup_container){
/** 这里要与 hx-target="body"对应,如果是放在其它div中,就用popup_container.parent.removeChild **/
document.body.removeChild(popup_container);
}
}
</script>
</html>
index.html 只有一个按钮,用户点击后触发 hx-get 获取弹出窗口的 html 片段,并通过 hx-target 把它加载到 body 的最前面: hx-swap="afterbegin"。
如果你想要把弹出窗口的 html 片段放到指定的 DIV 里面,可以通过修改 hx-target 及 hx-swap 两个属性的值来实现,但要记得同步修改 closePopup() 函数时的 removeChild 的元素。
popup.html
<div class="popup-container">
<div class="popup-box">
<div class="btn-close" onclick="closePopup();">X</div>
<h1>这是一个模态弹窗</h1>
</div>
</div>
popup.html 里面的内容是一些 html 片段,会通过 htmx 的 swap 嵌入到 index.html 中变成其中的一个元素,所以可以直接使用 index.html 中定义的 CSS 样式及 JavaScript 代码。
如果需要向弹出窗口放更多的内容,可以把内容与 h1 平级。
运行项目代码,在浏览器中打开 localhost:5000 就能看到只有一个按钮的页面,点击按钮后就会弹出一个模态窗口,再点击模态窗口右上角的 X 按钮就能将弹出窗口关闭。