Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CSS only, no transition on load

I have a custom checkbox that is filled with transitions for border, color, etc. as well as for 3d transformation to flip it over. If the checkbox is unchecked it looks fine and transitions nicely between states, however, if the checkbox is given the checked attribute on dom load then it has to spin into place and the checkbox is visible on the backface.

enter image description here

NOTE: Although I link the JsFiddle so you can see the code the issue is not happening in the fiddle. It only happens if the style is linked via style sheet.

https://jsfiddle.net/tj2djeej/

/* Radio & Checkbox */

input.flipCheckbox {
  -webkit-transition: transform .5s linear 0s;
  -webkit-transform-style: preserve-3d;
  -webkit-appearance: none;
  -webkit-transform: rotatey(0deg);
  -webkit-perspective: 800;
  -webkit-transform-style: preserve-3d;
  box-sizing: border-box;
  position: relative;
  outline: none;
  width: 26px;
  height: 26px;
  border: 3px solid #C15649;
  cursor: pointer;
}
input.flipCheckbox:checked {
  -webkit-transform: rotatey(180deg);
}
input.flipCheckbox:after {
  -webkit-transform: rotatey(-180deg);
  -webkit-transition: color 0s linear .25s, -webkit-text-stroke-color 0s linear .25s;
  -webkit-text-stroke-color: transparent;
  cursor: pointer;
  line-height: 26px;
  font-size: 14px;
  width: 26px;
  height: 26px;
  position: absolute;
  z-index: 1;
  top: -3px;
  left: -3px;
  color: transparent;
  text-align: center;
  -webkit-text-stroke-width: 2px;
  -webkit-text-stroke-color: transparent;
}
input.flipCheckbox:checked:after {
  color: #C15649;
  -webkit-text-stroke-color: #C15649;
}
input.flipCheckbox:after {
  content: "\2713";
}
<input type="checkbox" class="flipCheckbox" />
<input type="checkbox" checked class="flipCheckbox" />
like image 881
DasBeasto Avatar asked Oct 07 '16 17:10

DasBeasto


People also ask

How do you add a transition on load?

onload and once the document is loaded remove the class to trigger all transition on all elements as specified in your css. Here is a reverse solution: Make your html layout and set the css accordingly to your final result (with all the transformation you want). Set the transition property to your liking.

How do you stop a transition in CSS?

To trigger an element's transition, toggle a class name on that element that triggers it. To pause an element's transition, use getComputedStyle and getPropertyValue at the point in the transition you want to pause it. Then set those CSS properties of that element equal to those values you just got.


4 Answers

If you just want to hide the checkmark when unchecked, there's backface-visibility: hidden.

input.flipCheckbox:after {
    -webkit-backface-visibility: hidden;
    backface-visibility: hidden;
}

This should simplify a lot of things for you. For one, you no longer need to animate the checkmark's color from transparent.

like image 65
darrylyeo Avatar answered Oct 27 '22 13:10

darrylyeo


The :focus and :hover pseudo-classes should work well for your needs. Just move your transition rule from input.flipCheckbox to a new rule-set:

input.flipCheckbox:focus, body:hover input.flipCheckbox {
    -webkit-transition: transform .5s linear 0s;
}

Since the checkbox is not focused on page load the transition doesn't occur, yet when the user checks the check box it gains focus allowing the transition to occur. The only downside is if the checkbox uses focus before the animation completes. Like when a user is using just the keyboard and tabs away too quickly. That's where :hover steps in. Since :hover is applied to body (html or any other parent would work as well) as long as the cursor is on the page, the transition still occurs.

You could just use one or the other, but the two together covers everything except if the cursor is off the page and the user tabs away too quickly.

As you said, the issues doesn't occur in online editors, but here's the full code anyways.

input.flipCheckbox {
   -webkit-transform-style: preserve-3d;
   -webkit-appearance:none;
   -webkit-transform: rotatey(0deg);
   -webkit-perspective: 800;
   -webkit-transform-style: preserve-3d;
   box-sizing: border-box;
   position:relative;
   outline:none;
   width: 26px;
   height:26px;
   border: 3px solid #C15649;
   cursor: pointer;
}

