是否有CSS父选择器?

如何选择<li>元素是锚元素的直接父元素?

举个例子,我的CSS是这样的:

li < a.active {property: value;}

显然,JavaScript有很多方法可以做到这一点,但我希望有某种原生于CSS Level 2的解决方法。

我试图样式化的菜单是由CMS喷出的,所以我不能将活动元素移动到<li>元素…(除非我将菜单创建模块主题化,我宁愿不这样做)。

3010505 次浏览

在CSS 2中没有办法做到这一点。您可以将类添加到li并引用a

li.active > a {property: value;}

我认为你不能只在CSS中选择父级。

但是,由于您似乎已经拥有.active类,因此将该类移动到li(而不是a)会更容易。这样您就可以仅通过CSS访问lia

据我所知,CSS 2中没有。CSS 3有更健壮的选择器,但并没有在所有浏览器中一致地实现。即使有了改进的选择器,我也不相信它会完全完成你在示例中指定的内容。

选择器第4级工作草案包含一个:has()伪类,它将提供此功能。它将类似于jQuery实现,但目前不受Firefox支持。

li:has(> a.active) { /* styles to apply to the li tag */ }

截至2022年,Firefox是唯一默认不支持它的浏览器

与此同时,如果您需要选择具有完全跨浏览器支持的父元素,则必须在Firefox中使用JavaScript。

正如其他一些人所提到的,没有一种方法可以仅使用CSS来为元素的父元素设置样式,但以下方法适用于jQuery

$("a.active").parents('li').css("property", "value");

CSS选择器“通用同胞组合器”可能用于您想要的:

E ~ F {property: value;}

这匹配前面有E元素的任何F元素。

您可以使用这个脚本

