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

后端 未结 3 908
醉梦人生
醉梦人生 2020-11-22 15:19

I have elements that can reflect different states, either triggered by the user (:hover, :focus, etc.) or manipulated by the server (data-sta

3条回答
  •  栀梦
    栀梦 (楼主)
    2020-11-22 16:19

    You are very limited on what you can achieve with the current state of CSS.

    In short - you can make CSS elements react to a state change of an element, if they have the same parent AND are siblings, or the parent's children.


    The state of an element in CSS is handled by pseudo-classes, which cover most of the typical interactions that a browser handles based on user input.

    While this enables you to handle the visual look of the current state of an element and its children in the DOM tree, you still can't make other non-child elements react (with a visual change of style) to the current state of your element, since CSS does not offer a specific type of selector to do that in a flexible way.

    You can, however, combine the pseudo-classes with other types of CSS selectors and make this work in certain situations (I will use the hover state since it's the most obvious):

    pseudo class + adjacent sibling selector

    Adjacent sibling selector matches if element1 and element2 share the same parent in the document tree and element1 immediately precedes element2. (W3C specification of Adjacent sibling selectors)

    div:hover + div {
        background:red;
    }
    Hover on elements:
    
    Element 1
    Element 2
    Element 3
    Element 4
    Element 5

    Pseudo class + General sibling combinator

    This combination works the same as the adjacent sibling selector, except that the element being selected doesn't need to immediately succeed the first element; it can appear anywhere after it.

    div:hover ~ div {
        background:red;
    }
    Element 1
    Element 2
    Element 3
    Element 4
    Element 5

    Attribute selector + General sibling combinator / Attribute selector + adjacent sibling selector

    States of DOM elements are often stored in data attributes. CSS offers you an attribute selector, which lets you apply style based on the value of an attribute.

    The following example sets a lower opacity to all elements following the element with a status of »finished«:

    div[data-status~=finished] ~ div {
        opacity: 0.3;
    }
    Element 1
    Element 2
    Element 3
    Element 4
    Element 5

    :not()

    In certain cases, :not() could help you select all other elements that don't have the state in question active, however, non-simple selectors are not yet supported in CSS3 in :not(), though they are proposed in the new draft Selectors Level 4 draft. So currently, you can not do div:not(.class, .class) – since only simple selectors are supported ( type selector, universal selector, attribute selector, class selector, ID selector, or pseudo-class).


    In the end you can build some complex selectors that may achieve what you want to do, but are usually pretty static, and will probably stop working as soon as the DOM structure changes, but for corner cases you may solve the problem. MDN's pseudo selector list can be handy when combining them.

    Unfortunately, at the moment of writing this, you will still have to handle it outside CSS for a solid solution.

提交回复
热议问题