这取决于你的弹出窗口是否正确
absolute
或
fixed
而父母有
position
除了
static
设置,以及弹出窗口是否在包装器内;或者是你的直系子女
body
.
前面有三个例子:
-
完全的
作为非静态父对象的子对象弹出(
有优点也有缺点
)
-
固定的
弹出窗口(
有优点也有缺点
)
-
完全的
作为文档的直接子级弹出
<body>
(
最好的
)
1.将绝对子对象移动到父对象内的X、Y坐标
案例:
position: absolute;
在一个
position: relative;
父母亲
-
如果父母
有滚动条
(
overflow
价值以外的
visible
)
X = Event.pageX + Parent.scrollLeft - Parent.offsetLeft
Y = Event.pageY + Parent.scrollTop - Parent.offsetTop
// !! Bad practice !!
X = Event.pageX - Parent.offsetLeft
Y = Event.pageY - Parent.offsetTop
例子:
const EL = (sel, el) => (el||document).querySelector(sel);
const EL_area = EL("#area");
const EL_popup = EL("#popup");
const showPopup = (evt) => {
const EL_btn = evt.currentTarget;
Object.assign(EL_popup.style, {
left: `${evt.pageX + EL_btn.scrollLeft - EL_btn.offsetLeft}px`,
top: `${evt.pageY + EL_btn.scrollTop - EL_btn.offsetTop}px`,
display: `block`,
});
};
EL_area.addEventListener("click", showPopup);
body {
height: 300vh; /* Just to force some scrollbars */
}
#area {
position: relative; /* this is needed! */
height: 150px;
background: #eee;
margin: 40px;
}
#popup {
position: absolute;
height: 30px;
background: gold;
display: none;
}
<div id="area">
Click here to shop popup, and scroll the window
<div id="popup">Popup</div>
</div>
赞成的意见:
欺骗:
-
如果他是实际事件,则需要额外的代码来防止弹出移动
target
-允许与内部内容交互,且弹出窗口不移动。
-
弹出窗口需要是特定父元素的子元素,这会导致弹出窗口和代码重用性差。PS:解决方案是使用:
SomeClickedElement.append(EL_popup)
.
-
包装父元素(
#area
)需要有一个
位置
设置(除
静止的
),即:
位置:相对;
2.将固定元素移动到X、Y坐标
案例:
position: fixed;
在父对象的外部(或内部)弹出,但通常作为
<车身>
.
X = Event.clientX
Y = Event.clientY
例子:
const EL = (sel, el) => (el||document).querySelector(sel);
const EL_area = EL("#area");
const EL_popup = EL("#popup");
const showPopup = (evt) => {
Object.assign(EL_popup.style, {
left: `${evt.clientX}px`,
top: `${evt.clientY}px`,
display: `block`,
});
};
EL_area.addEventListener("click", showPopup);
body {
height: 300vh; /* Just to force some scrollbars */
}
#area {
/* position: relative; /* not necessary any more */
height: 150px;
background: #eee;
margin: 40px;
}
#popup {
position: fixed;
height: 30px;
background: gold;
display: none;
}
<div id="area">
Click here to shop popup, and scroll the window
</div>
<div id="popup">Popup fixed</div>
赞成的意见:
-
如果放置
外部
父母的(
#区域
)-如果点击在其内部启动,则无需额外代码来阻止其移动。
-
更好的代码重用性。根据单击的元素,您只需更改其内容即可重用同一弹出窗口。
-
包装父元素(
#区域
)不需要有一个
位置
.
-
Event.clientX
和
Event.clientY
这就是将其移动到新位置所需的全部。
欺骗:
-
如果页面被滚动,弹出位置相对于窗口是固定的。一个解决办法就是让它成为现实
隐藏
在页面滚动,或更复杂的-移动它的坐标变化的差异。
3.(最好!)绝对移动(
体内
)元素到X,Y坐标
案例:
位置:绝对;
弹出作为
身体
X = Event.clientX + window.scrollX
Y = Event.clientY + window.scrollY
例子:
const EL = (sel, el) => (el||document).querySelector(sel);
const EL_area = EL("#area");
const EL_popup = EL("#popup");
const showPopup = (evt) => {
Object.assign(EL_popup.style, {
left: `${evt.clientX + window.scrollX}px`,
top: `${evt.clientY + window.scrollY}px`,
display: `block`,
});
};
EL_area.addEventListener("click", showPopup);
body {
height: 300vh; /* Just to force some scrollbars */
}
#area {
/* position: relative; /* not necessary any more */
height: 150px;
background: #eee;
margin: 40px;
}
#popup {
position: absolute;
height: 30px;
background: gold;
display: none;
}
<div id=“区域”>
点击这里购物弹出窗口,并滚动窗口
</部门>
<div id=“popup”>弹出修复</部门>
赞成的意见:
-
即使页面被滚动,弹出位置也“锚定”在相对于文档的相同位置,而不是相对于滚动窗口。
-
(除非Event.currentTarget是整个
"body"
)如果单击了弹出窗口的内容,则其位置不会改变。
对所有情况的建议:
-
为了改善用户体验
“浮动”
弹出,需要额外的计算,这是决定
剩余可用空间
以便在不隐藏部分的情况下将其安装在窗口中(坐标的最小值、最大值、实际弹出窗口大小和可用窗口宽度、高度)。我把这个留给读者,因为答案变得相当冗长——除非在评论中明确要求。
-
需要附加代码才能关闭
弹出窗口
如果用户
外面咔嗒声
当然。只需检查是否单击
Event.target.closest("#popup") !== EL_popup
(如果需要,请关闭弹出窗口。)
true
).这一点有时也适用于
上下文菜单
,但很少以窗口为中心
情态动词
有专门的
关
按钮
最佳实践示例:
const EL = (sel, el) => (el||document).querySelector(sel);
let EL_popup; // To remember the currently active popup:
const handler_popup = (evt) => {
// Get clicked target
const EL_targ = evt.target;
// Clicked a popup, do nothing (Comment this line if not needed)
if (EL_targ.closest(".popup")) return;
// Close currently open popup (if any):
if (EL_popup) EL_popup.classList.remove("is-active");
// Get initiator button
const EL_btn = EL_targ.closest("[data-popup]");
// Not a valid button
if (!EL_btn) return;
// Get the popup
EL_popup = EL(EL_btn.dataset.popup);
// No matching popup in this page, do nothing
if (!EL_popup) return;
// Show popup
Object.assign(EL_popup.style, {
left: `${evt.clientX + window.scrollX}px`,
top: `${evt.clientY + window.scrollY}px`,
});
EL_popup.classList.add("is-active");
};
EL("body").addEventListener("click", handler_popup);
body {
min-height: 300vh;
}
#area {
background: #eee;
padding: 10px;
}
.popup {
position: absolute;
background: gold;
display: none;
}
.popup.is-active {
display: block;
}
<div id="area" data-popup="#popup-one">Show "popup one"</div>
<button data-popup="#popup-two" type="button">Show "popup two"</button>
<br>Click anywhere to close an open popup
<br>Click inside a popup. It will not close ()
<div class="popup" id="popup-one">Popup one!</div>
<div class="popup" id="popup-two">Popup TWO!</div>