1

I have the following markup, and I need to find a CSS way to change a triangle whenever .hide class is active.

To achieve this I've used a pseudo element like this:

summary:before  {
    content: '\25BC';
}
summary:before   + .hide  {
    content: '\25BA';
}

The problem is: it doesn't work. The arrow doesn't change. Even though summary:before + .hide appears in the DevTools.

So how to achive the desired effect without using JavaScript only CSS?

var $div = $('summary');

$div.on('click', function() {
  $('ul').toggleClass('hide');
});
.wrapper {
  width: 300px;
  height: 300px;
  background-color: #ecf0f1;
}
.details {
  outline: none;
  background-color: #95a5a6;
  cursor: pointer;
  position: relative;
}
summary {
  outline: none;
  margin-left: 30px;
}
summary:before {
  content: '\25BA';
  font-size: 12px;
  position: absolute;
  top: 2px;
  left: 13px;
}
summary:before + ul.hide {
  content: '\25BC';
  font-size: 12px;
  position: absolute;
  top: 2px;
  left: 13px;
}
.hide {
  display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrapper">
  <div class="details">
    <summary>Sample</summary>
    <ul class="hide">
      <li>
        <input type="radio" checked/>
        <label>Label 1</label>
      </li>
      <li>
        <input type="radio" />
        <label>Label 2</label>
      </li>
      <li>
        <input type="radio" />
        <label>Label 3</label>
      </li>
    </ul>
  </div>
</div>
Artem Z
  • 565
  • 1
  • 9
  • 19
  • 1
    Possible duplicate of [Is there a "previous sibling" CSS selector?](http://stackoverflow.com/questions/1817792/is-there-a-previous-sibling-css-selector) – Pete Aug 01 '16 at 10:33
  • "summary:before + .hide appears in the DevTools" Wait, seriously? That's super weird. It's not a valid selector. – BoltClock Aug 01 '16 at 10:33
  • 1
    If you are toggling a class with jQuery, why not either do it on the parent container or just toggle a class on the summary too? – Pete Aug 01 '16 at 10:34
  • Pete, it's just an example, actual project based on AngularJS. – Artem Z Aug 01 '16 at 10:43
  • @BoltClock : `summary:before + .hide` should be a valid selector. If `summary` exists then `summary:before` too will exist! – Pugazh Aug 01 '16 at 10:43
  • 1
    @Pugazh: summary:before + hide is not valid for the simple reason that a pseudo-element cannot appear anywhere other than the last compound selector. That means a combinator cannot follow a pseudo-element. It doesn't matter if you think it "should be" a valid selector - the fact is that it is not. – BoltClock Aug 01 '16 at 10:59
  • @BoltClock : Thanks for the explanation :-) – Pugazh Aug 01 '16 at 12:22

2 Answers2

4

You can't select the previous element in CSS. Instead add a class to the div and toggle it.

Try below solution.

var $div = $('summary');

$div.on('click', function() {
  $('ul').toggleClass('hide');
  $(this).toggleClass('collapse');
});
.wrapper {
  width: 300px;
  height: 300px;
  background-color: #ecf0f1;
}
.details {
  outline: none;
  background-color: #95a5a6;
  cursor: pointer;
  position: relative;
}
summary {
  outline: none;
  margin-left: 30px;
}
summary:before {
  content: '\25BA';
  font-size: 12px;
  position: absolute;
  top: 2px;
  left: 13px;
}
summary.collapse:before {
  content: '\25BC';
}
.hide {
  display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrapper">
  <div class="details">
    <summary>Sample</summary>
    <ul class="hide">
      <li>
        <input type="radio" checked/>
        <label>Label 1</label>
      </li>
      <li>
        <input type="radio" />
        <label>Label 2</label>
      </li>
      <li>
        <input type="radio" />
        <label>Label 3</label>
      </li>
    </ul>
  </div>
</div>
Pugazh
  • 9,453
  • 5
  • 33
  • 54
2

You have made 2 mistakes in you code writing.

1st: You have duplicated the styles for your pseudo classes in two places.

2nd: You've put the 'hidden' class directly to the sibling. The right way to do it is to put it in the parent, this way you can access all its children.

You've toggled the class 'hidden' whereas it should be 'expand', because by default, as I understand, your menu is closed and when the user clicks on the details box it ('expands'). Hope that makes sense.

I've made two codepens for you.

In the first we expand the ul list using display:block and display:none and following the class added in the jQuery.

Example 1


In the second we expand the ul list using only jquery to achieve nice slide animation. We also hide the ul by default.

Example 2

Marios Pittas
  • 151
  • 1
  • 4