[css] Is there a "previous sibling" selector?

The plus sign (+) is for the next sibling.

Is there an equivalent for the previous sibling?

This question is related to css css-selectors

The answer is


If you know the exact position an :nth-child()-based exclusion of all following siblings would work.

ul li:not(:nth-child(n+3))

Which would select all lis before the 3rd (e.g. 1st and 2nd). But, in my opinion this looks ugly and has a very tight usecase.

You also could select the nth-child right-to-left:

ul li:nth-child(-n+2)

Which does the same.


Removing the styles of next siblings on hover, so that it looks like only previous siblings have styles added on hover.

_x000D_
_x000D_
ul li {
  color: red;
  cursor: pointer;
}

ul:hover li {
  color: blue;
}

ul:hover li:hover ~ li{
  color: red;
}
_x000D_
<ul>
    <li>item 1</li>
    <li>item 2</li>
    <li>item 3</li>
</ul>
_x000D_
_x000D_
_x000D_


Two tricks. Basically inverting the HTML order of your desired elements in HTML and using
~ Next siblings operator:

float-right + inverse the order of HTML elements

_x000D_
_x000D_
div{ /* Do with the parent whatever you know just to make the_x000D_
  inner float-right elements appear where desired */_x000D_
  display:inline-block;_x000D_
}_x000D_
span{_x000D_
  float:right;  /* float-right the elements! */_x000D_
}_x000D_
span:hover ~ span{ /* On hover target it's "previous";) elements */_x000D_
  background:red;_x000D_
} 
_x000D_
<div>_x000D_
  <!-- Reverse the order of inner elements -->_x000D_
  <span>5</span>_x000D_
  <span>4</span>_x000D_
  <span>3</span>_x000D_
  <span>2</span>_x000D_
  <span>1</span>_x000D_
</div>
_x000D_
_x000D_
_x000D_


Parent with direction: rtl; + inverse the order of inner elements

_x000D_
_x000D_
.inverse{_x000D_
  direction: rtl;_x000D_
  display: inline-block; /* inline-block to keep parent at the left of window */_x000D_
}_x000D_
span:hover ~ span{ /* On hover target it's "previous";) elements */_x000D_
  background:gold;_x000D_
}
_x000D_
Hover one span and see the previous elements being targeted!<br>_x000D_
_x000D_
<div class="inverse">_x000D_
  <!-- Reverse the order of inner elements -->_x000D_
  <span>5</span>_x000D_
  <span>4</span>_x000D_
  <span>3</span>_x000D_
  <span>2</span>_x000D_
  <span>1</span>_x000D_
</div>
_x000D_
_x000D_
_x000D_


Don't think there's a similar answer here so try this. Assuming HTML of:

<ul>
  <li>before</li>
  <li class="target">target</li>
  <li>after</li>
  <li>after</li>
</ul>

Add a style to all the children, then undo the style to the target, and sibling children of your target.

ul > li { color: red; }
ul > li.target, ul > li.target ~ li { color: inherit; }

I had a similar problem and found out that all problem of this nature can be solved as follows:

  1. give all your items a style.
  2. give your selected item a style.
  3. give next items a style using + or ~.

and this way you'll be able to style your current, previous items(all items overridden with current and next items) and your next items.

example:

/* all items (will be styled as previous) */
li {
  color: blue;
}

/* the item i want to distinguish */
li.milk {
  color: red;
}

/* next items */
li ~ li  {
  color: green;
}


<ul>
  <li>Tea</li>
  <li class="milk">Milk</li>
  <li>Juice</li>
  <li>others</li>
</ul>

Hope it helps someone.


I found a way to style all previous siblings (opposite of ~) that may work depending on what you need.

Let's say you have a list of links and when hovering on one, all the previous ones should turn red. You can do it like this:

