22

I checked the API for some pseudo-selector such as :visible or :hidden, but was disappointed to find no such selector exists. Since jQuery has supported these selectors for a while now, I was hoping they'd be implemented. The idea is, that I'd like to show a certain element only when the element next to it is hidden, but I don't want to use JavaScript to do so. Any options?

GMchris
  • 5,439
  • 4
  • 22
  • 40
  • @dippas Automatic response? I'm asking if CSS offers a certain feature. I can't show any code, because I can't write any code relating to the problem unless I know if such a feature exists. I've already written what I've researched. – GMchris May 12 '16 at 16:15

5 Answers5

33

No, it is not possible and can't be possible, at least in stylesheets.

Otherwise, you could create an infinite loop:

element:visible {
  display: none;
}

The element would be visible at first, then the selector would select it and hide it, then the selector wouldn't apply and it would become visible again, etc.

It would be possible to allow that pseudo-class only in JS APIs like querySelector. But as far as I know there isn't anything like that, and it wouldn't be CSS-only.

Oriol
  • 274,082
  • 63
  • 437
  • 513
  • 1
    I think the phrase "circular logic" is maybe better than "infinite loop", since having tools that can create infinite loops is fine, and this problem is a different sort. – Clayton Rabenda Jan 29 '23 at 10:29
21

It depends on what you mean by "next to it". You can select an element by visibility using attribute-selectors. Or from here:

The CSS attribute selector matches elements based on the presence or value of a given attribute.

To access an element by visibility, you can use for instance the substring matching attribute-selector star [att*=val]. Supposing the style of the div was hidden using visibility: hidden;:

div[style*="hidden"] {

}

Now the question is how do you access the element "next to it". If the element you try to target comes directly after the hidden one (within same parent) use the + selector:

div[style*="hidden"] + span {

}

If it's before, you are out of luck but can look for some work around in the answers to this question: Is there a "previous sibling" CSS selector?

4

CSS, by its nature, cannot have such a selector. At all.

Consider this:

div:not(:hidden) {
  visibility:hidden;
}

That definition above will left the div in undetermined state - nor visible nor hidden - at any given moment of time you cannot say if the div is visible or not.

CSS wittingly prohibits such situations.

jQuery is another story, :visible and :hidden is feasible there for the simple reason: jQuery uses only CSS selector's syntax for its queries. Queries there do not affect style of elements so you can retrieve many things there including final (computed) styles of elements.

c-smile
  • 26,734
  • 7
  • 59
  • 86
2

The functionality you are describing sounds like you could use pure CSS tabs.

The below example was taken from here: https://webdesignerhut.com/create-pure-css-tabs

