【问题标题】:CSS only, no transition on load仅 CSS,加载时无过渡
【发布时间】:2016-10-15 22:36:44
【问题描述】:

我有一个自定义复选框,其中填充了边框、颜色等的转换以及 3d 转换以将其翻转。如果未选中复选框,它看起来很好并且在状态之间转换得很好,但是,如果复选框在 dom 加载时被赋予选中属性,那么它必须旋转到位并且复选框在背面可见。

注意:虽然我链接了 JsFiddle,以便您可以看到代码,但问题并没有发生在小提琴中。仅当样式通过样式表链接时才会发生。

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" />

【问题讨论】:

  • :after:before 伪选择器在大多数浏览器中的输入元素中不起作用...改用复选框样式的附加标签。
  • @seahorsepip 哦哇不知道,谢谢你的提示。
  • 我最终使用了一个完全不同的解决方案(包括添加一个 :before 元素),但事实证明这个答案对于简化我的代码以使其成为可能非常宝贵,所以我接受了它。谢谢!

标签: css css-transitions


【解决方案1】:

如果您只想在未选中时隐藏复选标记,则有backface-visibility: hidden

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

这应该会为您简化很多事情。一方面,您不再需要将复选标记的颜色设置为透明动画。

【讨论】:

  • 这可能会大大简化它!我会试一试并报告。我不确定它是否能解决问题,但至少可以忍受。
【解决方案2】:

:focus:hover 伪类应该可以很好地满足您的需求。只需将您的转换规则从 input.flipCheckbox 移动到新的规则集:

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

由于复选框没有关注页面加载,因此不会发生转换,但是当用户选中复选框时,它会获得焦点,从而允许发生转换。唯一的缺点是如果复选框在动画完成之前使用焦点。就像当用户只使用键盘和标签时太快了。这就是:hover 介入的地方。由于:hover 应用于bodyhtml 或任何其他父级也可以工作),只要光标在页面上,转换仍然会发生。

您可以只使用其中一个,但两者一起涵盖了所有内容,除非光标离开页面并且用户太快离开标签。

正如你所说,在线编辑器中不会出现这些问题,但无论如何这里是完整的代码。

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"/>

【讨论】:

  • 在尝试后它似乎确实有效,但是如果可能的话,我想找到一个更可靠的答案,因为我担心我们是否在移动设备上(因为悬停)或在一个模态(可能丢失“body”上下文),或者鼠标离开页面,这是插件的一部分,所以我需要它在所有场景中工作。
  • 对于移动设备,据我所知没有标签,所以:focus 会注意这一点。 :hover 不需要在body 上,它可以在任何父级,甚至多个父级上。但是,除非它在 ​​iframe 中,否则 body 上下文不会丢失,因为所有元素都应该是 body 的子元素。
【解决方案3】:

您可以在元素上设置动画,以自己的速度改变元素状态。

这里的技巧是得到一个动画:

  • 不是真正的动画,因为属性值没有变化。这是通过设置 2 个具有相同值的不同关键帧来实现的。
  • 选中和未选中状态的动画相同。如果我们更改动画名称,则每次更改状态时都会重播动画。为此,我设置了一个具有 2 个不同部分的动画,一个具有旋转的元素,另一个具有未旋转的元素。我们使用一个部分或另一个部分将方向从正常变为反向。并设置一个初始延迟,使其仅使用后半部分。

我已尝试通过 javascript 重现您的场景,然后重新设置元素并设置检查状态。我不确定这是否等同于它。

在 sn-p 上按下按钮,它将从头开始交替渲染元素,一次处于选中状态,另一个处于未选中状态

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>

【讨论】:

  • 这似乎有效,虽然比我希望的要重一些。你能更准确地解释一下动画发生了什么吗?是否只是以与过渡相反的方式旋转它以消除旋转或什么,它是如何让它保持“静止”的?
  • 我已经编辑了答案。我希望现在更清楚,但有点难以解释。另外,我已经修复了时间,现在我原来的缺点不再是问题了。
【解决方案4】:

这似乎是 Chrome/Webkit 的一个错误。至少在我的 Chrome 和 Safari 版本中,我的行为如下:

  • html 中没有任何 script 标签或 css 链接前的 script 标签或完全空的 script 标签,并且如果没有任何 input 元素,div 或其他非输入元素上不会发生过渡。

  • html 中没有任何 script 标签或 css 链接前的 script 标签或完全空的 script 标签,如只要有一个输入元素(无论哪种类型),所有样式与默认值不匹配的元素都会被转换。

  • 如果在 css 链接后添加 script 标签,其中至少有一个空格,则加载任何元素时都不会发生转换。

所以看起来 input 元素触发了某种布局刷新,奇怪的是,当脚本存在时不会发生这种情况。可能仅仅是因为解析中某处的延迟,或者某处设置错误的条件。至少这是我使用 Chrome 和 Safari 的行为。

所以你可以简单地添加:

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

在你 link 元素之后,你不会得到你描述的行为。这不是一个 CSS 解决方案,但问题似乎与你的 CSS 无关,所以我还是发布了它。

【讨论】:

    【解决方案5】:

    是否需要连接到外部样式表?您可能可以在 html 文件本身中使用 &lt;style&gt; 标记。如果没有,请确保 &lt;link&gt; 在标题中,以便它首先加载,以便在页面加载后立即应用 CSS。

    【讨论】:

    • 是的,它需要能够加载外部样式表,因为它将是插件的一部分,因此最终用户可以根据需要加载它。它在标题中,不幸的是没有解决问题。不过谢谢。
    【解决方案6】:

    有点骇人听闻,但只满足 css 要求。 对具有选中属性的元素进行一次性“动画”:

    input.flipCheckbox[checked]{
      animation-name: fakeRotate;
      animation-duration: 0.1s; 
      animation-iteration-count: 1;
    }
    @keyframes fakeRotate {
      from {
        transform: rotatey(180deg);
      }
      to {
        transform: rotatey(180deg);
      }
    }
    

    【讨论】:

      猜你喜欢
      • 2014-04-08
      • 2022-09-28
      • 1970-01-01
      • 2020-07-08
      • 2020-05-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-08-15
      相关资源
      最近更新 更多