_x000D_
_x000D_
/* default link color is blue */_x000D_
.parent a {_x000D_
  color: blue;_x000D_
}_x000D_
_x000D_
/* prev siblings should be red */_x000D_
.parent:hover a {_x000D_
  color: red;_x000D_
}_x000D_
.parent a:hover,_x000D_
.parent a:hover ~ a {_x000D_
  color: blue;_x000D_
}
_x000D_
<div class="parent">_x000D_
  <a href="#">link</a>_x000D_
  <a href="#">link</a>_x000D_
  <a href="#">link</a>_x000D_
  <a href="#">link</a>_x000D_
  <a href="#">link</a>_x000D_
</div>
_x000D_
_x000D_
_x000D_


Another flexbox solution

You can use inverse the order of elements in HTML. Then besides using order as in Michael_B's answer you can use flex-direction: row-reverse; or flex-direction: column-reverse; depending on your layout.

Working sample:

_x000D_
_x000D_
.flex {_x000D_
  display: flex;_x000D_
  flex-direction: row-reverse;_x000D_
   /* Align content at the "reversed" end i.e. beginning */_x000D_
  justify-content: flex-end;_x000D_
}_x000D_
_x000D_
/* On hover target its "previous" elements */_x000D_
.flex-item:hover ~ .flex-item {_x000D_
  background-color: lime;_x000D_
}_x000D_
_x000D_
/* styles just for demo */_x000D_
.flex-item {_x000D_
  background-color: orange;_x000D_
  color: white;_x000D_
  padding: 20px;_x000D_
  font-size: 3rem;_x000D_
  border-radius: 50%;_x000D_
}
_x000D_
<div class="flex">_x000D_
  <div class="flex-item">5</div>_x000D_
  <div class="flex-item">4</div>_x000D_
  <div class="flex-item">3</div>_x000D_
  <div class="flex-item">2</div>_x000D_
  <div class="flex-item">1</div>_x000D_
</div>
_x000D_
_x000D_
_x000D_


Selectors level 4 introduces :has() (previously the subject indicator !) which will allow you to select a previous sibling with:

previous:has(+ next) {}

… but at the time of writing, it is some distance beyond the bleeding edge for browser support.


I had the same question, but then I had a "duh" moment. Instead of writing

x ~ y

write

y ~ x

Obviously this matches "x" instead of "y", but it answers the "is there a match?" question, and simple DOM traversal may get you to the right element more efficiently than looping in javascript.

I realize that the original question was a CSS question so this answer is probably completely irrelevant, but other Javascript users may stumble on the question via search like I did.


Depending on your exact objective, there is a way to achieve the usefulness of a parent selector without using one (even if one were to exist)...

Say we have:

<div>
  <ul>
    <li><a>Pants</a></li>
    <li><a>Socks</a></li>
    <ul>
      <li><a>White socks</a></li>
      <li><a>Blue socks</a></li>
    </ul>
  </ul>
</div>

What can we do to make the Socks block (including sock colours) stand out visually using spacing?

What would be nice but doesn't exist:

ul li ul:parent {
  margin-top: 15px;
  margin-bottom: 15px;
}

What does exist:

li > a {
  margin-top: 15px;
  display: block;
}
li > a:only-child {
  margin-top: 0px;
}

This sets all anchor links to have 15px margin on the top and resets it back to 0 for those with no UL elements (or other tags) inside LIs.


+ is for the next sibling. Is there an equivalent for the previous sibling?

You can use the two axe selectors: ! and ?

There are 2 subsequent sibling selectors in conventional CSS:

  • + is the immediate subsequent sibling selector
  • ~ is the any subsequent sibling selector

In conventional CSS, there is no previous sibling selector.

However, in the axe CSS post-processor library, there are 2 previous sibling selectors:

  • ? is the immediate previous sibling selector (opposite of +)
  • ! is the any previous sibling selector (opposite of ~)

Working Example:

In the example below:

  • .any-subsequent:hover ~ div selects any subsequent div
  • .immediate-subsequent:hover + div selects the immediate subsequent div
  • .any-previous:hover ! div selects any previous div
  • .immediate-previous:hover ? div selects the immediate previous div

