Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to apply CSS styles between two siblings?

Tags:

html

css

To give my question some context, I have 12 sibling divs that each represent a month of the year. Either 0, 1, or 2 of these divs can be selected at a given time. When selected, a class of "active" is applied to that div. When two divs are selected I would like to apply a style to all divs between the two selected.

eg.

<div class="month">Jan</div>
<div class="month active">Feb</div>
<div class="month">Mar</div>
<div class="month">Apr</div>
<div class="month">May</div>
<div class="month">Jun</div>
<div class="month active">Jul</div>
<div class="month">Aug</div>
<div class="month">Sep</div>
<div class="month">Oct</div>
<div class="month">Nov</div>
<div class="month">Dec</div>

So in the above snippet, I would like to apply a CSS style to the active months, as well as all months in-between. Is this possible in CSS, or am I better off with JS?

EDIT:

This doesn't work, but I think it might be on the right track.

.month.active ~ .month {
    background-color: $color-lighter-text;
    color: #fff;
}

.month.active:nth-child(2) ~ .month {
    background-color: #fff !important;
    color: $color-muted-text !important;
}
like image 771
Nicholas Haley Avatar asked Dec 01 '15 20:12

Nicholas Haley


People also ask

How do you target siblings in CSS?

General Sibling Selector (~) The general sibling selector selects all elements that are next siblings of a specified element.

Can we move from sibling to sibling using CSS locator?

No, there is no "previous sibling" selector. On a related note, ~ is for general successor sibling (meaning the element comes after this one, but not necessarily immediately after) and is a CSS3 selector. + is for next sibling and is CSS2.

What is general sibling selector in CSS?

The general sibling selector (~) selects all elements that are next siblings of a specified element.

How do you target a child in CSS?

Definition and UsageThe :nth-child(n) selector matches every element that is the nth child of its parent. n can be a number, a keyword (odd or even), or a formula (like an + b). Tip: Look at the :nth-of-type() selector to select the element that is the nth child, of the same type (tag name), of its parent.


Video Answer


3 Answers

You could select all the .month elements following the first .active element, and then override that styling by selecting all the .month elements that follow the second .active element:

.month.active ~ .month,
.active {
  color: #f00;
}
.month.active ~ .month.active ~ .month {
  color: initial;
}
<div class="month">Jan</div>
<div class="month active">Feb</div>
<div class="month">Mar</div>
<div class="month">Apr</div>
<div class="month">May</div>
<div class="month">Jun</div>
<div class="month active">Jul</div>
<div class="month">Aug</div>
<div class="month">Sep</div>
<div class="month">Oct</div>
<div class="month">Nov</div>
<div class="month">Dec</div>

However, if you want a cleaner solution, I'd suggest using JS and adding an .active class to all the elements that you want to target.

If you're using jQuery, you can simply use the .nextUntil() method:

$('.month.active:first').nextUntil('.active').addClass('active');

$('.month.active:first').nextUntil('.active').addClass('active');
.month.active {
  color: #f00;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="month">Jan</div>
<div class="month active">Feb</div>
<div class="month">Mar</div>
<div class="month">Apr</div>
<div class="month">May</div>
<div class="month">Jun</div>
<div class="month active">Jul</div>
<div class="month">Aug</div>
<div class="month">Sep</div>
<div class="month">Oct</div>
<div class="month">Nov</div>
<div class="month">Dec</div>
like image 101
Josh Crozier Avatar answered Oct 11 '22 17:10

Josh Crozier


You need to use general sibling selectors: ~

<div class="month">Jan</div>
<div class="month active">Feb</div>
<div class="month">Mar</div>
<div class="month">Apr</div>
<div class="month">May</div>
<div class="month">Jun</div>
<div class="month active">Jul</div>
<div class="month">Aug</div>
<div class="month">Sep</div>
<div class="month">Oct</div>
<div class="month">Nov</div>
<div class="month">Dec</div>

.month {background: red;}
.month.active {background: blue;}
.month.active ~ .month {background: blue;}
.month.active ~ .month.active ~ .month {background: red;}
like image 33
aaronburrows Avatar answered Oct 11 '22 17:10

aaronburrows


Because of the cascading nature of CSS, the element before the .active cannot be effectively targeted from .active's reference. I added a .prev class to the element before an .active, then used the adjacent sibling selector + when referencing .active to the element after it.

My bad, you wanted the months in between so that can be done with the more indiscriminate ~. Updated to reflect OP's request but probably the same solution as some before me, sorry :-\

.month.active { 
  background-color: orange;
  }
.month.active ~ .month {
  background-color: orange;
}
.month.active ~ .month.active ~ .month {
  background-color: white;
}
<div class="month">Jan</div>
<div class="month active">Feb</div>
<div class="month">Mar</div>
<div class="month">Apr</div>
<div class="month">May</div>
<div class="month">Jun</div>
<div class="month active">Jul</div>
<div class="month">Aug</div>
<div class="month">Sep</div>
<div class="month">Oct</div>
<div class="month">Nov</div>
<div class="month">Dec</div>
like image 24
zer00ne Avatar answered Oct 11 '22 17:10

zer00ne