<hgroup>
  <h1><span>Interaction States:</span> <br/> Label Wrapped Checkbox</h1>
  <p>Visualizing the states of a <code>label</code> wrapping an <code>input[type="checkbox"]</code>.</p>
</hgroup>

<div class="container">
  <section class="demo one">
    <label for="cb_1">
      <input type="checkbox" id="cb_1" />
      <span>Label with Visible Checkbox</span>
    </label>
    <section class="states">
      <span class="default state">label</span>
      <span class="hover state">:hover</span>
      <span class="active state">:active</span>
      <span class="focus-within state">:focus-within</span>
      <span class="checked state">:has(:checked)</span>
    </section>
  </section>  
  <section class="demo two">
    <nav>
      <label for="cb_2">
        <input type="checkbox" id="cb_2" />
        <span>Label with Hidden Checkbox</span>
      </label>
    </nav>
    <section class="states">
      <span class="default state">label</span>
      <span class="hover state">:hover</span>
      <span class="active state">:active</span>
      <span class="focus-within state">:focus-within</span>
      <span class="checked state">:has(:checked)</span>
    </section>
  </section>
</div>
@import url(https://fonts.bunny.net/css?family=libre-franklin:400,700);

:root {
  --gap: 1rem;
  --padding: 2%;
}

html, body { }

body { 
  color: hsl(40 10% 30%); 
  font-family: "Libre Franklin", sans-serif;
  line-height: 1.2;
  padding: calc(var(--padding) * 2); 
}

code { background: hsl(40 30% 90%); border-radius: 3px; color: hsl(40 30% 30%); font-weight: bold; padding: .15rem .5rem .25rem; }
label { cursor: pointer; user-select: none; }
h1, p { margin: 0; }

hgroup { 
  margin-bottom: calc(var(--gap) * 3);
  
  h1 span { font-weight: 400; }
  
  p { 
    line-height: 1.5;
    margin-top: calc(var(--gap) / 2);
  }
}

.container {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(420px, 1fr));
  gap: calc(var(--gap) * 2) var(--gap);
}

.demo {
  --bg: hsl(40 60% 20%);
  --color: color-mix(in lab, var(--bg), black 10%);
  --border-color: transparent;
  --padding: 3rem;
  
  background: color-mix(in lab, var(--bg), white 95%);
  border: 2px solid var(--border-color);
  display: grid;
  height: 8rem;
  
  position: relative;
  
  label {
    background: inherit; /* for filter */
    color: var(--color);
    display: flex;
    gap: .6rem;
    place-items: center;
    transition: all .12s ease-in-out;
    z-index: 3;
    
    input {
      appearance: none;
      aspect-ratio: 1;
      background: transparent;
      border-radius: 1px;
      outline: 2px solid var(--color);
      outline-offset: 2px;
      
      position: relative;
      width: .5rem;
      
      &:checked {
        background: var(--color);
        padding: 3px;
      }
    }
    
    span {      
      background: inherit;
      background-clip: text;    
      color: var(--color);
      display: inline-block;
      font-weight: 700;
    }
  }
  
  /* :hover shading */
/*  &:before {
    background: color-mix(in lab, var(--bg), white 70%);
    opacity: 0;
    pointer-events: none;
    
    transition: opacity .15s;
    
    content: "";
    inset: 0;
    position: absolute;
    z-index: 3;
  }  */
  
  /* State Pills */ 
  .states {
    display: flex;
    justify-content: center;
    gap: calc( var(--gap) / 4);
    width: 100%;
    
    position: absolute;
    
    left: 50%;
    bottom: 0;
    transform: translateX(-50%) translateY(50%);
    z-index: 5;
  }
  
  .state {
    --opacity: 0;
    --transformY: 3dvh;
    --visibility: hidden;   
    
    opacity: var(--opacity);
    transform: translateY(var(--transformY));
    visibility: var(--visibility);
    
    background: color-mix(in lab, var(--bg), white 80%);
    border-radius: 2rem;
    color: var(--color);
    
    font-family: monospace;
    font-size: .75rem;
    font-weight: bold;    
    
    max-width: max-content;   
    padding: .5rem .72rem .47rem;   
    user-select: none;
    white-space: nowrap;
    
    transition-duration: .15s;
    transition-property: all;   
  } 
  
  .state.default,
  &:active .state.active,
  &:hover .state.hover,
  &:focus-within .state.focus-within,
  &:focus-within:has(:checked) .state.focus-within-checked,
  &:has(:checked) .state.checked {
    --opacity: 1; 
    --transformY: 0px; 
    --visibility: visible; 
  }
  
  /* shading */ 
  /*  &:hover::after { opacity: 1; }   */
  &:hover { --bg: hsl(40 60% 40%) }
  
  &:focus-within { 
    --bg: hsl(40 100% 40%); 
    --border-color: color-mix(in lab, var(--bg), white 75%); 
    border-style: dashed;
    &:hover { border-style: solid; }
  }
  
  &:focus-within:has(:checked) { 
    --bg: hsl(130 80% 36%); 
  }
  
  &:has(:checked) { 
    --bg: hsl(130 50% 30%);
  } 
  
  &:active { 
    --bg: hsl(200 100% 30%) !important; 
    --border-color: color-mix(in lab, var(--bg), white 75%);
  }
  
  
  &.one,
  &.two {
    nav { 
      display: grid;
      background: inherit;
    }
    
    label {     
      grid-area: 1 / 1;
      place-content: center;
      text-align: center;
    }
  }
  
  &.two {   
    input {
      opacity: 0;
      height: 0;
      width: 0;
      
      &:checked { padding: 0; }
    }
  }
}

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.