_x000D_
_x000D_
div {_x000D_
  display: inline-block;_x000D_
  width: 60px;_x000D_
  height: 100px;_x000D_
  color: rgb(255, 255, 255);_x000D_
  background-color: rgb(255, 0, 0);_x000D_
  text-align: center;_x000D_
  vertical-align: top;_x000D_
  cursor: pointer;_x000D_
  opacity: 0;_x000D_
  transition: opacity 0.6s ease-out;_x000D_
}_x000D_
_x000D_
code {_x000D_
  display: block;_x000D_
  margin: 4px;_x000D_
  font-size: 24px;_x000D_
  line-height: 24px;_x000D_
  background-color: rgba(0, 0, 0, 0.5);_x000D_
}_x000D_
_x000D_
div:nth-of-type(-n+4) {_x000D_
  background-color: rgb(0, 0, 255);_x000D_
}_x000D_
_x000D_
div:nth-of-type(n+3):nth-of-type(-n+6) {_x000D_
  opacity: 1;_x000D_
}_x000D_
_x000D_
.any-subsequent:hover ~ div,_x000D_
.immediate-subsequent:hover + div,_x000D_
.any-previous:hover ! div,_x000D_
.immediate-previous:hover ? div {_x000D_
  opacity: 1;_x000D_
}
_x000D_
<h2>Hover over any of the blocks below</h2>_x000D_
_x000D_
<div></div>_x000D_
<div></div>_x000D_
_x000D_
<div class="immediate-previous">Hover for <code>?</code> selector</div>_x000D_
<div class="any-previous">Hover for <code>!</code> selector</div>_x000D_
<div class="any-subsequent">Hover for <code>~</code> selector</div>_x000D_
<div class="immediate-subsequent">Hover for <code>+</code> selector</div>_x000D_
_x000D_
<div></div>_x000D_
<div></div>_x000D_
_x000D_
<script src="https://rouninmedia.github.io/axe/axe.js"></script>
_x000D_
_x000D_
_x000D_


I needed a solution to select the previous sibling tr. I came up with this solution using React and Styled-components. This is not my exact solution (This is from memory, hours later). I know there is a flaw in the setHighlighterRow function.

OnMouseOver a row will set the row index to state, and rerender the previous row with a new background color

class ReactClass extends Component {
  constructor() {
    this.state = {
       highlightRowIndex: null
    }
  }

  setHighlightedRow = (index) => {
    const highlightRowIndex = index === null ? null : index - 1;
    this.setState({highlightRowIndex});
  }

  render() {
    return (
       <Table>
        <Tbody>
           {arr.map((row, index) => {
                const isHighlighted = index === this.state.highlightRowIndex
                return {
                    <Trow 
                        isHighlighted={isHighlighted}
                        onMouseOver={() => this.setHighlightedRow(index)}
                        onMouseOut={() => this.setHighlightedRow(null)}
                        >
                        ...
                    </Trow>
                }
           })}  
        </Tbody>   
       </Table>
    )
  }
}

const Trow = styled.tr`
    & td {
        background-color: ${p => p.isHighlighted ? 'red' : 'white'};
    }

    &:hover {
        background-color: red;
    }
`;

There is no "previous" sibling selector unfortunately, but you can possibly still get the same effect by using positioning (e.g. float right). It depends on what you are trying to do.

In my case, I wanted a primarily CSS 5-star rating system. I would need to color (or swap the icon of) the previous stars. By floating each element right, I am essentially getting the same effect (the html for the stars thus must be written 'backwards').

I'm using FontAwesome in this example and swapping between the unicodes of fa-star-o and fa-star http://fortawesome.github.io/Font-Awesome/

CSS:

