如何实现div弹窗弹出时背景半暗且不可点击?
实现弹窗时背景半暗且不可点击的优化方案
我已经实现点击「change my grid」按钮弹出div弹窗的功能,现在需要弹窗显示时,背景呈现半暗效果(能隐约看到背景内容)且不可点击。
我尝试在点击事件监听器中添加一个背景div,但没达到预期效果——console.log显示div已创建,但视觉和交互都不对。请问是继续优化这个方案还是有其他思路?
附上我的代码(已标注背景div相关部分):
<body> <div id="container"> <button id="change-grid">Change my grid!</button> <div id="box"> <div id="shell"> <div id="screen-border"> <div id="screen"> <span id="inner-screen"></span> </div> </div> </div> <div id="knobs"> <div id="outer-left"> <div id="central-left"> <div id="inner-left"></div> </div> </div> <div id="outer-right"> <div id="central-right"> <div id="inner-right"></div> </div> </div> </div> </div> <button id="refresh">Refresh me!</button> <div id="popup"> <button id="small">Small</button> <button id="medium">Medium</button> <button id="large">large</button> </div> </div> </body>
body { margin: 0px; } #container { display: flex; flex-direction: row; justify-content: space-evenly; align-items: center; min-height: 100vh; box-shadow: inset 0px -20px 20px 1px #1d321d; background: linear-gradient(380deg, black, 5%, #72c077); } #box { display: flex; flex-direction: column; justify-content: center; align-items: center; height: 542px; width: 680px; border: solid 1px 0px 1px; border-radius: 30px 30px 20px 20px; box-shadow: inset 0px 20px 10px #e20000, inset 0px -8px 10px #340000, 0px 10.5px 15px 5px #200000; background-color: #8a0000; } #shell { display: flex; justify-content: center; align-items: flex-end; height: 400px; width: 670px; border-radius: 26px 26px 0px 0px; background-color: #dc0000; } #screen-border { display: flex; justify-content: center; align-items: center; height: 320px; width: 520px; border-top: solid 5px #bd0202; border-right: solid 2px white; border-left: solid 2px white; border-radius: 10px 10px 7px 7px; box-shadow: inset 1.5px 0px white, inset 0px -8px 10px #dc0000, inset -1.5px 0px white; background-color: #9a0000; } #screen { position: relative; display: flex; flex-direction: column; height: 300px; width: 500px; border-top: solid 0.1px #292828; border-right: solid 0.1px rgba(41, 40, 40, 0.75); border-left: solid 0.1px rgba(41, 40, 40, 0.75); background-color: #cdcdcd } #inner-screen { position: absolute; top: 0; left: 0; height: 100%; width: 100%; box-shadow: 0px 10px 10px -5px #b30202, inset 0px 10px 10px -8px #121212, inset -8px 0px 10px -4px #343434, inset 8px 0px 10px -4px #343434; user-select: none; pointer-events: none; } #screen div { /*THESE ARE THE ROWS...*/ display: flex; height: 100%; } #screen div div { /*...AND THESE ARE THE LITTLE SQUARES INSIDE THE ROWS!!*/ width: 100%; box-shadow: 1px 1px 0 rgba(0, 0, 0, 0.05) inset; } #knobs { display: flex; justify-content: space-between; align-items: flex-end; height: 130px; width: 670px; margin-bottom: 6px; border-radius: 0px 0px 18px 18px; background-color: #dc0000; } #central-left { display: flex; justify-content: center; align-items: center; height: 100px; width: 100px; margin-top: 2.5px; margin-left: -7px; margin-bottom: -3px; border-radius: 50px; background-color: #fff0f0; } #central-right { display: flex; justify-content: center; align-items: center; height: 100px; width: 100px; margin-top: 2.5px; margin-right: -7px; margin-bottom: -3px; border: solid 1px white; border-radius: 50px; background-color: #fff0f0; } #outer-left, #outer-right { display: flex; justify-content: center; align-items: center; height: 102px; width: 102px; margin-bottom: 8px; border: solid 1px #382929; border-radius: 50px; background-color: #bebebe; } #outer-left { margin-left: 20px; box-shadow: inset -2px 2px #a2a2a2, 8px -1px 20px #382929; } #outer-right { margin-right: 20px; box-shadow: inset 2px 2px #a2a2a2, -8px -1px 20px #382929; } #inner-left, #inner-right { height: 85px; width: 85px; border-radius: 50px; background-color: #f3f3f3; } #inner-left { margin-bottom: -2px; margin-left: -2px; box-shadow: inset 3px 3px 10px 0px #cecece; } #inner-right { margin-bottom: -2px; margin-right: -2px; box-shadow: inset -3px 3px 10px #cecece; } button { display: flex; justify-content: center; align-items: center; height: 75px; width: 215px; border: 2px solid; border-bottom: 4px solid; padding: 30px; border-radius: 20px; font-size: 20px; font-family: 'Comic Sans MS', 'Comic Sans', cursive; box-shadow: 0px 5px 10px #263c26; transition: all 0.1s; } .hover-style { box-shadow: 0px 15px 25px -5px #263c26; transform: scale(1.03); } .click-style { box-shadow: 0px 4px 8px #263c26; transform: scale(.98); } #popup { display: flex; justify-content: space-evenly; align-items: center; position: absolute; top: 2%; transform: scale(0.01); visibility: hidden; height: 300px; width: 840px; border: 1px solid; border-radius: 40px; box-shadow: inset 0px 0px 15px #263c26; background-color: #72c077; transition: 0.5s; } #popup.opened-popup { top: initial; transform: scale(1); visibility: visible; } #background { /* <--- The style of the new div */ height: inherit; width: inherit; position: absolute; background-color: rgba(0, 0, blue, 1); }
//FUNCTION TO MAKE THE GRID function makeGrid(a, b) { const container = document.querySelector('#screen'); let divRow = undefined; for (i = 0; a > i; i++) { divRow = document.createElement('div') container.appendChild(divRow); } const containers = document.querySelectorAll('#screen div'); let divColumn = undefined; containers.forEach(function (div) { for (i = 0; b > i; i++) { divColumn = document.createElement('div'); div.appendChild(divColumn) } }) } makeGrid(30, 50); // TO MAKE THE RANDOM COLORS const squares = document.querySelectorAll('#screen div div'); function randomValue() { return Math.floor(Math.random() * 256); } function randomColor() { return `rgb(${randomValue()}, ${randomValue()}, ${randomValue()})`; } function changeBackground() { let opacity = 0; this.style.backgroundColor = randomColor(); console.log(randomColor()); } squares.forEach(function(element) { element.addEventListener('mouseover', changeBackground, {once: true}); }); // Start from here!!! // EVENTS: HOVERING AND CLICKING THE BUTTONS const container = document.getElementById('container') const backgroundDiv = document.createElement('div'); backgroundDiv.setAttribute('id', 'background') /*Up here it's how I tryed to set a div for a new background that should appear when you press the change grid button in order to darken everything but the popup*/ const btnChangeGrid = document.getElementById('change-grid'); const btnRefresh = document.getElementById('refresh'); const popup = document.querySelector('#popup'); btnChangeGrid.addEventListener('mouseenter', function() {this.classList.add('hover-style')}); btnChangeGrid.addEventListener('mouseleave', function() {this.classList.remove('hover-style')}); btnRefresh.addEventListener('mouseenter', function() {this.classList.add('hover-style')}); btnRefresh.addEventListener('mouseleave', function() {this.classList.remove('hover-style')}); btnChangeGrid.addEventListener('mousedown', openPopUp); btnChangeGrid.addEventListener('mouseup', function() {this.classList.remove('click-style')}); btnRefresh.addEventListener('mousedown', resetBackground); btnRefresh.addEventListener('mouseup', function() {this.classList.remove('click-style')}); function openPopUp() { this.classList.add('click-style'); popup.classList.add('opened-popup'); container.appendChild(backgroundDiv); // <--- The new div background } function resetBackground() { const squares = document.querySelectorAll('#screen div div'); squares.forEach(element => element.style.setProperty('background-color', null)); this.classList.add('click-style'); }
优化方案(基于你的思路调整即可)
你的思路完全可行,只需要修正背景div的样式、层级逻辑,补充关闭交互即可:
1. 修复背景div的CSS样式
当前#background的样式有语法错误且定位逻辑不对,替换为:
#background { position: fixed; top: 0; left: 0; width: 100vw; height: 100vh; background-color: rgba(0, 0, 0, 0.5); /* 半透明黑色,0.5可按需调整透明度 */ z-index: 999; /* 低于弹窗层级,确保弹窗在最上层 */ pointer-events: auto; /* 拦截点击,防止穿透到背景内容 */ }
2. 提升弹窗的层级
确保弹窗在背景之上,给#popup添加:
#popup { /* 保留原有样式 */ z-index: 1000; /* 比背景高一级 */ }
3. 完善JS交互逻辑
- 补充弹窗关闭时移除背景的逻辑
- 避免重复添加背景div
- 添加背景点击关闭弹窗的功能
// 新增关闭弹窗函数 function closePopUp() { popup.classList.remove('opened-popup'); // 移除背景div if (backgroundDiv.parentNode) { backgroundDiv.parentNode.removeChild(backgroundDiv); } } // 修改打开弹窗函数,避免重复添加背景 function openPopUp() { this.classList.add('click-style'); popup.classList.add('opened-popup'); // 仅当背景未添加时才插入 if (!backgroundDiv.parentNode) { container.appendChild(backgroundDiv); } } // 点击背景关闭弹窗 backgroundDiv.addEventListener('click', closePopUp); // 点击弹窗内按钮关闭弹窗(可同时添加修改网格的逻辑) document.querySelectorAll('#popup button').forEach(btn => { btn.addEventListener('click', function() { // 这里可以添加对应网格大小的修改逻辑,比如调用makeGrid(10,20)等 closePopUp(); }); });
4. 给容器添加相对定位
确保弹窗和背景的定位逻辑正确,给#container添加:
#container { /* 保留原有样式 */ position: relative; }
修改后,背景会正确覆盖整个屏幕,呈现半暗效果,同时拦截点击事件,弹窗始终显示在最上层。
内容的提问来源于stack exchange,提问作者91Flavio91
相关产品推荐
相关产品推荐

