skip to Main Content

I’m trying to create a filterable list of items that shows unique values when a combination of filters are checked. I need to be able to do this with only with CSS and HTML because the internal corporate wiki page where I’m building this does not allow the "script" tag.

My list is : A B C

My Values are A, B, C, D

I want value A to show when just filter A is checked, value B to show when just filter B is selected, and so on.

I want value D to show only when filters A, B & C are all checked.

This is what I currently have:

.items>[data-type] {
  display: none;
}

input[name=a]:checked~.items div[data-type=a],
input[name=b]:checked~.items div[data-type=b],
input[name=c]:checked~.items div[data-type=c] {
  display: block;
}
<input type="checkbox" name="a" style="display: inline-block;"> A
<br/><input type="checkbox" name="b" style="display: inline-block;"> B
<br/><input type="checkbox" name="c" style="display: inline-block;"> C
<hr/>
<div class="items">
  <div data-type="a">A</div>
  <div data-type="b">B</div>
  <div data-type="c">C</div>
</div>

I’m not sure how to specify with the CSS that data-type=d is the result of input a, b, and c being checked.

2

Answers


  1. You were in the right way

    .items>[data-type] {
      display: none;
    }
    
    input[name=a]:checked~.items div[data-type=a],
    input[name=b]:checked~.items div[data-type=b],
    input[name=c]:checked~.items div[data-type=c] {
      display: block;
    }
    
    /* Sequential siblings check */
    input[name=a]:checked~input[name=b]:checked~input[name=c]:checked~.items div[data-type=d] {
      display: block;
    }
        <input type="checkbox" name="a" style="display: inline-block;"> A
    <br><input type="checkbox" name="b" style="display: inline-block;"> B
    <br><input type="checkbox" name="c" style="display: inline-block;"> C
    <hr>
    <div class="items">
      <div data-type="a">A</div>
      <div data-type="b">B</div>
      <div data-type="c">C</div>
      <div data-type="d">D</div>
    </div>
    Login or Signup to reply.
  2. Here is a verbose version. Pretty verbose and ugly. Starting to get a bit MUCH when we do a show/hide of AB, BC, ABC etc. I did not take time to dive deep but there might be a simpler method using just CSS – or just enlist JavaScript to do some of this.

    Here is a verbose set of notes:

    Since this is a cascade (C in css) we go top/down

    Format the label with a left pad between it and the checkbox:

    input[type="checkbox"]~label {
      padding-left: 1em;
    }
    

    Format the label with a new line after:

    input[type="checkbox"]~label::after {
      content: "A";
      white-space: pre;
      margin-left: 3em;
    }
    

    Hide them all initially:

    .items>[data-type] {
      display: none;
    }
    

    Now show the single checked target:

    input[name=a]:checked~.items div[data-type=a],
    input[name=b]:checked~.items div[data-type=b],
    input[name=c]:checked~.items div[data-type=c] {
      display: block;
    }
    

    Now when there are TWO (or three) checked we target that ones siblings:

    input:is(input[name=a]:checked ~ input[name=b]:checked)~.items div[data-type=d],
    input:is(input[name=a]:checked ~ input[name=c]:checked)~.items div[data-type=e],
    input:is(input[name=b]:checked ~ input[name=c]:checked)~.items div[data-type=f],
    input:is(input[name=a]:checked ~ input[name=b]:checked ~ input[name=c]:checked)~.items div[data-type=g] {
      display: block;
    }
    

    Now when two are checked we turn off visibility of the others:
    Trick here is the ~.items :is([data-type]) finds the non-targeted siblings to turn those off.

    THEN when three are checked we just show the ABC one.

    input:is(input[name=a]:checked ~ input[name=b]:checked)~.items :is([data-type]),
    input:is(input[name=a]:checked ~ input[name=c]:checked)~.items :is([data-type]),
    input:is(input[name=b]:checked ~ input[name=c]:checked)~.items :is([data-type]),
    input:is(input[name=a]:checked ~ input[name=b]:checked ~ input[name=c]:checked)~.items :is([data-type]) {
      display: none;
    }
    
    input[type="checkbox"]~label {
      padding-left: 1em;
    }
    
    input[type="checkbox"]~label::after {
      content: "A";
      white-space: pre;
      margin-left: 3em;
    }
    
    .items>[data-type] {
      display: none;
    }
    
    input[name=a]:checked~.items div[data-type=a],
    input[name=b]:checked~.items div[data-type=b],
    input[name=c]:checked~.items div[data-type=c] {
      display: block;
    }
    
    input:is(input[name=a]:checked ~ input[name=b]:checked)~.items div[data-type=d],
    input:is(input[name=a]:checked ~ input[name=c]:checked)~.items div[data-type=e],
    input:is(input[name=b]:checked ~ input[name=c]:checked)~.items div[data-type=f],
    input:is(input[name=a]:checked ~ input[name=b]:checked ~ input[name=c]:checked)~.items div[data-type=g] {
      display: block;
    }
    
    input:is(input[name=a]:checked ~ input[name=b]:checked)~.items :is([data-type]),
    input:is(input[name=a]:checked ~ input[name=c]:checked)~.items :is([data-type]),
    input:is(input[name=b]:checked ~ input[name=c]:checked)~.items :is([data-type]),
    input:is(input[name=a]:checked ~ input[name=b]:checked ~ input[name=c]:checked)~.items :is([data-type]) {
      display: none;
    }
    <input type="checkbox" name="a"><label for="a">A</label>
    <input type="checkbox" name="b"><label for="b">B</label>
    <input type="checkbox" name="c"><label for="c">C</label>
    <div class="items">
      <div data-type="a">A</div>
      <div data-type="b">B</div>
      <div data-type="c">C</div>
      <div data-type="d">AB</div>
      <div data-type="e">AC</div>
      <div data-type="f">BC</div>
      <div data-type="g">ABC</div>
    </div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search