.fa {
    display: inline-block;
    font-family: FontAwesome;
    font-style: normal;
    font-weight: normal;
    line-height: 1;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

/* set all stars to 'empty star' */
.stars-container {
    display: inline-block;      
}   

/* set all stars to 'empty star' */
.stars-container .star {
    float: right;
    display: inline-block;
    padding: 2px;
    color: orange;
    cursor: pointer;

}

.stars-container .star:before {
    content: "\f006"; /* fontAwesome empty star code */
}

/* set hovered star to 'filled star' */
.star:hover:before{
    content: "\f005"; /* fontAwesome filled star code */
}

/* set all stars after hovered to'filled star' 
** it will appear that it selects all after due to positioning */
.star:hover ~ .star:before {
    content: "\f005"; /* fontAwesome filled star code */
}

HTML: (40)

JSFiddle: http://jsfiddle.net/andrewleyva/88j0105g/


I had this same problem, while I was trying to change prepend icon fill color on input focus, my code looked something like this:

<template #append>
    <b-input-group-text><strong class="text-danger">!</strong></b-input-group-text>
</template>
<b-form-input id="password_confirmation" v-model="form.password_confirmation" type="password" placeholder="Repeat password" autocomplete="new-password" />

The problem was that I'm using a vue-bootstrap slot to inject the prepend, so even if i change the location still get rendered after the input

Well my solution was to swipe their location, and add custom prepend and used ~ symbol, as css doesn't support previous sibling.

<div class="form-input-prepend">
    <svg-vue icon="common.lock" />
</div>
<b-form-input id="password_confirmation" v-model="form.password_confirmation" type="password" placeholder="Repeat password" autocomplete="new-password" />

Scss style

.form-control:focus ~ .form-input-prepend {
    svg path {
        fill: $accent;
    }
}

So just try to change its position, and if necessary use css order or position: absolute; to achieve what you want, and to avoid using javascript for this kind of needs.


here is the link for a similar question

CSS select all previous siblings for a star rating

So I post my solution using bits of everyones responses and anyone can use it as reference and possibliy recommend improvements.

_x000D_
_x000D_
// Just to check input value
// Consts
const starRadios = document.querySelectorAll('input[name="rating"]');

// EventListeners
starRadios.forEach((radio) => radio.addEventListener('change', getStarRadioValue));

// Get star radio value
function getStarRadioValue(event) { 
    alert(event.target.value) 
    // Do something with it
};
_x000D_
.star-rating {
  font-size: 1.5rem;
  unicode-bidi: bidi-override;
  direction: rtl;
  text-align: left;
}
.star-rating.editable label:hover {
  cursor: pointer;
}
.star-rating.editable .icon-star:hover,
.star-rating.editable .icon-star:hover ~ .icon-star {
  background-color: #fb2727 !important;
}

.icon-star {
  position: relative;
  background-color: #72747d;
  width: 32px;
  height: 32px;
  display: inline-block;
  transition: background-color 0.3s ease;
}
.icon-star.filled {
  background-color: #fb2727;
}

.icon-star > label {
  display: inline-block;
  width: 100%;
  height: 100%;
  left: 0;
  top: 0;
  position: absolute;
}

.icon-star > label > input[type="radio"] {
  position: absolute;
  top: 0;
  left: 0;
  transform: translateY(50%) translateX(50%);
  display: none;
}
_x000D_
<div class="star-rating editable">
  <span class="icon-star">
    <label>
      <input type="radio" name="rating"  value="5" />
    </label>
  </span>
  <span class="icon-star">
    <label>
      <input type="radio" name="rating" value="4" />
    </label>
  </span>
  <span class="icon-star">
    <label>
      <input type="radio" name="rating" value="3" />
    </label>
  </span>
  <span class="icon-star">
    <label>
      <input type="radio" name="rating" value="2" />
    </label>
  </span>
  <span class="icon-star">
    <label>
      <input type="radio" name="rating"  value="1" />
    </label>
  </span>
</div>
_x000D_
_x000D_
_x000D_


No. It is not possible via CSS. It takes the "Cascade" to heart ;-).


