Search code examples
htmlcsscheckboxcss-transforms

CSS prevent rotation transform from affecting :before elements


I'm trying to have the checkboxes appear below their slanted "span" label. However, the transform applied to the "span" is also applying to the custom checkbox created with the ":before" selector. How do you prevent the 45deg rotation to the custom checkbox, and have it appear directly below it's label?

.slanted_chkbx {
  margin-top: 25px;
}

.slanted_check {
  margin-left: 5px;
  margin-right: 15px;
  display: inline-block;
  position: relative;
}

.slanted_check span {
  position: absolute;
  top: -20px;
  left: .7em;
  transform-origin: bottom left;
  transform: rotate(-45deg);
}

.custom_check {
  display: none;
}

.custom_check + span:before {
  content: '';
  display: block;
  cursor: pointer;
  width: 10px;
  height: 10px;
  left: 0;
  top: 0;
  position: absolute;
  border: 2px solid #111111;
  -webkit-transition: all .2s;
  transition: all .2s;
}

.custom_check:checked + span:before {
  width: 5px;
  top: -2px;
  left: 2px;
  border-radius: 0;
  opacity: 1;
  border-top-color: transparent;
  border-left-color: transparent;
  -webkit-transform: rotate(45deg);
  transform: rotate(45deg);
}
<div class="slanted_chkbx">
  <label class="slanted_check">
    <input type="checkbox" class="custom_check" name="option_one" value="option_one">
    <span>One</span>
  </label>
  <label class="slanted_check">
    <input type="checkbox" class="custom_check" name="option_two" value="option_two">
    <span>Two</span>
  </label>
  <label class="slanted_check">
    <input type="checkbox" class="custom_check" name="option_three" value="option_three">
    <span>Three</span>
  </label>
</div>


Solution

  • You need to place the reverse transform on the base state of the pseudo-element, not on the hover state.

    .slanted_chkbx {
      margin-top: 25px;
    }
    
    .slanted_check {
      margin-left: 15px;
      margin-right: 15px;
      display: inline-block;
      position: relative;
    }
    
    .slanted_check span {
      margin-right: -25px;
      display: inline-block;
      transform-origin: bottom left;
      transform: rotate(-45deg);
    }
    
    .custom_check {
      display: none;
    }
    
    .custom_check+span:before {
      content: '';
      display: block;
      cursor: pointer;
      width: 10px;
      height: 10px;
      left: -15px;
      bottom: -10px;
      position: absolute;
      border: 2px solid #111111;
      -webkit-transition: all .2s;
      transition: all .2s;
      -webkit-transform: rotate(45deg);
      transform: rotate(45deg);
    }
    
    .custom_check:checked+span:before {
      width: 5px;
      border-radius: 0;
      opacity: 1;
      border-top-color: transparent;
      border-left-color: transparent;
    }
    <div class="slanted_chkbx">
      <label class="slanted_check">
        <input type="checkbox" class="custom_check" name="option_one" value="option_one">
        <span>One</span>
      </label>
      <label class="slanted_check">
        <input type="checkbox" class="custom_check" name="option_two" value="option_two">
        <span>Two</span>
      </label>
      <label class="slanted_check">
        <input type="checkbox" class="custom_check" name="option_three" value="option_three">
        <span>Three</span>
      </label>
    </div>

    I'm not entirely sure what effect you are going for in the checked state so I have not adjusted that.