CSS Checkboxes

Pretty proud of this one, more than the sidebar menu. Working checkboxes to hide and unhide stuff, all done with CSS! So here's how I did it.
As seen on the Characters category page.   And just to let you know, you'll need the Grandmaster level membership, as it uses container and section BBCode.  

Preface

The way this works is that if nothing is selected, everything shows. Then, if something is selected, things of that group are shown, including if multiple things are selected. This also works when the page loads. (Spoilers are weird when the page first loads and you haven't used them yet, idk)
 

Intermodal Containers

I'll start with the containers this time. On the Characters category page, I have a table of all the characters in my world, but the table is not necessary for this to work. However, some of the CSS uses the table to do stuff, but I'll change it for here.   BBCode Structure
[container:wrapper][container:test group-a]Something 1[/container][/container]
[container:wrapper][container:test group-b]Something 2[/container][/container]
[container:wrapper][container:test group-c]Something 3[/container][/container]
  That's all, honestly; it's just mainly settings CSS classes. It also depends on what you're doing / other CSS styling.
There are two containers here because you'll need the "wrapper" to select specific things. In my code, I don't have this as I select the table cells, which act as my "wrapper".   For my characters page, I have a container for the background image, several specific CSS classes for the second level container, then the character's name is wrapped in a [p] tag for styling.   My Character Example
[td]
[url:https://www.worldanvil.com/w/dragonguard/a/azier][container:img-char][container:char aff-drgngrd ph-female-1][p]Azier[/p][/container][/container][/url]
[/td]
  (Of course wrapped in the [table] tags)
 

Legend / Checkboxes

Here's the BBCode for the legend / checkboxes themselves, based on my characters category page.
I chose to do three just so you can see it works with multiple groups.  
[container:checkbox group-a][spoiler]|[section:unchecked][][/section][section:checked][c][/section][/spoiler][section:group-style-a]Group A[/section][/container]
[container:checkbox group-b][spoiler]|[section:unchecked][][/section][section:checked][c][/section][/spoiler][section:group-style-b]Group B[/section][/container]
[container:checkbox group-c][spoiler]|[section:unchecked][][/section][section:checked][c][/section][/spoiler][section:group-style-c]Group C[/section][/container]
  It's a bit confusing, but I'll break it down.   I had a legend container wrapping all the checkboxes for styling; I didn't include it here.
  • First is the general checkbox container with a subclass of each listing. (group-a / group-b / etc)
  • Then the spoiler tag, but don't put anything there. Just do the pipe ( | ) and move on.
  • The "title" of the spoiler is actually the checkmark box. I use the BBCode for that, [] and [c], which makes:
  • I set these checkmark boxes in a section tag for styling; we've got to hide one at any given time, after all.
  • After the closing spoiler tag, I put down what that checkbox relates to (Group A / Group B / etc). I added a container around them for styling.
  •  

    The Good Stuff (CSS)

    Now for the part that makes it work.  
    .user-css .wrapper {
    display: none;
    }
    
      First, you hide all containers with the wrapper class.
    For me, these are the table's cells. (.table td)   Then, do whatever styling stuff you want.  

    Legend / Checkbox CSS

    .user-css .checkbox {
    margin: 0;
    }
     
    .user-css .checkbox .spoiler-button {
    background: none;
    }
     
    .user-css .checkbox .spoiler-card {
    display: none;
    }
    
      We want to remove any instance of actual spoiler stuff. We're just using the spoiler as a button for an on / off state, more or less, since we can't use JavaScript. (Lol it even removed that word in plain text, so I had to PascalCase it.)   Switching the checkboxes
    .user-css .checkbox .spoiler-button .checked,
    .user-css .checkbox .spoiler-button[aria-expanded=true] .unchecked,
    .user-css .checkbox .spoiler-button[aria-expanded=false] .checked {
    display: none;
    }
     
    .user-css .checkbox .spoiler-button[aria-expanded=false] .unchecked,
    .user-css .checkbox .spoiler-button[aria-expanded=true] .checked {
    display: block;
    }
    
      Here's where we switch the checkboxes based on the spoiler's state. We first hide the checked box in general because, for some reason, when loading the page, the spoiler element is like... wierd and doesn't register that it's actually closed. idk man..   We also tell it to hide the unchecked box if the spoiler's expanded state is true and also tell it to hide the checked box if the expanded state is false.
    Then, in the second block, it's just the opposite. Display unchecked if the spoiler state is not expanded, and show checked if it is.  
    .user-css .checkbox .group-style {
    padding-inline: 5px;
    }
    
      Then we do some styling with the legend / checkbox group. In mine, I added a left border that is colored and corresponds to the same colored border by the character's name.  

    Toggling Visibility

    Note: Make sure this is below the very first thing of hiding all the containers with "wrapper"!   Now for what you came here for. The meat and potatoes of CSS code. (?)
    Making it work.   Brace yourself, it's a bit crazy, and it took me like a week to figure it out. You can always go to my Characters page and hit F12 to view the CSS code too!  
    .user-css:has(.checkbox.group-a .spoiler-button[aria-expanded=true]) .wrapper:has(:not(.test.group-a)),
    .user-css:has(.checkbox.group-b .spoiler-button[aria-expanded=true]) .wrapper:has(:not(.test.group-b)),
    .user-css:has(.checkbox.group-c .spoiler-button[aria-expanded=true]) .wrapper:has(:not(.test.group-c)) {
    display: none;
    }
     
    .user-css:has(.checkbox .spoiler-button:not([aria-expanded])) .wrapper:has(.test),
    .user-css:has(.checkbox.group-a .spoiler-button[aria-expanded=true]) .wrapper:has(.test.group-a),
    .user-css:has(.checkbox.group-b .spoiler-button[aria-expanded=true]) .wrapper:has(.test.group-b),
    .user-css:has(.checkbox.group-c .spoiler-button[aria-expanded=true]) .wrapper:has(.test.group-c),
    .user-css:has(.checkbox .spoiler-button[aria-expanded=false]) .wrapper:has(.test) {
    display: block;
    }
    
      This is why you need that wrapper container! (Or in my case, table cells)
    We extensively use the CSS :has and :not selectors.  
    Note: If you're using a table, you can just use the table cells. Replace all the .wrapper with .table td!
      First block
  • Hide the wrappers (or table cells) not currently selected. (Showing only the ones that are in that selected group)
  • Yeah, it's kinda confusing; if group-a is checked, it checks to see if the wrappers have a group that isn't group-a. If it does, hide them.   Second block
  • If checkbox spoilers don't have the "aria-expanded" attribute, display wrappers (or table cells) that have a .test child. (This is what I was talking about earlier with spoilers being weird when you first load the page)
  • If a checkbox is selected (spoiler as the "aria-expanded" attribute as true), display wrappers (or table cells) that are currently selected. (this x3 or however many selections / groups you have)
  • If no checkboxes are selected (all spoiler "aria-expanded" attributes as false), display all wrapper (or table cells). (This is all you would need if the spoilers would have this attribute when the page loads. But it doesn't, so we need the first bullet point.)

  • If I recall correctly, I had to have the group selections in the second code block to be specifically between those first and last lines. Y'know, cascading styling stuff. (Disclaimer: Not actually what CSS means. lol)
    Remember, you can always check out the Characters category page and hit F12! This tutorial was based on that page. That one uses tables and stuff, so the CSS is slightly different.   You can also hit F12 on this page too, as I provided a live example below that doesn't use tables.    

    Use it, Test it, Switch, Update it

    Test it out yourself!  
    Oh boy, some stuff (Group A)
    Oh boy, some other stuff (Group B)
    Oh boy, even more other stuff (Group C)
    Oh boy, some other stuff, again (Group B)
    Group A
    Group B
    Group C


    Cover image: by Nulcheck

    Comments

    Please Login in order to comment!
    Powered by World Anvil