4

I have a script (JsFiddle here) that detects when an li block element is vertically centered on a page and assigns it a .centered class to make it bigger via CSS.

.centered {
    height: 30vh;
    background-color: #bbb;
    -webkit-transition: height 0.6s;
}

Once the central element is identified I manage to select the next sibling to via this:

.centered + li {
    height: 20vh;
    background-color: #ccc;
    -webkit-transition: height 0.6s;
}

The problem arises when I try to select the sibling element preceding the .centered element in pure CSS

After looking at this question from 2011 I tried playing with the :has() pseudo class suggested in one of the comments and other selectors, but with no luck.

This CSS4 relational pseudo class could have done the trick, but is not currently supported:

li:has(+ .centered) {
    height: 20vh;
    background-color: #Fcc;
    -webkit-transition: height 0.6s;
}

I also tried to select the last-of-type of li elements that are not siblings of .centered, but either :not() supports only simple selectors or I'm just not getting how to chain the selectors properly.

Here's the non-working selector:

li:not(.centered ~ li):last-of-type {
    height: 20vh;
    background-color: #Fcc;
    -webkit-transition: height 0.6s;
}

QUESTION: Is there any combination of pseudo classes and selectors that could do the trick in pure CSS?

My hope is that some progress has been made since those questions have been asked.

Community
  • 1
  • 1
HappyTorso
  • 327
  • 1
  • 5
  • 14
  • That `**` font is really distracting. – Roope Aug 23 '15 at 13:54
  • 2
    The answer is no. Just give up and assign a unique class to the preceding `li` in your Javascript routine. – Mr Lister Aug 23 '15 at 14:00
  • 2
    You're trying to go "backwards" in CSS and have one element affect the styling of something that occurs earlier. Can't do that. –  Aug 23 '15 at 16:28
  • @torazaburo thanks for your comment, it made me realise that I could start my jQuery selection from the element preceding the middle one and then select downwards in CSS with `.top + li` and `.top + li + li`. Example: http://jsfiddle.net/3t4r8xy1/1/ – HappyTorso Aug 23 '15 at 18:04

2 Answers2

6

Is there any combination of pseudo classes and selectors that could do the trick in pure CSS?

There isn't; the reason :not(.centered ~ li) doesn't work is indeed that it only currently supports simple selectors — like :has(), :not() will only accept combinators in Selectors 4. Since there are no pseudo-classes that currently accept combinators, and the only available sibling combinators go forward, you are left with a very restricted domain language in this regard. This is why those additions to Selectors were made.

As for progress... progress on the :has() pseudo-class has been eh. Last I heard, the working group was still deciding between allowing a subset of :has() in CSS or separating that out into its own pseudo-class, and vendors were going to see how much of it they could implement in CSS for this to work. But I don't think there has been any data yet.

BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
0

Following the confirmation that it is impossible by @BoltClock and the @torazaburo comment I changed my initial jQuery selection starting element

From this:

        middleElement = this;
        $(this).toggleClass("centered", true);

To this:

        middleElement = this;
        $(this).prev().toggleClass("top", true);

Without adding extra javascript code, I could then change my CSS selectors.

From:

.centered { /*selects the middle element */ 
        height: 30vh;
        background-color: #bbb;
        -webkit-transition: height 0.6s;
    }

.centered + li { /*selects the next sibling after middle element */ 
        height: 20vh;
        background-color: #ccc;
        -webkit-transition: height 0.6s;
    }

li:has(+ .centered){ /*not supported at time of writing*/
        height: 20vh;
        background-color: #Fcc;
        -webkit-transition: height 0.6s;
    }

To:

 .top, .top + li + li { /* selects the siblings before and after the middle one*/
        height: 20vh;
        background-color: #ccc;
        -webkit-transition: height 0.6s;
    }


 .top + li { /* This selects the middle element*/
        height: 30vh;
        background-color: #bbb;
        -webkit-transition: height 0.6s;
    }   

>> JSFiddle

HappyTorso
  • 327
  • 1
  • 5
  • 14