However, if you are able to add JavaScript to your page, a little bit of jQuery could get you to your end goal.
You can use jQuery's find to perform a "look-ahead" on your target element/class/id, then backtrack to select your target.
Then you use jQuery to re-write the DOM (CSS) for your element.

Based on this answer by Mike Brant, the following jQuery snippet could help.

$('p + ul').prev('p')

This first selects all <ul>s that immediately follow a <p>.
Then it "backtracks" to select all the previous <p>s from that set of <ul>s.

Effectively, "previous sibling" has been selected via jQuery.
Now, use the .css function to pass in your CSS new values for that element.


In my case I was looking to find a way to select a DIV with the id #full-width, but ONLY if it had a (indirect) descendant DIV with the class of .companies.

I had control of all the HTML under .companies, but could not alter any of the HTML above it.
And the cascade goes only 1 direction: down.

Thus I could select ALL #full-widths.
Or I could select .companies that only followed a #full-width.
But I could not select only #full-widths that proceeded .companies.

And, again, I was unable to add .companies any higher up in the HTML. That part of the HTML was written externally, and wrapped our code.

But with jQuery, I can select the required #full-widths, then assign the appropriate style:

$("#full-width").find(".companies").parents("#full-width").css( "width", "300px" );

This finds all #full-width .companies, and selects just those .companies, similar to how selectors are used to target specific elements in standard in CSS.
Then it uses .parents to "backtrack" and select ALL parents of .companies,
but filters those results to keep only #fill-width elements, so that in the end,
it only selects a #full-width element if it has a .companies class descendant.
Finally, it assigns a new CSS (width) value to the resulting element.

_x000D_
_x000D_
$(".parent").find(".change-parent").parents(".parent").css( "background-color", "darkred");
_x000D_
div {_x000D_
  background-color: lightblue;_x000D_
  width: 120px;_x000D_
  height: 40px;_x000D_
  border: 1px solid gray;_x000D_
  padding: 5px;_x000D_
}_x000D_
.wrapper {_x000D_
  background-color: blue;_x000D_
  width: 250px;_x000D_
  height: 165px;_x000D_
}_x000D_
.parent {_x000D_
  background-color: green;_x000D_
  width: 200px;_x000D_
  height: 70px;_x000D_
}
_x000D_
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>_x000D_
<html>_x000D_
<div class="wrapper">_x000D_
_x000D_
  <div class="parent">_x000D_
    "parent" turns red_x000D_
    <div class="change-parent">_x000D_
    descendant: "change-parent"_x000D_
    </div>_x000D_
  </div>_x000D_
  _x000D_
  <div class="parent">_x000D_
    "parent" stays green_x000D_
    <div class="nope">_x000D_
    descendant: "nope"_x000D_
    </div>_x000D_
  </div>_x000D_
  _x000D_
</div>_x000D_
Target <b>"<span style="color:darkgreen">parent</span>"</b> to turn <span style="color:red">red</span>.<br>_x000D_
<b>Only</b> if it <b>has</b> a descendant of "change-parent".<br>_x000D_
<br>_x000D_
(reverse cascade, look ahead, parent un-descendant)_x000D_
</html>
_x000D_
_x000D_
_x000D_

jQuery Reference Docs:
$() or jQuery(): DOM element.
.find: Get the descendants of each element in the current set of matched elements, filtered by a selector, jQuery object, or element.
.parents: Get the immediately preceding sibling of each element in the set of matched elements. If a selector is provided, it retrieves the previous sibling only if it matches that selector (filters the results to only include the listed elements/selectors).
.css: Set one or more CSS properties for the set of matched elements.


There is no official way to do that at the moment but you can use a little trick to achieve this ! Remember that it is experimental and it has some limitation ... (check this link if you worries about navigator compatibility )

What you can do is use a CSS3 selector : the pseudo classe called nth-child()

