-1

Why isn't the filter working here?

.btns a {
  display: block;
  float: left;
  text-decoration: none;
  text-align: center;
  padding: 10px;
  margin: 0 5px 0 0;
  color: white;
  background: #1271C7;
}

.btns a:focus[cat] {
  background-color: grey;
}

.btns a[cat="java"]:focus ~ .post div:not([cat="java"]),
.btns a[cat="internet-things"]:focus ~ .post div:not([cat="internet-things"]),
.btns a[cat="blockchain"]:focus ~ .post div:not([cat="blockchain"]) {
  display: none;
}

.post div {
  display: block;
  float: left;
  width: 99%;
  border: 1px solid black;
  margin-top: 20px;
  background-color: lightgrey;
}
<div class="btns">
  <a href="#" cat="all">Show all</a>
  <a href="#" cat="java">Java</a>
  <a href="#" cat="internet-things">Internet of Things</a>
  <a href="#" cat="blockchain">Blockchain</a>
</div>

<div class="post">
  <div cat="java">Everything about Java Spring</div>
  <div cat="blockchain">A bitcoin project</div>
  <div cat="java">Eclipse IDE Java</div>
  <div cat="blockchain">Ethereum tokens ICO</div>
  <div cat="internet-things">Walking Fridge</div>
  <div cat="blockchain">Bitcoin 3.0</div>
  <div cat="internet-things">Aibo</div>
</div>

Not-working example: https://jsfiddle.net/3qbvvt50/2/

While the filter DOES work, when I remove <div class="btns"> from the HTML and remove .btns from the CSS.

Working example: https://jsfiddle.net/3qbvvt50/3/

Stickers
  • 75,527
  • 23
  • 147
  • 186
Konijn
  • 51
  • 2
  • 7
  • Can you define `what works` and `what does not work` what do you expect? – caramba Jan 20 '18 at 15:29
  • The filtering not working on https://jsfiddle.net/3qbvvt50/2/ While the filtering does works on https://jsfiddle.net/3qbvvt50/3/ My question is: Why does the filter of the first example not working? – Konijn Jan 20 '18 at 15:36
  • What do you mean by filter? – TylerH Jan 20 '18 at 18:09
  • 1
    Possible duplicate of [Is there a CSS parent selector?](https://stackoverflow.com/questions/1014861/is-there-a-css-parent-selector) – TylerH Jan 20 '18 at 18:10
  • Elements targetted with `+` and/or `~` **must** have the same direct parent element as the element specified before the selector. Given your current HTML structure what you want to do **cannot be done with CSS**. – connexo Jan 20 '18 at 18:37
  • @connexo just tweaking the HTML a little (and without disturbing the separation of buttons from content divs), this **can** be achieved with CSS. – Facundo Corradini Jan 20 '18 at 20:24
  • 1
    @connexo I got what you mean, without touching the HTML **at all** you cannot do that. I agree with that. But your comment also gives the idea that you cannot have them in separate containers. You can, just need to add something in the divs container to play the part of the sibling. – Facundo Corradini Jan 20 '18 at 20:30

2 Answers2

4

The general sibling combinator (~), and adjacent sibling combinator (+), they only work with elements that are direct siblings.

In the code your posted above, a[cat="java"] and <div cat="java"> they are under different parent divs, so the sibling selector won't work.

The best results you can achieve for this tabs liked layout with plain CSS is to use <label> and <input type="radio"> I think. Note, I also changed cat= to data-cat= for a proper markup.

jsFiddle

.btns label {
  display: inline-block;
  padding: 5px 10px;
  margin: 0 5px 10px 0;
  background: royalblue;
  color: white;
}

#all:checked ~ .btns label[for="all"],
#java:checked ~ .btns label[for="java"],
#internet-thing:checked ~ .btns label[for="internet-thing"],
#blockchain:checked ~ .btns label[for="blockchain"] {
  background: tomato;
}

#all:checked ~ .post div,
#java:checked ~ .post div[data-cat="java"],
#internet-thing:checked ~ .post div[data-cat="internet-things"],
#blockchain:checked ~ .post div[data-cat="blockchain"] {
  display: block;
}

