【问题标题】:Manipulate :before and :after with javascript使用 javascript 操作 :before 和 :after
【发布时间】:2026-01-06 10:30:01
【问题描述】:

我有一个下拉导航栏(小提琴here 和下面的 sn-p)。单击 SubItem 时,JS 函数会进行 Ajax 调用(未显示)。我想要实现的是在单击 SubItem 时隐藏 SubItems 列表,以避免当前烦人的重叠。

function GetData(TheClicked,WhichItem) {
	//In the working version, here is an Ajax call;
	document.getElementById("MainContainer").innerHTML = 'SomeTextSomeTextSomeTextSomeText';
}
body {
	margin: 0;
	padding: 0;
	background: #fcf8f2;
}
.NavBarContainer {
	position: block;
  clear: both;
	top: 0;
	width: 100%;
	background: #4a535b;
}
.NavBar ul {
  list-style: none;
  padding: 0;
  margin: 0;
}

.NavBar ul li {
	display: block;
	position: relative;
	float: left;
}
.NavBar li ul { display: none; }

.NavBar ul li a {
	display: block;
	padding: 0.6rem;
	text-decoration: none;
	white-space: nowrap;
	color: #fffbf4;
	font-size:1.2rem;
	letter-spacing:0.1rem;
	-webkit-animation: fadeIn 1s;
	animation: fadeIn 1s;
}

.NavBar ul li a:hover { 
	background: #2c3e50; 
	-webkit-transition: background-color 0.5s ease-out;
	-moz-transition: background-color 0.5s ease-out;
	-o-transition: background-color 0.5s ease-out;
	transition: background-color 0.5s ease-out;
}
.NavBar li:hover > ul {
	display: block;
	position: absolute;
}

.NavBar li:hover li { float: none; }