_x000D_
_x000D_
#list>* {_x000D_
  display: inline-block;_x000D_
  padding: 20px 28px;_x000D_
  margin-right: 5px;_x000D_
  border: 1px solid #bbb;_x000D_
  background: #ddd;_x000D_
  color: #444;_x000D_
  margin: 0.4em 0;_x000D_
}_x000D_
_x000D_
#list :nth-child(-n+4) {_x000D_
  color: #600b90;_x000D_
  border: 1px dashed red;_x000D_
  background: orange;_x000D_
}
_x000D_
<p>The oranges elements are the previous sibling li selected using li:nth-child(-n+4)</p>_x000D_
_x000D_
<div id="list">_x000D_
  <span>1</span><!-- this will be selected -->_x000D_
  <p>2</p><!-- this will be selected -->_x000D_
  <p>3</p><!-- this will be selected -->_x000D_
  <div>4</div><!-- this will be selected -->_x000D_
  <div>5</div>_x000D_
  <p>6</p>_x000D_
  <p>7</p>_x000D_
  <p>8</p>_x000D_
  <p>9</p>_x000D_
</div>
_x000D_
_x000D_
_x000D_

Limitations

  • You can't select previous elements based on the classes of the next elements
  • This is the same for pseudo classes

You can rearrange the html, set the container to either flex or grid, and also set for each child the "order" property so it will look as you want


You could use double negation

SELECTOR:not([SELECTOR]FILTER):not([SELECTOR]FILTER + SELECTOR) { ... }