.tabs {
    max-width: 90%;
    float: none;
    list-style: none;
    padding: 0;
    margin: 75px auto;
    border-bottom: 4px solid #ccc;
}
.tabs:after {
    content: '';
    display: table;
    clear: both;
}
.tabs input[type=radio] {
    display:none;
}
.tabs label {
    display: block;
    float: left;
    width: 33.3333%;
    color: #ccc;
    font-size: 30px;
    font-weight: normal;
    text-decoration: none;
    text-align: center;
    line-height: 2;
    cursor: pointer;
    box-shadow: inset 0 4px #ccc;
    border-bottom: 4px solid #ccc;
    -webkit-transition: all 0.5s; /* Safari 3.1 to 6.0 */
    transition: all 0.5s;
}
.tabs label i {
    padding: 5px;
    margin-right: 0;
}
.tabs label:hover {
    color: #3498db;
    box-shadow: inset 0 4px #3498db;
    border-bottom: 4px solid #3498db;
}
.tab-content {
    display: none;
    width: 100%;
    float: left;
    padding: 15px;
    box-sizing: border-box;
    background-color:#ffffff;
}
.tabs [id^="tab"]:checked + label {
    background: #FFF;
    box-shadow: inset 0 4px #3498db;
    border-bottom: 4px solid #3498db;
    color: #3498db;
}
#tab1:checked ~ #tab-content1,
#tab2:checked ~ #tab-content2,
#tab3:checked ~ #tab-content3 {
    display: block;
}
@media (min-width: 768px) {
    .tabs i {
        padding: 5px;
        margin-right: 10px;
    }
    .tabs label span {
        display: inline-block;
    }
    .tabs {
    max-width: 750px;
    margin: 50px auto;
    }
}
/*Animation*/
.tab-content * {
    -webkit-animation: scale 0.7s ease-in-out;
    -moz-animation: scale 0.7s ease-in-out;
    animation: scale 0.7s ease-in-out;
}
@keyframes scale {
  0% {
    transform: scale(0.9);
    opacity: 0;
    }
  50% {
    transform: scale(1.01);
    opacity: 0.5;
    }
  100% {
    transform: scale(1);
    opacity: 1;
  }
}
<div class="tabs">
    <!-- Radio button and lable for #tab-content1 -->
    <input type="radio" name="tabs" id="tab1" checked >
    <label for="tab1">
        <i class="fa fa-html5"></i><span>Tab 1</span>
    </label>
    <!-- Radio button and lable for #tab-content2 -->
    <input type="radio" name="tabs" id="tab2">
    <label for="tab2">
        <i class="fa fa-css3"></i><span>Tab 2</span>
    </label>
    <!-- Radio button and lable for #tab-content3 -->
    <input type="radio" name="tabs" id="tab3">
    <label for="tab3">
        <i class="fa fa-code"></i><span>Tab 3</span>
    </label>
    <div id="tab-content1" class="tab-content">
        <h3>Tab 1</h3>
        <p>Lorem ipsum dolor sit amet, dignissim magna mauris integer, praesent id ut massa. Metus quis nam laoreet auctor, consectetuer nunc et penatibus nec, consequat torquent sit, vivamus commodo integer sit nec aliquam. Nulla in non, occaecat dui suspendisse, lacus ut consectetuer. Ipsum malesuada, at id, laoreet suspendisse quisque massa, nulla risus convallis mauris enim tellus nulla, in eget molestie eu dolor dolor urna. Molestie malesuada turpis auctor rutrum libero fusce.</p>
    </div>
    <div id="tab-content2" class="tab-content">
        <h3>Tab 2</h3>
        <p>Id neque ut mi condimentum numquam wisi, ut ultricies, tempus dui tellus vehicula nisl per, adipiscing nascetur lacus dolor fringilla. Maecenas purus scelerisque tempus bibendum donec eu, nam quisque mattis, montes consectetuer leo augue amet, magna nam. Wisi vestibulum bibendum. Posuere donec sed ornare arcu, quis donec turpis, nullam urna, sagittis urna pede amet. Lacus nascetur suscipit phasellus diam eget egestas, pulvinar lacus, amet mattis gravida, pede arcu praesent. Diam per felis nunc, interdum facilisi nunc tristique leo libero, amet est velit amet, wisi blandit in a adipiscing, sed mus libero. </p>
    </div>
    <div id="tab-content3" class="tab-content">
        <h3>Tab 3</h3>
        <p>Suspendisse lacus vel et aut id nonummy, libero velit, justo eu, odio phasellus mattis sapien ipsum. Suspendisse volutpat dui non proin egestas, vulputate mauris nunc amet sollicitudin, neque accumsan tincidunt, dolores viverra, aliquet metus. Beatae sed turpis, fusce nec condimentum eu lacus dolor. Elit molestie dapibus felis quisque iaculis, cum quisque lobortis ipsum vitae, lorem et ligula magna, viverra tempus vitae malesuada sapien, nec ullamcorper. Elit proident, turpis penatibus pede placerat mi laoreet augue, nullam nec. Pellentesque donec ut sed quam, fermentum ultrices ante bibendum sit, mollis viverra faucibus vestibulum pretium.</p>
    </div>
</div>
mhatch
  • 4,441
  • 6
  • 36
  • 62
0

You could try .element[style*="display:hidden"] or .element[class*="hide"] (where hide is a class that simply sets display: hidden;). Seemed to work in my setup, but havent tried the edge cases of using it to turn itself off as the above comments point out.

How to use pure css selector to select hidden element

  • Turning this on itself could not create an infinite loop because `[style=...]` selector checks the DOM, specifically style _attribute_ on the HTML elements, which is not affected by CSS at all. CSS like `display: none` affects the _"computed style"_, which does not modify the DOM. – Beni Cherniavsky-Paskin Mar 05 '20 at 14:31