3

I'm looking for a technical explanation, not a solution. If I have, for example, the following structure of HTML:

<div class="container">
    <div class="box1">
        <div class="square"></div>
    </div>
    <div class="box2">
        <div class="circle"></div>
    </div>
</div>

Why can't I create a CSS rule where if I hover over .square, change the background color of .circle? In other words, why can't I affect an element outside of another element's scope?

Also, will there be a time when we can do this? Are there any future plans to allow this behavior?

j08691
  • 204,283
  • 31
  • 260
  • 272
user4913694
  • 466
  • 1
  • 8
  • 19
  • 1
    this might help: http://stackoverflow.com/questions/6910049/on-a-css-hover-event-can-i-change-another-divs-styling – Dan Beaulieu Jun 19 '15 at 20:40
  • @DanBeaulieu Again, I'm not looking for a solution. I'm looking for a technical explanation. – user4913694 Jun 19 '15 at 20:42
  • 2
    Notice. That's why I posted this in the comments section and not the answers section. – Dan Beaulieu Jun 19 '15 at 20:43
  • 1
    I believe you're getting down votes because there's already a lot of content on the web about this. In my answer I link to a website which was the first result from google. – jaunt Jun 19 '15 at 20:53
  • 1
    Does [this](http://stackoverflow.com/questions/28708741/how-do-i-select-an-element-based-on-the-state-of-another-element-in-the-page-wit) offer the technical explanation you're looking for? It is quite a long read, though, I apologize for that. It does take quite a bit of background info to understand why, but you'll probably get it as it ties with the concept of scope. In fact, I think your title is much better than the one I suggested for the linked question, at least, for the "can't" part anyway. – BoltClock Jun 20 '15 at 01:43

4 Answers4

2

As you point out, there is currently no way to select the parent of an element in CSS2/CSS3 spec.

Answer:

Its just not in the spec namely for present performance considerations and the way that specificity works in CSS.

It is in neither of the current CSS selectors specs:

In the meantime you'll have to resort to JavaScript if you need to select a parent element.

The Selectors Level 4 Working Draft includes a :has() pseudo-class that works the same as the jQuery implementation. As of 2015, this is not available in any browser.

Example has()

container:has(> a.active) { /* styles to apply to the container tag */ }
BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
ѺȐeallү
  • 2,887
  • 3
  • 22
  • 34
  • This doesn't have anything to do with specificity. There is no reason a hypothetical parent combinator - or `:has()` as is currently specced - would have any specificity issues. – BoltClock Jun 20 '15 at 01:47
  • (The spec currently does not define the specificity of `:has()`, but most likely it'll simply be the most specific argument that matches, just like `:matches()` and `:not()`.) – BoltClock Jun 20 '15 at 01:58
0

This website explains why we can't have a parent selector - which is what would be required in order to select a tag inside another scope.

From my knowledge, the reason is not that we can't have it, but simply because the performance demand is too great.

It could be done - but compatibility would be god awful to say the least. So why bother implementing that will hardly be supported when you'll need an alternative anyway? It's just easier to use JavaScript or other client side languages.

jaunt
  • 4,978
  • 4
  • 33
  • 54
  • "compatibility would be god awful to say the least" It can only get better, though, once it is implemented. Just look at all the new features being implemented every day in spite of existing, tried and tested JavaScript-based solutions. – BoltClock Jun 20 '15 at 01:48
  • Very true. But the point still stands that older browsers do not have the framework to support these newer features. So even if, by some miracle we eventually get it to work on all browser versions, we would still need alternatives during the implementation period - and let's be honest, that's a bit of a bummer. – jaunt Jun 20 '15 at 22:41
0

Well, it is for curiosity. Well, the :has() is the best approach, it is the future, for sure. But in different scenarios you have differents creative possibilities.

For example, in the context that I propose to you, the elements are positioning with absolute. And we now the distance between the elemetns.

We can use the pseudo-element after or before and put in top of the other. Now you can use :hover.

http://codepen.io/luarmr/pen/jPGYoM

CSS

/*Normal css*/

[class^='box']{
  position: absolute;
  top:10px;
  border:1px solid #fabada;
}

[class^='box']:hover{
  background: #0da;
}

.box1{
  left:10px;
}

.box2{
  left:240px;
}

.square, .circle{
  margin:10px;
  height:100px;
  width:100px;
  background:#fe0;
}

.circle{
  border-radius:50%;
}


/*TRICK*/

[class^='box']:after{
  content:'';
  position:absolute;
  height:100%;
  width:100%;
  top:0;
  z-index:1;
}

.box1:after{
  left:230px;∑
}

.box2:after{
  left:-230px;
}
Raúl Martín
  • 4,471
  • 3
  • 23
  • 42
0

While you cannot target parents in CSS selectors (as ѺȐeallү pointed out), you can still style siblings. So, you can style some elements which are not hovered:

.square {
    display: inline-block;
    width: 50px;
    height: 50px;
    background: none #4679BD;
}
.circle {
    display: inline-block;
    width: 50px;
    height: 50px;
    background: none #FFB900;
    border-radius: 50%;
}
.triangle {
    display: inline-block;
    width: 0;
    height: 0;
    border-top: 25px solid transparent;
    border-bottom: 25px solid transparent;
    border-left: 50px solid green;
}
.square:hover ~ .circle {
    background: none #118889;
}
.square:hover ~ .triangle {
    border-left: 50px solid #4D4D4D;
}
.circle:hover + * {
 border-left: 50px solid lime;
}
<div class="container">
        <div class="square"></div>
        <div class="circle"></div>
        <div class="triangle"></div>
</div>

Same method is used in this pure css slide toggle example.

Community
  • 1
  • 1
skobaljic
  • 9,379
  • 1
  • 25
  • 51