gpt4 book ai didi

css - 如何使用CSS根据页面中另一个元素的状态选择一个元素?

转载 作者:行者123 更新时间:2023-12-02 12:23:24 25 4
gpt4 key购买 nike

我具有可以反射(reflect)不同状态的元素,这些元素可以由用户触发(: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仅具有相同的父吗?

最佳答案

规范问题的一般答案

How do I select an element based on the state of another element in the page with CSS?



取决于三个条件:
  • 是否可以使用简单的选择器
  • 表示这些元素的状态
  • 是否可以使用组合器来形成单个复杂选择器来表达这两个元素之间的结构关系,以及
  • 是否可以将要定位的元素作为结果复杂选择器的主题。

  • 尽管 current Selectors standard具有一些有趣的功能,有时还可能具有强大的功能,但它的设计方式使其在#2区域极为受限制(直接带来了#3的后果)。其中一些有限的可能性在其他答案中得到了列举,例如通过对子级和同级组合器的最基本使用, clever use of dynamic pseudo-classes(实际上与条件#1有关)或 a combination of both

    另一方面,由于这个原因,无法使用选择器中当前可用的方法解决问题中给出的问题。多数情况归结为缺少父选择器和/或 previous sibling 选择器,这两者似乎都是微不足道的功能,但具有某些隐含含义,使它们难以良好定义或实现。综上所述:
  • 是的,可以使用简单的选择器来表示这些元素的状态:前者为div[data-status~=finished],后两者为.blink.spin
  • 第一个元素可以由section > div[data-status~=finished]表示,两个主题元素可以分别由section + section > .blinksection + section > .spin表示。问题在于,不可能编写包含所有这些结构的复杂选择器,因为组合器是单向的,并且子组合器没有父级对应项,无法在第一个section元素处将它们联接。
  • 假设前两个问题的答案也是"is",则.blink.spin中的每一个都可以成为其自己的复杂选择器的主题。 (但在下一节中会对此进行更多介绍。)

  • 如果您直接针对此问题,则由于上述限制,您可能想解决的问题就像上面给出的那样,无法使用选择器解决。

    upcoming standard具有一些新功能,这些功能将极大地丰富选择器语法,并有可能将其(和CSS)开放给许多新的可能性,包括可能解决示例问题的方法。以下各节将介绍所有这些内容,但首先我将解释每个条件的含义以及它与给定示例的关系:

    元素状态以及元素之间的结构关系

    选择器的定义特征是它表示文档树中一个或多个元素的某种结构。这不仅仅是我的工作-您实际上可以在 informative overview of the Selectors standard中找到此描述:

    A Selector represents a structure. This structure can be used as a condition (e.g. in a CSS rule) that determines which elements a selector matches in the document tree, or as a flat description of the HTML or XML fragment corresponding to that structure.

    Selectors may range from simple element names to rich contextual representations.



    每个元素由一个或多个简单选择器的序列表示。该序列称为复合选择器(我在这里使用选择器4中的术语,因为它比选择器3中使用的术语更清楚-有关术语的非详尽列表,请参见 this answer)。

    每个简单的选择器代表一个元素的某个状态。有简单的选择器,用于匹配元素的类型(或标签名称),类名称,ID或任意属性。还有一些伪类,它们代表抽象和其他未在文档树中直接表示的特殊状态,例如元素在其层次结构中的顺序和位置( :nth-child():nth-of-type()),用户交互( :hover:active:focus:checked) ),超链接( :link:visited)的访问量等等。

    在给定的示例中,可以使用类型选择器和属性选择器来表示具有 div属性且其空格分隔值包含 data-statusfinished元素:
    div[data-status~=finished]

    如果您希望选择器仅在指针悬停于此元素上时应用,则只需抛出 :hover伪类:
    div[data-status~=finished]:hover

    复合选择器通过组合器链接以形成复杂的选择器。您可能熟悉的这些组合符 >+~符号表示每个复合选择器表示的元素之间的关系。仅使用这两个工具,您就已经可以创建一些非常有趣的结果,如此处其他答案所示。我在 this answer中进一步解释了这些基础知识。

    在给定的示例中,可以建立以下结构关系:
  • 第一个section元素是div[data-status~=finished]的父元素。这是使用child combinator > 表示的:
    section > div[data-status~=finished]
  • 第二个section紧跟着第一个
  • 。这是使用adjacent sibling combinator + 表示的:
    section + section
  • 此外,第二个section.blink.spin的父级。可以使用两个选择器来表示,每个选择器一个:
    section + section > .blink, 
    section + section > .spin

    为什么需要两个选择器?在这种情况下,主要是因为subgrouping two compound selectors into one目前没有语法,因此您必须分别表示每个子元素。即将推出的Selectors 4标准引入了:matches()伪类,它将提供此非常分组的功能:
    section + section > :matches(.blink, .spin)

  • 现在,由于复杂选择器中的每个复合选择器都代表一个元素,因此 section + section代表两个同级元素, section > div代表父级和子级, section + section > div代表下一个兄弟级的子级,您会认为父级组合器和先前的同级组合器是非常多余的。那么为什么我们通常会遇到以下问题:
  • Is there a CSS parent selector?
  • Is there a "previous sibling" CSS selector?

  • 而且,更重要的是,为什么这两个问题的答案都是 而不是?在下一点中将解决原因:

    选择器的主题

    选择器的 subject始终由最右边的复合选择器表示。例如,选择器 section + section > div代表三个元素,其中 div是主题。您可能会说 div是被选择的或针对性的,就像在问题中一样,但是如果您曾经想知道是否有一个合适的术语,则将其称为选择器的主题。

    在CSS规则中,将样式应用于选择器主题表示的元素。适当时,任何子框和伪元素框都将从该元素继承样式。 (如果选择器的主题包含伪元素,则是异常(exception),在这种情况下,样式仅直接应用于伪元素。)

    从上一节中的选择器中,我们有以下内容:
  • 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一直在做的事情。

    这使我们从原始问题中得出以下结论:

    Is there a CSS selector that would let me specify which elements should get selected based on target element state?



    答案是否定的,并将保持不变。但是,在选择器4的早期草稿中(从 FPWDthe latest working draft from May 2013),提出了一项新功能的建议,该功能可以让您选择除最右边的复合选择器之外的任何复合选择器,并将其指定为选择器。

    潜在的解决方案

    但是,最近删除了主题指示符,而使用了 :has()伪类(即 adopted from jQuery)。我推测可能是 here的原因:

    The reason :has() is more versatile is because, with the subject selector, it was never made clear in any draft if a single complex selector could have more than one subject selector (since a single complex selector can only ever have one subject) and/or if functional pseudo-classes such as :matches() accepted the subject selector. But because a pseudo-class is a simple selector, you know that :has() can be accepted anywhere a pseudo-class is accepted.



    因此,虽然您不能更改选择器的主题,但是 :has()由于具有伪类性质,因此可以完全取消这样做的需要。最好的部分是,它可以执行此操作,然后执行某些操作,而这些操作都没有从根本上改变选择器语法。

    实际上,可以使用选择器4的 :has()解决示例问题:
    /* Combined with the :matches() example from above */
    section:has(> div[data-status~=finished]) + section > div:matches(.blink, .spin)

    注意使用子组合器:这会将相对选择器参数的范围限定为第一个 section的子组合。是的,这是全世界的Web开发人员多年来一直想要的难以捉摸的“父选择器”。

    而且因为 :has()来自jQuery,所以您现在可以使用它,尽管 :matches()尚不存在,所以您必须同时用对 .filter()的调用来替换它:

    $('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()都尚未实现的原因。后两个特别有问题,因为“最右边的复合选择器”定义 serves as the basis of mainstream CSS selector engines,这两个功能试图完全挑战它。

    这也是为什么 :has()暂时从 fast profile中排除,因此可能无法在CSS中使用的原因,因为它需要在页面渲染期间进行实时选择器匹配,这无疑对性能至关重要。但是,仍然可以通过DOM方法 querySelector() querySelectorAll() matches() (以及碰巧使用它们的所有选择器库)进行访问。

    也就是说,CSSWG具有 plans来测试 :has()的有限变体(例如,使用单个子组合器或同级组合器),以查看它们是否可以很好地实现以包含在CSS中,这将满足绝大多数用例,包括上面的第一个例子。

    结论

    不幸的是,今天的CSS选择器语法仍然非常有限。但是,该标准的新提议将带来强大的新可能性,其中的一些补充是基于选择器库(如jQuery已经提供)的功能。希望这些实现能够支持这些在CSS中使用的新功能。

    关于css - 如何使用CSS根据页面中另一个元素的状态选择一个元素?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28708741/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com