Replace SELECTOR with either the TAG or .CLASS ( Using #ID is probably too specific ). Replace FILTER with some other :PSUEDO-SELECTOR (I've only tried :hover) or .CLASS (More for toggling through Javascript).

Since the typical usage will probably rely upon hovering (See example that follows)

/* Effect only limited when hovering */
TAG.CLASS:not(TAG.CLASS:hover):not(TAG.CLASS:hover + TAG.CLASS) {}
/* Effect only applied when hovering */
PARENT.CLASS:hover > CHILD.CLASS:not(CHILD.CLASS:hover):not(CHILD.CLASS:hover + CHILD.CLASS) {}

_x000D_
_x000D_
/* Solution */
div.parent:hover > div.child:not(:hover):not(:hover ~ .child)  {
    background-color:red;
    border-radius:1.5em;
}
div.parent:hover > div.child:not(:hover):not(:hover ~ .child) > div {
    background-color:yellow;
}

/* Make pretty (kinda) */
div.parent {
  width:9em;
  height:9em;
  /* Layout */
  display:grid;
  grid-template-columns : auto auto auto;
  grid-template-rows : auto auto auto;
}
div.child {
  /* Dimensions */
  height:3em;
  width:3em;
  /* Layout */
  position:relative;
  /* Cursor */
  cursor: pointer;
  /* Presentation */
  border: 1px black solid;
  border-radius:1.5em;
}
.star {
  /* Dimensions */
  width: 2.5em;
  height: 2.5em;
  /* Placement */
  position:absolute;
  top: 50%;
  left: 50%;
  transform:translate(-50%,-50%);
  /* Geometry */
  -webkit-clip-path: polygon(
    50% 0%,
    63% 38%,
    100% 38%,
    69% 59%,
    82% 100%,
    50% 75%,
    18% 100%,
    31% 59%,
    0% 38%,
    37% 38%
  );
  clip-path: polygon(
    50% 0%,
    63% 38%,
    100% 38%,
    69% 59%,
    82% 100%,
    50% 75%,
    18% 100%,
    31% 59%,
    0% 38%,
    37% 38%
  );
  /* Presentation */
  background-color: lightgrey;
}
div.child:hover {
    /* Presentation */
    background-color:yellow;
    border-radius:1.5em;
}
div.child:hover > div.star {
    /* Presentation */
    background-color:red;
}
_x000D_
<div class="parent">
  <div class="child" href="#"><div class="star"></div></div>
  <div class="child" href="#"><div class="star"></div></div>
  <div class="child" href="#"><div class="star"></div></div>
  <div class="child" href="#"><div class="star"></div></div>
  <div class="child" href="#"><div class="star"></div></div>
  <div class="child" href="#"><div class="star"></div></div>
  <div class="child" href="#"><div class="star"></div></div>
  <div class="child" href="#"><div class="star"></div></div>
  <div class="child" href="#"><div class="star"></div></div>
 </div>
_x000D_
_x000D_
_x000D_


There isn't, and there is.

If you must place the label before the input, just place the label after the input and keep both the label & the input inside a div, and style the div as following :

_x000D_
_x000D_
.input-box {
  display: flex;
  flex-direction: column-reverse;
}
_x000D_
<div class="input-box">
  <input
   id="email"
   class="form-item"           
   />

   <label for="email" class="form-item-header">                  
   E-Mail*                  
   </label>
</div>
_x000D_
_x000D_
_x000D_

Now you can apply the standard next sibling styling options available in css, and it will appear like you are using a previous sibling styling.


Consider the order property of flex and grid layouts.

I'll focus on flexbox in the examples below, but the same concepts apply to Grid.


With flexbox, a previous sibling selector can be simulated.

In particular, the flex order property can move elements around the screen.

Here's an example:

You want element A to turn red when element B is hovered.

<ul>
    <li>A</li>
    <li>B</li>
</ul>

STEPS

  1. Make the ul a flex container.

    ul { display: flex; }
    

  1. Reverse the order of siblings in the mark-up.

    <ul>
       <li>B</li>
       <li>A</li>
    </ul>
    

  1. Use a sibling selector to target Element A (~ or + will do) .

    li:hover + li { background-color: red; }
    

  1. Use the flex order property to restore the order of siblings on the visual display.

    li:last-child { order: -1; }
    

...and voilà! A previous sibling selector is born (or at least simulated).

Here's the full code:

_x000D_
_x000D_
ul {_x000D_
    display: flex;_x000D_
}_x000D_
_x000D_
li:hover + li {_x000D_
    background-color: red;_x000D_
}_x000D_
_x000D_
li:last-child {_x000D_
    order: -1;_x000D_
}_x000D_
_x000D_
/* non-essential decorative styles */_x000D_
li {_x000D_
    height: 200px;_x000D_
    width: 200px;_x000D_
    background-color: aqua;_x000D_
    margin: 5px;_x000D_
    list-style-type: none;_x000D_
    cursor: pointer;_x000D_
}
_x000D_
<ul>_x000D_
    <li>B</li>_x000D_
    <li>A</li>_x000D_
</ul>
_x000D_
_x000D_
_x000D_

From the flexbox spec:

5.4. Display Order: the order property

Flex items are, by default, displayed and laid out in the same order as they appear in the source document. The order property can be used to change this ordering.

The order property controls the order in which flex items appear within the flex container, by assigning them to ordinal groups. It takes a single <integer> value, which specifies which ordinal group the flex item belongs to.

The initial order value for all flex items is 0.

Also see order in the CSS Grid Layout spec.


Examples of "previous sibling selectors" created with the flex order property.

_x000D_
_x000D_
.container { display: flex; }_x000D_
_x000D_
.box5 { order: 1; }    _x000D_
.box5:hover + .box4 { background-color: orangered; font-size: 1.5em; }_x000D_
_x000D_
.box6 { order: -4; }_x000D_
.box7 { order: -3; }_x000D_
.box8 { order: -2; }_x000D_
.box9 { order: -1; }_x000D_
.box9:hover ~ :not(.box12):nth-child(-1n+5) { background-color: orangered;_x000D_
                                              font-size: 1.5em; }_x000D_
.box12 { order: 2; }_x000D_
.box12:hover ~ :nth-last-child(-1n+2) { background-color: orangered;_x000D_
                                        font-size: 1.5em; }_x000D_
.box21 { order: 1; }_x000D_
.box21:hover ~ .box { background-color: orangered; font-size: 1.5em; }_x000D_
_x000D_
/* non-essential decorative styles */_x000D_
.container {_x000D_
    padding: 5px;_x000D_
    background-color: #888;_x000D_
}_x000D_
.box {_x000D_
    height: 50px;_x000D_
    width: 75px;_x000D_
    margin: 5px;_x000D_
    background-color: lightgreen;_x000D_
    display: flex;_x000D_
    justify-content: center;_x000D_
    align-items: center;_x000D_
    text-align: center;_x000D_
    cursor: pointer;_x000D_
}
_x000D_
<p>_x000D_
Using the flex <code>order</code> property to construct a previous sibling selector_x000D_
</p>_x000D_
_x000D_
<div class="container">_x000D_
    <div class="box box1"><span>1</span></div>_x000D_
    <div class="box box2"><span>2</span></div>_x000D_
    <div class="box box3"><span>3</span></div>_x000D_
    <div class="box box5"><span>HOVER ME</span></div>_x000D_
    <div class="box box4"><span>4</span></div>_x000D_
</div>_x000D_
_x000D_
<br>_x000D_
_x000D_
<div class="container">_x000D_
    <div class="box box9"><span>HOVER ME</span></div>_x000D_
    <div class="box box12"><span>HOVER ME</span></div>_x000D_
    <div class="box box6"><span>6</span></div>_x000D_
    <div class="box box7"><span>7</span></div>_x000D_
    <div class="box box8"><span>8</span></div>_x000D_
    <div class="box box10"><span>10</span></div>_x000D_
    <div class="box box11"><span>11</span></div>_x000D_
</div>_x000D_
_x000D_
<br>_x000D_
_x000D_
<div class="container">_x000D_
    <div class="box box21"><span>HOVER ME</span></div>_x000D_
    <div class="box box13"><span>13</span></div>_x000D_
    <div class="box box14"><span>14</span></div>_x000D_
    <div class="box box15"><span>15</span></div>_x000D_
    <div class="box box16"><span>16</span></div>_x000D_
    <div class="box box17"><span>17</span></div>_x000D_
    <div class="box box18"><span>18</span></div>_x000D_
    <div class="box box19"><span>19</span></div>_x000D_
    <div class="box box20"><span>20</span></div>_x000D_
</div>
_x000D_
_x000D_
_x000D_

jsFiddle


A Side Note – Two Outdated Beliefs about CSS

Flexbox is shattering long-held beliefs about CSS.

One such belief is that a previous sibling selector is not possible in CSS.

To say this belief is widespread would be an understatement. Here's a sampling of related questions on Stack Overflow alone:

As described above, this belief is not entirely true. A previous sibling selector can be simulated in CSS using the flex order property.

The z-index Myth

Another long-standing belief has been that z-index works only on positioned elements.

In fact, the most current version of the spec – the W3C Editor's Draft – still asserts this to be true:

9.9.1 Specifying the stack level: the z-index property

z-index

  • Value: auto | | inherit
  • Initial: auto
  • Applies to: positioned elements
  • Inherited: no
  • Percentages: N/A
  • Media: visual
  • Computed value: as specified

(emphasis added)

In reality, however, this information is obsolete and inaccurate.

Elements that are flex items or grid items can create stacking contexts even when position is static.

4.3. Flex Item Z-Ordering

Flex items paint exactly the same as inline blocks, except that order-modified document order is used in place of raw document order, and z-index values other than auto create a stacking context even if position is static.

5.4. Z-axis Ordering: the z-index property

The painting order of grid items is exactly the same as inline blocks, except that order-modified document order is used in place of raw document order, and z-index values other than auto create a stacking context even if position is static.

Here's a demonstration of z-index working on non-positioned flex items: https://jsfiddle.net/m0wddwxs/