input.flipCheckbox:focus, body:hover input.flipCheckbox {
    -webkit-transition: transform .5s linear 0s;
}

input.flipCheckbox:checked {
   -webkit-transform: rotatey(180deg);
}

input.flipCheckbox:after {
 -webkit-transform: rotatey(-180deg);
 -webkit-transition: color 0s linear .25s, -webkit-text-stroke-color 0s linear .25s;
 -webkit-text-stroke-color: transparent;
  cursor: pointer;
  line-height:26px;
  font-size:14px;
  width:26px;
  height:26px;
  position: absolute;
  z-index: 1;
  top:-3px;
  left:-3px;
  color:transparent;
  text-align: center;
  -webkit-text-stroke-width: 2px;
  -webkit-text-stroke-color: transparent;
}

input.flipCheckbox:checked:after {
   color: #C15649;
  -webkit-text-stroke-color: #C15649;
}

input.flipCheckbox:after {
  content:"\2713";
}
<input type="checkbox" class="flipCheckbox"/>
<input type="checkbox" checked class="flipCheckbox"/>
like image 30
David Mann Avatar answered Oct 27 '22 13:10

David Mann


You could set an animation on the element, that changes the element state at its own speed.

The trick here is to get an animation that is:

  • Not really an animation, in the sense that there is no change in the property value. This is achieved setting 2 different keyframes with the same value.
  • The same animation for both the checked and the unchecked states. If we change the animation name, the animation will be replayed every time that we change states. To allow for this, I set an animation that has 2 different parts, one that has the element rotated and another with the element unrotated. We use one part or the other changing the direction from normal to reverse. And setting an initial delay that makes it use only the last half.

I Have tried to reproduce your scenario via javascript, redenring the elemnt and setting the check state afterwards. I don't know for sure if this is equivalent to it.

On the snippet press the button and it will alternate rendering the element from scratch, once in the checked state and another in the unchecked

var ele;
var checked = true;

function reload() {
  var oldele = document.getElementById("test");

  ele = oldele.cloneNode(true);
  oldele.parentNode.replaceChild(ele, oldele);
  setTimeout(check, 1);
}

function check() {
  ele.checked = checked;
  checked = !checked;
}
.test {
  width: 100px;
  height: 100px;
  transition: transform 0.5s;
  transform: rotateY(180deg);
  animation-name: still;
  animation-duration: 0.2s;
  animation-iteration-count: 1;
  animation-direction: normal;
  animation-delay: -0.11s;
}
button {
  margin: 20px;
}
.test:checked {
  transform: rotateY(0deg);
  animation-direction: reverse;
}
input {
  animation-name: "";
}
@keyframes still {
  from, 49.9% {
    transform: rotateY(0deg);
  }
  50%,
  to {
    transform: rotateY(180deg);
  }
}
<input type="checkbox" class="test" id="test" />
<button onclick="reload()">Load</button>
like image 31
vals Avatar answered Oct 27 '22 13:10

vals


It seems to be a bug with Chrome/Webkit. At least in my version of Chrome and Safari, the behavior I have is the following:

  • Without any script tag in the html or a script tag before the css link or a completely empty script tag, and without any input elements, there is no transition happening on div, or other non input elements.

  • Without any script tag in the html or a script tag before the css link or a completely empty script tag, as soon as there's one input element (whichever type), then all elements that have a style that doesn't match default value are transitioned.

  • If you add a script tag after the css link with at least a space inside it, then no transition occurs on load on any element.

So it looks like input elements trigger some kind of layout refresh, that strangely does not occur when a script is there. Maybe simply because of a delay somewhere in the parsing, or a condition that is wrongly set somewhere. At least this is the behavior I have with Chrome and Safari.

So you can simply add :

<script> </script> <!-- the space is important -->

after you link element, and you won't get the behavior you describe. It is not a css solution, but the problem doesn't seem to be with your CSS, so I'm posting it anyway.

like image 29
Julien Grégoire Avatar answered Oct 27 '22 12:10

Julien Grégoire