.NavBar li:hover a { background: #4a535b; }

.NavBar li:hover li a:hover { background: #2c3e50; }

.NavBar li ul li { border-top: 0; }
.NavBar ul ul ul {
	left: 100%;
  top: 0;
}

.NavBar ul:before,
.NavBar ul:after {
	content: " "; /* 1 */
	display: table; /* 2 */
}
.NavBar ul:after { clear: both; }

.MainContainer {
	background: #fffcf9;
	margin: auto;
	width: 80%;
	border-style:solid;
	border-width:thin;
	border-color:#e2e0d9;
	padding:1rem;
  color: red;
}
<div class="NavBarContainer" id="NavBarContainer">
<div class="NavBar">
  <ul>
    <li><a href="#">Item#1</a>
      <ul>
        <li><a href="#" onclick="GetData(this,'SubItem_11');">SubItem_11</a></li>
        <li><a href="#" onclick="GetData(this,'SubItem_12'); return false;">SubItem_12</a></li>
        <li><a href="#" onclick="GetData(this,'SubItem_13'); return false;">SubItem_13</a></li>
      </ul>
    </li>
		<li><a href="#">Item#2</a>
      <ul>
        <li><a href="#" onclick="GetData(this,'SubItem_21'); return false;">SubItem_21</a></li>
        <li><a href="#" onclick="GetData(this,'SubItem_22'); return false;">SubItem_22</a></li>
        <li><a href="#" onclick="GetData(this,'SubItem_23'); return false;">SubItem_23</a></li>
      </ul>   
		</li> 
		<li><a href="#">Item#3</a>
      <ul>
        <li><a href="#" onclick="GetData(this,'SubItem_31');">SubItem_31</a></li>
        <li><a href="#" onclick="GetData(this,'SubItem_32');">SubItem_32</a></li>
        <li><a href="#" onclick="GetData(this,'SubItem_33');">SubItem_33</a></li>
      </ul>   
		</li>     
  </ul>     
</div>
</div>


<div class="MainContainer" id="MainContainer">...</div>

【问题讨论】:

  • 到底是什么问题?
  • 例如,如果您单击 SubItem_22 并且不将鼠标移开,则响应文本位于下拉列表下方。我希望 SubItems 列表在单击时消失(并且只有在将鼠标悬停在主菜单上时才会再次出现)。
  • 好吧,CSS 伪类做他们做的事,你不能用 JavaScript 来影响它。如果你想让你的菜单有不同的表现,你通常必须使用 JavaScript,处理“mouseenter”、“mouseleave”等事件并根据需要添加/删除类。
  • 我明白了。我希望有一些 JS 技巧来避免重写所有现有的 css。非常感谢。

标签: javascript css class


【解决方案1】:

你不想操纵 :after 和 :before 伪元素,你想隐藏 UL 元素。您可以做的是在用户单击任何链接设置 displaynone 时隐藏 UL(并且不要忘记之后删除该属性)。

function GetData(TheClicked,WhichItem) {
  parent = TheClicked.parentElement.parentElement; //get the UL
  parent.style.display = 'none'; //hide it

  //In the working version, here is an Ajax call;
  document.getElementById("MainContainer").innerHTML = 'SomeTextSomeTextSomeTextSomeText';

  //remove the display set before
  setTimeout(function(){
    parent.style.removeProperty('display');
  }, 50)
}

注意超时,如果您删除没有它的属性,.NavBar 元素看起来不会像 hover 状态并且菜单弹出窗口再次出现。

一些建议:

  • 不要在变量和函数的开头使用大写字母,将其留给 javascript 类(使用 getDatatheClickedwhichItem
  • 一些 click 事件回调返回 false 而一些不返回,请阅读回调中的 event 对象以及正确使用 event.preventDefault() 而不是返回 false
  • 您不需要将文本作为参数传递,您可以通过theClicked.innerText 获取它以简化您的代码

【讨论】:

  • 我尝试了这两种解决方案(@arieljoud 和@Armel)并且都完成了这项工作,我都喜欢。你们中的一个人提供建议,另一个人提供sn-p。接受一个或另一个(对我来说)是一样的,所以决定是随机的。谢谢!
【解决方案2】:

你可以做的是关闭指针事件,在子菜单隐藏后立即重新激活,例如:

function GetData(TheClicked,WhichItem) {
    //In the working version, here is an Ajax call;
    document.getElementById("MainContainer").innerHTML = 'SomeTextSomeTextSomeTextSomeText';
    // The parent ul
    var parent = TheClicked.parentElement.parentElement;
    // De-activate the pointer-events
    parent.style['pointer-events'] = 'none';
    // Re-activate the pointer-events after 100ms
    setTimeout(function() {
        parent.style['pointer-events'] = '';
    }, 100);
}
body {
	margin: 0;
	padding: 0;
	background: #fcf8f2;
}
.NavBarContainer {
	position: block;
  clear: both;
	top: 0;
	width: 100%;
	background: #4a535b;
}
.NavBar ul {
  list-style: none;
  padding: 0;
  margin: 0;
}

.NavBar ul li {
	display: block;
	position: relative;
	float: left;
}
.NavBar li ul { display: none; }

.NavBar ul li a {
	display: block;
	padding: 0.6rem;
	text-decoration: none;
	white-space: nowrap;
	color: #fffbf4;
	font-size:1.2rem;
	letter-spacing:0.1rem;
	-webkit-animation: fadeIn 1s;
	animation: fadeIn 1s;
}

.NavBar ul li a:hover { 
	background: #2c3e50; 
	-webkit-transition: background-color 0.5s ease-out;
	-moz-transition: background-color 0.5s ease-out;
	-o-transition: background-color 0.5s ease-out;
	transition: background-color 0.5s ease-out;
}
.NavBar li:hover > ul {
	display: block;
	position: absolute;
}

.NavBar li:hover li { float: none; }

.NavBar li:hover a { background: #4a535b; }

.NavBar li:hover li a:hover { background: #2c3e50; }

.NavBar li ul li { border-top: 0; }
.NavBar ul ul ul {
	left: 100%;
  top: 0;
}

.NavBar ul:before,
.NavBar ul:after {
	content: " "; /* 1 */
	display: table; /* 2 */
}
.NavBar ul:after { clear: both; }

.MainContainer {
	background: #fffcf9;
	margin: auto;
	width: 80%;
	border-style:solid;
	border-width:thin;
	border-color:#e2e0d9;
	padding:1rem;
  color: red;
}
<div class="NavBarContainer" id="NavBarContainer">
<div class="NavBar">
  <ul>
    <li><a href="#">Item#1</a>
      <ul>
        <li><a href="#" onclick="GetData(this,'SubItem_11');">SubItem_11</a></li>
        <li><a href="#" onclick="GetData(this,'SubItem_12'); return false;">SubItem_12</a></li>
        <li><a href="#" onclick="GetData(this,'SubItem_13'); return false;">SubItem_13</a></li>
      </ul>
    </li>
		<li><a href="#">Item#2</a>
      <ul>
        <li><a href="#" onclick="GetData(this,'SubItem_21'); return false;">SubItem_21</a></li>
        <li><a href="#" onclick="GetData(this,'SubItem_22'); return false;">SubItem_22</a></li>
        <li><a href="#" onclick="GetData(this,'SubItem_23'); return false;">SubItem_23</a></li>
      </ul>   
		</li> 
		<li><a href="#">Item#3</a>
      <ul>
        <li><a href="#" onclick="GetData(this,'SubItem_31');">SubItem_31</a></li>
        <li><a href="#" onclick="GetData(this,'SubItem_32');">SubItem_32</a></li>
        <li><a href="#" onclick="GetData(this,'SubItem_33');">SubItem_33</a></li>
      </ul>   
		</li>     
  </ul>     
</div>
</div>


<div class="MainContainer" id="MainContainer">...</div>

【讨论】:

  • 我尝试了这两种解决方案(@arieljoud 和@Armel)并且都完成了这项工作,我都喜欢。你们中的一个人提供建议,另一个人提供sn-p。接受一个或另一个(对我来说)是一样的,所以决定是随机的。谢谢!