9

In CSS is it possible to select all elements before an element with a given class?

Example HTML:

<div>
    <a href>One</a>
    <a href>Two</a>
    <a href>Three</a>
    <a href class="active">Four</a>
    <a href>Five</a>
</div>

And CSS:

.active:(all-before) {
    border-left: solid 1px #C0FFEE;
}

So links 'One', 'Two', and 'Three' would would have a left border but 'Four' and 'Five' would not.

saricden
  • 2,084
  • 4
  • 29
  • 40

5 Answers5

13

a {
  text-decoration: none;
  border-left: 1px solid black;
}

a.active, a.active ~ * {
  border: none;
}
<div>
    <a href>One</a>
    <a href>Two</a>
    <a href>Three</a>
    <a href class="active">Four</a>
    <a href>Five</a>
</div>
Chris Burton
  • 1,195
  • 6
  • 19
  • 54
4

Okay. What is really going to work is the use of flex-direction in combination with the ~ selector.

.container {
  display: flex;
  /* could also be column-reverse*/
  flex-direction: row-reverse;
  justify-content: flex-end;
}

.item {
  /* just styling */
  margin: 0 8px;
  border: 1px solid gray;
  border-radius: 3px;
  padding: 4px 8px;
  transition: all .1s ease-in-out;
}

/* we are still selecting every element after according to HTML
 * but as they have reversed order, we're applying styles to all
 * elements that were rendered before */
.item:hover ~ .item {
  color: coral;
  border-color: coral;
}
<div class="container">
  <!-- notice how children are ordered in reverse direction -->
  <div class="item">Third</div>
  <div class="item">Second</div>
  <div class="item">First</div>
</div>
3

A much easy solution, first select the </a> element with class .active and the </a> elements after it using using .active ~ a, .active, then just put it inside the :not() pseudo-class on </a> tag, a:not(.active ~ a, .active) this will select all </a> elements except the ones with the class .active and the </a> elements the come after it.

a {
  text-decoration: none;
  color: black;
}

a:not(.active ~ a, .active) {
  border-left: 1px solid red
}
<div>
  <a href>One</a>
  <a href>Two</a>
  <a href>Three</a>
  <a href class="active">Four</a>
  <a href>Five</a>
</div>
2

Baraa Al-Tabbaa's answer has a drawback that all other elements' value will be set to none.

To avoid this, you can use multiple :not selectors, so the rest of the elements can still inherent properties from the parent.

a:not(a.active ~ a):not(a.active) {
  border-left: solid 5px #C0FFEE;
}
<div>
    <a href>One</a>
    <a href>Two</a>
    <a href>Three</a>
    <a href class="active">Four</a>
    <a href>Five</a>
</div>
toaruScar
  • 401
  • 4
  • 6
1

Well, Normally it's not possible, but you can hack it someway.

So for example if you want to do this:

.active:(all-before) {
    border-left: solid 1px #C0FFEE;
}

then you can do this:

a {
    border-left: solid 1px #C0FFEE;
}
a.active, a.active~a {
    border-left: none;
}

So you put the style you want in the first selector, and then you disable that design in the second selector.

Working example: http://jsfiddle.net/prrd14u2/

Also you can use javascript, jquery as another solution.

Baraa Al-Tabbaa
  • 753
  • 5
  • 11