input[name="cat"][type="radio"],
.post div {
  display: none;
}
<input id="all" name="cat" type="radio" checked>
<input id="java" name="cat" type="radio">
<input id="internet-thing" name="cat" type="radio">
<input id="blockchain" name="cat" type="radio">

<div class="btns">
  <label for="all">All</label>
  <label for="java">Java</label>
  <label for="internet-thing">Internet of Things</label>
  <label for="blockchain">Blockchain</label>
</div>

<div class="post">
  <div data-cat="java">Everything about Java Spring</div>
  <div data-cat="blockchain">A bitcoin project</div>
  <div data-cat="java">Eclipse IDE Java</div>
  <div data-cat="blockchain">Ripple Network</div>
  <div data-cat="internet-things">Smart Thermostate</div>
  <div data-cat="java">IntelliJ IDEA Community Edition</div>
  <div data-cat="java">Java SDK 9.0</div>
  <div data-cat="java">Java SDK 8.0</div>
  <div data-cat="blockchain">Ethereum tokens ICO</div>
  <div data-cat="internet-things">Walking Fridge</div>
  <div data-cat="blockchain">Bitcoin 3.0</div>
  <div data-cat="internet-things">Aibo</div>
</div>
Stickers
  • 75,527
  • 23
  • 147
  • 186
2

The radio buttons solution is probably what I'd go with at first, but since you need to use <a> tags and have separate wrapper classes for buttons and the contents, you can use the :target selector on some helper divs to act as siblings, and filter out options with the :not selector and attr.

.btns a {
  display: inline-block;
  padding: 5px 10px;
  margin: 0 5px 10px 0;
  background: royalblue;
  color: white;
}

a:active {
  background: tomato;
}

#java:target ~ div:not([data-cat="java"]){display:none;}

#blockchain:target ~ div:not([data-cat="blockchain"]){display:none;}

#internet-things:target ~ div:not([data-cat="internet-things"]){display:none;}
<div class="btns">
  <a href="#"> All </a>
  <a href="#java">Java</a>
  <a href="#internet-things">Internet of Things</a>
  <a href="#blockchain">Blockchain</a>
</div>

<div class="post">
  <div class="helper" id="java"></div>
  <div class="helper" id="blockchain"></div>
  <div class="helper" id="internet-things"></div>
  <div data-cat="java">Everything about Java Spring</div>
  <div data-cat="blockchain">A bitcoin project</div>
  <div data-cat="java">Eclipse IDE Java</div>
  <div data-cat="blockchain">Ripple Network</div>
  <div data-cat="internet-things">Smart Thermostate</div>
  <div data-cat="java">IntelliJ IDEA Community Edition</div>
  <div data-cat="java">Java SDK 9.0</div>
  <div data-cat="java">Java SDK 8.0</div>
  <div data-cat="blockchain">Ethereum tokens ICO</div>
  <div data-cat="internet-things">Walking Fridge</div>
  <div data-cat="blockchain">Bitcoin 3.0</div>
  <div data-cat="internet-things">Aibo</div>
</div>

Not something I would use in production as it relies on having a CSS rule for each category (which most likely will be dynamic), but quite fun as a CSS challenge still.

Facundo Corradini
  • 3,825
  • 9
  • 24
  • Interesting approach, though I don't think this is worth going for. It is almost certain to cause collisions in any web application, e.g. with SPA routing. Might be a working approach for a static page though. – connexo Jan 20 '18 at 20:34
  • @connexo I agree, that's another reason I wouldn't consider it for production. To be honest, I would just use JS for this and call it a day. But since the OP said he wanted to use anchor tags in the comments for Pangloss radio buttons solution, and was already using anchors in his code, maybe this is exactly the static / barely dynamic scenario where this can work. – Facundo Corradini Jan 20 '18 at 20:56
  • @CalvinK great, glad to help :) If the answer works for you, remember to mark it as accepted ;) – Facundo Corradini Jan 20 '18 at 21:53
  • Nice solution, @CalvinK just be aware that `:target` will make page to [jump](https://jsfiddle.net/rpb23g7b/) each time you click. – Stickers Jan 20 '18 at 22:04