*! > input[type=text] { background: #000; }

这将选择文本输入的任何父级。但是等等,还有更多。如果需要,您可以选择指定的父级:

.input-wrap! > input[type=text] { background: #000; }

或者在它处于活动状态时选择它:

.input-wrap! > input[type=text]:focus { background: #000; }

看看这个超文本标记语言:

<div class="input-wrap"><input type="text" class="Name"/><span class="help hide">Your name sir</span></div>

input处于活动状态时,您可以选择span.help并显示它:

.input-wrap! .help > input[type=text]:focus { display: block; }

还有更多的功能;只需查看插件的留档。

顺便说一句,它在Internet Explorer中工作。

W3C排除了这样的选择器,因为它会对浏览器产生巨大的性能影响。

尝试将a切换到block显示,然后使用您想要的任何样式。a元素将填充li元素,您可以根据需要修改其外观。不要忘记将li填充设置为0。

li {padding: 0;overflow: hidden;}a {display: block;width: 100%;color: ..., background: ..., border-radius: ..., etc...}a.active {color: ..., background: ...}

你可以尝试使用超链接作为父链接,然后更改hover上的内部元素。像这样:

a.active h1 {color:red;}
a.active:hover h1 {color:green;}
a.active h2 {color:blue;}
a.active:hover h1 {color:yellow;}

通过这种方式,您可以根据父元素的翻转来更改多个内部标记中的样式。

我知道OP正在寻找一个CSS解决方案,但使用jQuery很容易实现。在我的例子中,我需要为子<li>中包含的<span>标记找到<ul>父标记。jQuery具有:has选择器,因此可以通过它包含的子标记来识别父标记:

$("ul:has(#someId)")

将选择具有id一些的子元素的ul元素。或者为了回答最初的问题,应该像下面这样做(未经测试):

$("li:has(.active)")

没有父选择器;就像没有前一个兄弟选择器一样。没有这些选择器的一个很好的原因是浏览器必须遍历元素的所有子元素以确定是否应该应用一个类。例如,如果你写了:

body:contains-selector(a.active) { background: red; }

然后浏览器将不得不等待,直到它已经加载并解析了所有内容,直到</body>来确定页面是否应该是红色的。

文章为什么我们没有父选择器详细解释了这一点。

目前没有父选择器&它甚至没有在W3C的任何讨论中讨论。您需要了解浏览器如何评估CSS,以实际了解我们是否需要它。

这里有很多技术解释。

Jonathan Snook解释如何评估CSS

Chris Coyier谈家长选择器

Harry Roberts再次谈论如何编写高效的CSS选择器

但是妮可·沙利文有一些关于积极趋势的有趣事实

这些人都是前端开发领域的顶级人才。

这是选择器级别4规范中讨论最多的方面。有了这个,选择器将能够通过在给定的选择器之后使用感叹号来根据其子元素设置样式 (!).

例如:

body! a:hover{background: red;}

如果用户悬停在任何锚点上,将设置红色背景色。

但我们必须等待浏览器的实现:(

从技术上讲,没有直接的方法可以做到这一点。但是,您可以使用jQuery或JavaScript来解决这个问题。

但是,你也可以做这样的事情。

a.active h1 {color: blue;}a.active p {color: green;}

jQuery

$("a.active").parents('li').css("property", "value");

如果你想使用jQuery实现这一点,这里是jQuery父选择器的参考。

只是一个横向菜单的想法…

超文本标记语言

<div class='list'><div class='item'><a>Link</a></div><div class='parent-background'></div><!-- submenu takes this place --></div>

CSS的一部分

/* Hide parent backgrounds... */.parent-background {display: none; }
/* ... and show it when hover on children */.item:hover + .parent-background {display: block;position: absolute;z-index: 10;top: 0;width: 100%; }

更新了演示和其余代码

另一个例子如何在文本输入中使用它-选择父字段集

不,您不能仅在CSS中选择父级。

但是,由于您似乎已经拥有.active类,因此将该类移动到li(而不是a)会更容易。这样您就可以仅通过CSS访问lia

有一个插件可以扩展CSS以包含一些非标准功能,这些功能可以在设计网站时真正提供帮助。它被称为EQCSS

EQCSS添加的内容之一是父选择器。它适用于所有浏览器,Internet Explorer 8及更高版本。格式如下:

@element 'a.active' {$parent {background: red;}}

所以在这里我们对每个元素a.active打开了一个元素查询,对于该查询中的样式,像$parent这样的东西是有意义的,因为有一个参考点。浏览器可以找到父级,因为它与JavaScript中的parentNode非常相似。

这里是#0的演示在Internet Explorer 8中工作的另一个#0演示,以及一个屏幕截图,以防您没有Internet Explorer 8进行测试

EQCSS还包括元选择器$prev用于所选元素之前的元素,$this用于仅匹配元素查询的元素等。

虽然目前标准CSS中没有父选择器,但我正在从事一个名为斧头(即增强CSS选择器语法/ACSSSS)的(个人)项目,其中包括7个新选择器:

  1. 直系父母选择器<(它允许与>相反的选择)
  2. 任何祖先选择器^(启用与[SPACE]相反的选择)

斧头目前处于相对较早的BETA开发阶段。

在此处查看演示:

.parent {float: left;width: 180px;height: 180px;margin-right: 12px;background-color: rgb(191, 191, 191);}
.child {width: 90px;height: 90px;margin: 45px;padding-top: 12px;font-family: sans-serif;text-align: center;font-size: 12px;background-color: rgb(255, 255, 0);}
.child.using-axe < .parent {background-color: rgb(255, 0, 0);}
<div class="parent"><div class="child"></div></div>
<div class="parent"><div class="child using-axe">Here, the axe parent selector turns the outer square red.</div></div>

<script src="https://rouninmedia.github.io/axe/axe.js"></script>

在上面的例子中,<直接父选择器,所以

  • .child.using-axe < .parent

手段:

.child.using-axe的任何直接父级,即.parent

您也可以使用:

  • .child.using-axe < div

这将意味着:

.child.using-axe的任何直接父级,即div

简短的回答是;在CSS的这个阶段,我们没有parent selector,但是如果你无论如何都不需要交换元素或类,第二个选择是使用JavaScript。像这样的:

var activeATag = Array.prototype.slice.call(document.querySelectorAll('a.active'));
activeATag.map(function(x) {if(x.parentNode.tagName === 'LI') {x.parentNode.style.color = 'red'; // Your property: value;}});

或者更短的方法,如果您在应用程序中使用jQuery

$('a.active').parents('li').css('color', 'red'); // Your property: value;

如果子代具有焦点,则伪元素:focus-within允许选择父级。

如果元素具有tabindex属性,则可以聚焦。

浏览器支持焦点内

Tabindex

示例

.parent:focus-within {background: hsl(199deg, 65%, 73%);}
/* demo styles */body {margin: 0;}.parent {background: hsl(0, 0%, 80%);min-height: 100vh;display: grid;place-content: center;}.child {background: hsl(0, 0%, 0%);color: white;padding: 3rem;outline: 0;cursor: pointer;font: 18px/1.25 sans-serif;width: 20ch;}
<div class="parent"><div class="child" tabindex="1">Click or Focus on me, my parent will change.</div></div>

你可以使用#0 CSS伪类

但它有有限的浏览器支持(目前只有Chrome/Edge/Safari)。

至少在CSS 3之前,您不能这样选择。但是现在在JavaScript中可以很容易地完成,你只需要添加一点普通的JavaScript,注意代码很短。

cells = document.querySelectorAll('div');[].forEach.call(cells, function (el) {//console.log(el.nodeName)if (el.hasChildNodes() && el.firstChild.nodeName=="A") {console.log(el)};});
<div>Peter</div><div><a href="#">Jackson link</a></div><div>Philip</div><div><a href="#">Pullman link</a></div>

这是一个使用pointer-eventshover的黑客:

<!doctype html><html><head><title></title><style>/* accessory */.parent {width: 200px;height: 200px;background: gray;}.parent,.selector {display: flex;justify-content: center;align-items: center;}.selector {cursor: pointer;background: silver;width: 50%;height: 50%;}</style><style>/* pertinent */.parent {background: gray;pointer-events: none;}.parent:hover {background: fuchsia;}.parent.selector {pointer-events: auto;}</style></head><body><div class="parent"><div class="selector"></div></div></body></html>

现在是2019年,CSS嵌套模块的最新草案实际上有这样的东西。介绍@nest at规则。

3.2.嵌套规则:@nest

虽然直接嵌套看起来不错,但它有点脆弱。一些有效的嵌套选择器,如. foo&,是不允许的,并且以某些方式编辑选择器可能会使规则意外无效。此外,有些人发现嵌套很难在视觉上与周围的声明区分开来。

为了帮助解决所有这些问题,本规范定义了@nest规则,它对如何有效嵌套样式规则施加了更少的限制。它的语法是:

@nest = @nest <selector> { <declaration-list> }

@nest规则的功能与样式规则相同:它以选择器开头,并包含适用于选择器匹配的元素的声明。唯一的区别是@nest规则中使用的选择器必须是包含嵌套的,这意味着它在某个地方包含嵌套选择器。如果选择器列表中所有单独的复杂选择器都包含嵌套,则选择器列表就是包含嵌套的。

(从上面的URL复制并粘贴)。

本规范下的有效选择器示例:

.foo {color: red;@nest & > .bar {color: blue;}}/* Equivalent to:.foo { color: red; }.foo > .bar { color: blue; }*/
.foo {color: red;@nest .parent & {color: blue;}}/* Equivalent to:.foo { color: red; }.parent .foo { color: blue; }*/
.foo {color: red;@nest :not(&) {color: blue;}}/* Equivalent to:.foo { color: red; }:not(.foo) { color: blue; }*/

有什么想法吗?

如果CSS4将一些钩子添加到向后走中,那将是奇特的。在那之前,有可能(尽管没有建议)使用checkbox和/或radio#2s打破以通常的方式连接事物,并通过这也允许CSS在其正常范围之外运行…

/* Hide things that may be latter shown */.menu__checkbox__selection,.menu__checkbox__style,.menu__hidden {display: none;visibility: hidden;opacity: 0;filter: alpha(opacity=0); /* Old Microsoft opacity */}

/* Base style for content and style menu */.main__content {background-color: lightgray;color: black;}
.menu__hidden {background-color: black;color: lightgray;/* Make list look not so _listy_ */list-style: none;padding-left: 5px;}
.menu__option {box-sizing: content-box;display: block;position: static;z-index: auto;}
/* &#9660; - \u2630 - Three Bars *//*.menu__trigger__selection::before {content: '\2630';display: inline-block;}*/
/* &#9660; - Down Arrow */.menu__trigger__selection::after {content: "\25BC";display: inline-block;transform: rotate(90deg);}

/* Customize to look more `select` like if you like */.menu__trigger__style:hover,.menu__trigger__style:active {cursor: pointer;background-color: darkgray;color: white;}

/*** Things to do when checkboxes/radios are checked*/
.menu__checkbox__selection:checked + .menu__trigger__selection::after,.menu__checkbox__selection[checked] + .menu__trigger__selection::after {transform: rotate(0deg);}
/* This bit is something that you may see elsewhere */.menu__checkbox__selection:checked ~ .menu__hidden,.menu__checkbox__selection[checked] ~ .menu__hidden {display: block;visibility: visible;opacity: 1;filter: alpha(opacity=100); /* Microsoft!? */}

/*** Hacky CSS only changes based off non-inline checkboxes* ... AKA the stuff you cannot unsee after this...*/.menu__checkbox__style[id="style-default"]:checked ~ .main__content {background-color: lightgray;color: black;}
.menu__checkbox__style[id="style-default"]:checked ~ .main__content .menu__trigger__style[for="style-default"] {color: darkorange;}
.menu__checkbox__style[id="style-one"]:checked ~ .main__content {background-color: black;color: lightgray;}
.menu__checkbox__style[id="style-one"]:checked ~ .main__content .menu__trigger__style[for="style-one"] {color: darkorange;}
.menu__checkbox__style[id="style-two"]:checked ~ .main__content {background-color: darkgreen;color: red;}
.menu__checkbox__style[id="style-two"]:checked ~ .main__content .menu__trigger__style[for="style-two"] {color: darkorange;}
<!--This bit works, but will one day cause troubles,but truth is you can stick checkbox/radio inputsjust about anywhere and then call them by id witha `for` label. Keep scrolling to see what I mean--><input type="radio"name="colorize"class="menu__checkbox__style"id="style-default"><input type="radio"name="colorize"class="menu__checkbox__style"id="style-one"><input type="radio"name="colorize"class="menu__checkbox__style"id="style-two">

<div class="main__content">
<p class="paragraph__split">Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmodtempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo</p>
<input type="checkbox"class="menu__checkbox__selection"id="trigger-style-menu"><label for="trigger-style-menu"class="menu__trigger__selection"> Theme</label>
<ul class="menu__hidden"><li class="menu__option"><label for="style-default"class="menu__trigger__style">Default Style</label></li>
<li class="menu__option"><label for="style-one"class="menu__trigger__style">First Alternative Style</label></li>
<li class="menu__option"><label for="style-two"class="menu__trigger__style">Second Alternative Style</label></li></ul>
<p class="paragraph__split">consequat. Duis aute irure dolor in reprehenderit in voluptate velit essecillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat nonproident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
</div>

…漂亮的,但只使用CSS和超文本标记语言,可以通过链接radio/checkbox#6slabel:root0的idfor属性,从几乎任何地方触摸和重新触摸body:root之外的任何东西;可能有人会在某个时候展示如何重新触摸这些。

一个额外的警告是,只有一个input的特定id可能使用,第一checkbox/radio赢得切换状态换句话说…但是多个标签都可以指向相同的input,尽管这会使超文本标记语言和CSS看起来更粗俗。


…我希望有某种原生于CSS Level 2的解决方法…

我不确定其他伪类,但我:checked for pre-CSS 3。如果我没记错的话,它类似于[checked],这就是为什么你可以在上面的代码中找到它,例如,

.menu__checkbox__selection:checked ~ .menu__hidden,.menu__checkbox__selection[checked] ~ .menu__hidden {/* rules: and-stuff; */}

…但是对于::after:hover之类的东西,我根本不确定它们首先出现在哪个CSS版本中。

总之,请不要在生产中使用它,即使是在愤怒的时候。作为一个笑话,或者换句话说,仅仅因为做了一件事并不总是意味着做了一件事。

我会雇佣一些JavaScript代码来做到这一点。例如,在React中,当你迭代数组时,向父组件添加另一个类,这表明它包含你的孩子:

<div className={`parent ${hasKiddos ? 'has-kiddos' : ''}`}>{kiddos.map(kid => <div key={kid.id} />)}</div>

然后简单地说:

.parent {color: #000;}
.parent.has-kiddos {color: red;}

基于子元素更改父元素目前只能在父元素中有<input>元素时发生。当输入获得焦点时,其对应的父元素可能会使用CSS受到影响。

以下示例将帮助您了解在CSS中使用:focus-within

.outer-div {width: 400px;height: 400px;padding: 50px;float: left}
.outer-div:focus-within {background: red;}
.inner-div {width: 200px;height: 200px;float: left;background: yellow;padding: 50px;}
<div class="outer-div"><div class="inner-div">I want to change outer-div(Background color) class based on inner-div. Is it possible?<input type="text" placeholder="Name" /></div></div>

没有css(因此在css预处理器中)父选择器,因为“CSS工作组之前拒绝父选择器提案的主要原因与浏览器性能和增量呈现问题有关。”

试试这个…

此解决方案使用纯CSS2规则,没有Javascript,适用于所有新旧浏览器。单击时,子anchor标签激活其active伪类事件。然后它简单地隐藏自己,允许active事件冒泡到父li标签,然后父li标签重新设置自己并以新样式再次显示他的锚定子标记。孩子已经为父标记设置了样式。

使用您的示例:

<ul><li class="listitem"><a class="link" href="#">This is a Link</a></li></ul>

现在使用a上的active伪类应用这些样式以在单击链接时重新设置父li标记的样式:

a.link {display: inline-block;color: white;background-color: green;text-decoration: none;padding: 5px;}
li.listitem {display: inline-block;margin: 0;padding: 0;background-color: transparent;}
/* When this 'active' pseudo-class event below fires on click, it hides itself,triggering the active event again on its parent which applies new styles to itself and its child. */
a.link:active {display: none;}
.listitem:active {background-color: blue;}
.listitem:active a.link {display: inline-block;background-color: transparent;}

单击时,您应该会看到绿色背景的链接现在更改为列表项的蓝色背景。

输入图片描述

转向

输入图片描述

点击。

这是对一个类似(但我感觉不完全相同)问题的回答,这个问题已经结束,所以我在这里回答了检查输入时如何更改边框颜色

由于无法使用纯CSS根据其子级的状态为父级设置样式,因此此代码段更改了超文本标记语言,以便在输入元素之后立即有一个空的跨度元素。此跨度元素什么都不做,直到输入悬停,此时它显示自己并扩展以适应与具有位置集的祖先相同的大小。这是标签本身,而不是输入。因此边框(阴影)显示就好像它在标签上一样。

* {margin: 0;padding: 0;box-sizing: border-box;}
.OuterField {display: flex;}
.listLabel {padding: 8px 5px;border: 2px solid black;width: 32%;margin: 1%;display: flex;justify-content: space-between;align-items: center;flex-flow: row;position: relative;}
input[type="radio"]~span {display: none;}
input[type="radio"]:checked~span {display: inline-block;width: 100%;height: 100%;border: 2px solid red;box-shadow: 0 0 0 3px orange;position: absolute;top: 0;left: 0;}
<div class="OuterField"><label for="List1" class="listLabel">List 1<input type="radio" id="List1" name="list" value="List1"><span></span></label><label for="List2" class="listLabel">List 2<input type="radio" id="List2" name="list" value="List2"><span></span></label></div>

CSS父选择器(也称为: has()选择器)终于登陆SafariTP 137。该功能目前也正在Chrome实现。(MDN文档

父选择通过伪类:has()完成。例如,div:has(> .child)将选择所有<div>元素,其子级具有child类。

其他例子:

选择元素的直接父元素

<div><p>Child Element</p></div>
div:has(> p)

选择一个元素的所有父元素

<div id="grandparent"><div id="parent"><div id="child"></div><div></div>

下面的选择器将同时选择grandparentparent

div:has(.child)

您还可以将其用于嵌套选择器,甚至用于其他伪类:

div:has(> :nth-child(10))

其他有效的CSS运算符可用于自定义查询。

注意caniuse.com/css-has的浏览器兼容性。

答案中有许多复杂的解决方案。但是您知道父级,因此解决方案并不复杂。如果您想在选中时更改样式。

.parentDiv > input[type="checkbox"]:checked {//style it}

2022年更新CSS选择器4

在CSS选择器4规范中,CSS引入了一个名为:has()的新选择器,它最终允许我们选择父元素。这意味着我们将能够针对其中包含特定子元素的CSS元素。这已经在Safari中得到支持,Chrome105也支持。完整的支持表显示这里.

父选择器的工作原理

在CSS中,如果我们想选择一些东西,我们使用降DOM的选择器。

例如,在div标签中选择p标签如下所示:

 div p {color: red;}

到目前为止,无法真正选择div标签,其中包含p标签,这意味着我们不得不求助于Javascript。这在CSS中没有实现的主要原因是它是一个相当昂贵的操作。CSS解析速度相对较快,但选择父标签需要相对较大的处理量。

使用:has选择器,我们现在可以选择具有p子元素的div元素,或者选择器的任何正常组合。

例如,选择带有子节点pdiv现在看起来像这样:

div:has(p) {color: red;}

这将使任何div与孩子p红色。

将父选择与其他选择器相结合

就像任何其他CSS选择器一样,我们可以针对特定情况组合它。例如,如果您只想选择具有直接span子级的div标签:

div:has(> span) {color: red;}

正如:has的词汇表所建议的,它不仅限于父选择。

例如,下面我们可以选择span,其中:has是兄弟姐妹div

span:has(+ div) {color: red;}

甚至,通过使用: not()选择器选择一个没有子元素的元素。

例如,下面将选择任何没有p子级的div:

div:not(:has(p)) {color: red;}

选择CSS中仅包含文本的元素

CSS中一个非常常见的问题是:empty标记不选择包含任何文本的元素-因此有时一个元素可以包含一个空格,而:empty将不适用。:has选择器使我们能够选择仅包含文本节点而不包含其他子元素的元素。

虽然这不是简单的:empty元素与空格的完美解决方案(因为这将选择任何元素只有文本,没有额外的超文本标记语言DOM元素)-它确实使我们能够选择DOM元素只有文本节点,这是以前不可能的。

div:not(:has(*)) {background: green;}