如何使用CSS根据页面中另一个元素的状态选择一个元素?
我有能够反映不同的状态,由用户(触发元件:hover
,:focus
等)或由所述服务器(操作data-
status="finished",disabled
等等)。
我可以定位状态已更改的元素,但似乎找不到基于所讨论元素的状态定位DOM中其他元素的方法。
例:
<section> <div>Element 1</div>
<div data-status="finished">Element 2</div>
<div>Element 3</div>
</section>
<section>
<div>Element 4</div>
<div class="blink">Element 5</div>
<div>Element 4</div>
<div>Element 4</div>
<div class="spin">Element 4</div>
...
</section>
或者只是在服务器端使用适当的样式呈现元素。
是否有CSS选择器可让我指定应根据目标元素的状态选择哪些元素?
就像是:
div[data-status~=finished]:affect(.blink, .spin)
那将允许我也将 与CSS ?
回答:
规范问题的一般答案
如何使用CSS根据页面中另一个元素的状态选择一个元素?
取决于三个条件:
- 是否可以使用简单的选择器来表示这些元素的状态,
- 是否可以使用组合器来形成 单个复杂选择器 来表达这两个元素之间的结构关系,以及
- 是否可以将要定位的元素作为结果复杂选择器的主题。
尽管当前的Selectors标准具有一些有趣的功能,有时甚至可能具有强大的功能,但其设计方式使其在#2区域极为受限制(直接带来了#3的后果)。在其他答案中列举了其中一些有限的可能性,例如,通过最基本的使用子级和同级组合器,[聪明地使用动态伪类(实际上与条件#1相关)或两者结合。
另一方面,由于这个原因,无法使用选择器中当前可用的方法解决问题中给出的问题。多数情况归结为缺少父选择器和/或先前的兄弟选择器,这两者似乎都是琐碎的功能,但具有某些隐含含义,使它们难以良好定义或实现。综上所述:
是的,可以使用简单的选择器来表示这些元素的状态:
div
和[data-status~=finished]
用于前者,.blink
以及.spin
用于后两者。第一个元素可以用表示
section > div[data-status~=finished]
,而两个主题元素可以分别用section + section > .blink
和表示section + section > .spin
。问题在于,不可能编写包含所有这些结构的复杂选择器,因为组合器是单向的,并且子组合器没有父级对应项可以在第一个section
元素处将它们连接起来。假设回答前两个问题也是“是”,每个的
.blink
和.spin
可以做了它的主题 本身 复杂的选择。(但在下一节中会对此进行更多介绍。)
如果您已被引导解决此问题,则由于上述限制,选择器可能无法解决上述问题,就像上面给出的那样。
在即将到来的标准拥有一些新的功能,这将大大丰富选择语法和潜在打开它(CSS)达到新的可能性,其中包括一个可能的解决方案,以例题的主机。以下各节将介绍所有这些内容,但首先我将解释每个条件的含义以及它与给定示例的关系:
元素状态以及元素之间的结构关系
选择器的定义特征是它表示文档树中一个或多个元素的某种结构。这不仅仅是我的工作-您实际上可以在Selectors标准的内容丰富的概述中找到此描述:
选择器代表结构。该结构可用作确定选择器在文档树中匹配哪些元素的条件(例如,在CSS规则中),或用作与该结构相对应的HTML或XML片段的平面描述。
选择器的范围从简单的元素名称到丰富的上下文表示。
每个元素由一个或多个简单选择器的序列表示。该序列称为复合选择器(我在这里使用选择器4中的术语,因为它比选择器3中使用的术语更清楚-
每个简单的选择器代表一个元素的某个状态。有一些简单的选择器可用于匹配元素的类型(或标签名称),类名称,ID或任意属性。也有伪类,其表示抽象等特殊状态下的文档树内不直接表示,诸如在它的层次结构中的顺序和元件的位置(:nth-child()
,:nth-of-type()
),用户交互(:hover
,:active
,:focus
,:checked
),一个的visitedness超链接(:link
,:visited
)等。
在给定的示例中,可以使用类型选择器和属性选择器来表示具有以空格分隔的值div
的data-status
属性的元素finished
:
div[data-status~=finished]
如果希望选择器仅在指针悬停于此元素上时应用,则只需抛出一个:hover
伪类:
div[data-status~=finished]:hover
复合选择器通过组合器链接以形成复杂的选择器。这些组合子的>
,+
和~
符号,你可能熟悉,表达由每种化合物选择所表示的元素之间的关系。仅使用这两个工具,您就已经可以创建一些非常有趣的结果,如此处其他答案所示。更深入地解释这些基础知识。
在给定的示例中,可以建立以下结构关系:
第一个
section
元素是的父元素div[data-status~=finished]
。这是通过子组合>
器表示的:section > div[data-status~=finished]
第二个
section
紧随其后的是第一个。这是使用相邻的同级组合器表示的+
:section + section
另外,第二
section
是两者的亲.blink
和.spin
。可以使用两个选择器来表示,每个选择器一个:section + section > .blink,
section + section > .spin
为什么需要两个选择器?在这种情况下,主要是因为当前没有将两个复合选择器分组为一个的语法,因此您必须分别表示每个子元素。即将推出的Selectors4标准引入了一个:matches()
伪类,它将提供此子分组功能:
section + section > :matches(.blink, .spin)
现在,由于复杂选择器中的每个复合选择器都代表一个元素,因此section + section
代表两个同级元素,section >
div代表父级和子级,并section+section>div
代表下一个兄弟级的子级,因此您会认为父级组合器和前级组合器同级组合器是非常多余的。
而且,更重要的是,为什么对这两个问题的回答都 ?原因在下一点中得到解决:
选择器的主题
选择器的主题始终由最右边的复合选择器表示。例如,选择器section
+ section > div代表三个元素,其中三个div
是主题。你可能会说div
是 选择 ,还是 有针对性的
,如问题,但如果你是否有一个适当的期限曾经想知道,它被称为选择的主题。
在CSS规则中,样式应用于选择器主题所表示的元素。适当时,任何子框和伪元素框都将从该元素继承样式。(例外情况是,如果选择器的主题包括伪元素,则在这种情况下,样式仅直接应用于伪元素。)
从上一节中的选择器中,我们有以下内容:
- 的主题
section > div[data-status~=finished]
是div[data-status~=finished]
。 - 的主题
section + section
是 第二个section
选择器。 - 的主题分别
section + section > .blink, section + section > .spin
是.blink
和.spin
。 - 使用
:matches()
的主题section + section > :matches(.blink, .spin)
是:matches(.blink, .spin)
。
因此,似乎我们确实需要一个父选择器或一个前一个兄弟选择器。但是请记住,选择器已经可以表示复杂的结构。寻找一个更灵活的解决方案而不是简单地添加与现有组合器相反的新组合器,这正是CSSWG一直在做的事情。
这使我们从原始问题中得出以下结论:
是否有CSS选择器可让我指定应根据目标元素状态选择哪些元素?
答案是否定的,并将保持不变。但是,在选择器4的较早草案(从FPWD到2013年5月的最新工作草案)中,提出了一项新功能的建议,该功能使您可以选择除最右边的选择器以外的任何复合选择器,并指定作为选择器的主题。
潜在的解决方案
但是,最近删除了主题指示符,转而使用:has()
伪类(该伪类又从jQuery中采用。推测一个可能的原因:
:has()
用途更广泛的原因是,对于主题选择器,从未在任何草稿中明确指出单个复杂选择器可以具有多个主题选择器(因为单个复杂选择器只能具有一个主题)和/或功能性伪类,例如:matches()
接受主题选择器。但是因为伪类是一个简单的选择器,所以您知道:has()
在接受伪类的任何地方都可以接受伪类。
因此,尽管您不能更改选择器的主题:has()
,但由于其伪类的性质,它会完全取消这样做的需要。最好的部分是,它可以执行此操作 ,然后执行某些操作,而这些操作都没有从根本上改变选择器语法。
实际上,示例问题 可以 使用选择器4 解决:has()
:
/* Combined with the :matches() example from above */section:has(> div[data-status~=finished]) + section > div:matches(.blink, .spin)
注意使用子组合器:这会将相对选择器参数的范围限定为first的子组合section
。是的,这是全世界的Web开发人员多年来一直想要的难以捉摸的“父选择器”。
由于:has()
来自jQuery,因此您 今天
可以使用,尽管:matches()
它尚不存在,所以.filter()
在此期间您必须将其替换为to :
$('section:has(> div[data-status~=finished]) + section > div') .filter('.blink, .spin')
.css('color', 'red');
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<section>
<div>Element 1</div>
<div data-status="finished">Element 2</div>
<div>Element 3</div>
</section>
<section>
<div>Element 4</div>
<div class="blink">Element 5</div>
<div>Element 4</div>
<div>Element 4</div>
<div class="spin">Element 4</div>
...
</section>
它是如此通用,它不仅使您可以“定位没有相同父元素的元素”,而且还可以使那些完全不相关的元素,包括其在文档树中的位置可能彼此无关的元素。这将 有效地消除
上面的条件2,尽管这样做会带来很大的警告,我将在下一秒钟进行说明。例如,如果我们假设所讨论的div
元素可能出现在彼此之间没有结构关系的任何位置,则:has()
可以执行以下操作:
:root:has(div[data-status~=finished]) div:matches(.blink, .spin)
…查找div.blink, div.spin
何时 在文档树中的任何地方div[data-status~=finished]
存在,因为
文档树中的 任何元素都必须是文档根元素的后代。
现在,我提到的警告是,使用带有的任意复杂选择器:has()
可能会对性能产生严重影响,这就是为什么在很长一段时间内从未实现父选择器,而主题指示符和:has()
尚未实现的原因。后两个特别有问题,因为“最右边的复合选择器”定义用作主流CSS选择器引擎的基础,并且这两个功能试图完全挑战它。
这也是为什么:has()
暂时将其排除在快速配置文件之外,因此可能无法在CSS中使用的原因,因为它要求在页面渲染期间进行实时选择器匹配,这无疑对性能至关重要。它仍然会通过DOM方法访问querySelector()
,querySelectorAll()
(和发生在使用它们的任何选择库),但是。
这就是说,CSSWG有计划,以测试有限的变化:has()
(例如,使用一个子组合子或兄弟姐妹组合子),看看他们是否可以实现不够好,包括在CSS,这将满足广大大多数的使用案例, 其中包括了上面的第一个例子。
结论
不幸的是,今天的CSS选择器语法仍然非常有限。但是,该标准的新提议将带来强大的新可能性,其中的一些附加功能是基于选择器库(例如jQuery)已经提供的功能。希望这些实现能够支持这些在CSS中使用的新功能。
以上是 如何使用CSS根据页面中另一个元素的状态选择一个元素? 的全部内容, 来源链接: utcz.com/qa/421616.html