容器的 CSS 翻译 X 在 Safari 中不起作用



今天,我注意到 Safari (9.0) 的一个奇怪行为,当我对在 X 轴上平移的元素应用过渡时,宽度也在增加。

我已经在这个 JsFiddle 中重现了这种行为。这是一个嵌入代码,适合那些更喜欢它的人。在Firefox和Chrome中,它看起来非常流畅,但在Safari中则不然,有没有人有解决方案或最佳方法来达到相同的效果

var button = document.getElementsByTagName('button')[0],
	container = document.getElementsByTagName('div')[0];
    
button.addEventListener('click', function() { container.classList.toggle('open'); });
.container {
  width: 100%;
  overflow: hidden;
}
ul {
  display: block;
  width: 100%;
  padding: 0;
  margin: 0;
  transition: width 1s, transform 1s;
}
.open ul {
  width: 200%;
  transform: translateX(-50%);
}
li {
  /* Just some style first */
  font-family: sans-serif;
  color: #fff;
  text-align: center;
  text-transform: uppercase;
  background-color: red;
  padding: 1em 0;
  
  display: inline-block;
  width: calc(50% - 4px);
}
li:first-child {
  background-color: green;
}
<div class="container">
  <ul>
    <li>Test</li>
    <li>Test</li>
  </ul>
</div>
<button type="button">Toggle translation</button>

重新发布作为答案。

这是jsFiddle结果和片段,如下所示:

var button = document.getElementsByTagName('button')[0];
var container = document.getElementsByTagName('div')[0];
var timeline = new TimelineMax({ paused: true });
timeline.to('ul', 1, { width: '200%', xPercent: -50, ease: Power2.easeInOut });
button.addEventListener('click', function() {
	timeline.progress() > 0 ? timeline.reverse() : timeline.play();
});
.container {
	width: 100%;
  overflow: hidden;
}
ul {
  display: block;
	width: 100%;
  padding: 0;
  margin: 0;
}
li {
  font-family: sans-serif;
  color: #fff;
  text-align: center;
  text-transform: uppercase;
  background-color: red;
	display: inline-block;
  padding: 1em 0;
  width: calc(50% - 4px);
}
li:first-child {
	background-color: green;
}
<script src="//cdnjs.cloudflare.com/ajax/libs/gsap/1.18.2/TweenMax.min.js"></script>
<div class="container">
  <ul>
    <li>Test</li>
    <li>Test</li>
  </ul>
</div>
<button type="button">Toggle translation</button>

希望这是有帮助的。

附言我已经使用 GSAP 有一段时间了,我不记得遇到过任何特定于浏览器的问题,除非浏览器会做一些不同的事情。对GSAP进行一些研究,它会告诉您浏览器兼容性是他们的主要卖点之一。

通过动画margin-left而不是translateX结果在 Safari 中是可以接受的:

var button = document.getElementsByTagName('button')[0],
		container = document.getElementsByTagName('div')[0];
    
button.addEventListener('click', function() {
	container.classList.toggle('open');
});
.container {
	width: 100%;
  overflow: hidden;
}
ul {
  display: block;
  width: 100%;
  padding: 0;
  margin: 0;
  transition: width 1s, margin-left 1s;
}
.open ul {
  width: 200%;
  margin-left:-100%;
}
li {
  font-family: sans-serif;
  color: #fff;
  text-align: center;
  text-transform: uppercase;
  background-color: red;
  
	display: inline-block;
  padding: 1em 0;
  width: calc(50% - 4px);
}
li:first-child {
	background-color: green;
}
<div class="container">
  <ul>
    <li>Test</li>
    <li>Test</li>
  </ul>
</div>
<button type="button">Toggle translation</button>

使用scaleX而不是动画width更流畅,但可能不是您想要的。

var button = document.getElementsByTagName('button')[0],
		container = document.getElementsByTagName('div')[0];
    
button.addEventListener('click', function() {
	container.classList.toggle('open');
});
.container {
	width: 100%;
  overflow: hidden;
}
ul {
  display: block;
	width: 100%;
  padding: 0;
  margin: 0;
  transition: transform 1s;
}
.open ul {
  transform: translateX(-50%) scaleX(2);
}
li {
  font-family: sans-serif;
  color: #fff;
  text-align: center;
  text-transform: uppercase;
  background-color: red;
  
	display: inline-block;
  padding: 1em 0;
  width: calc(50% - 4px);
}
li:first-child {
	background-color: green;
}
<div class="container">
  <ul>
    <li>Test</li>
    <li>Test</li>
  </ul>
</div>
<button type="button">Toggle translation</button>

因此,我将尝试在这里总结两个最佳解决方案:一个使用CSS转换,另一个使用Javascript动画(GSAP)。


CSS 转换

在性能方面,建议仅对变换(平移、缩放、旋转)和不透明度进行动画处理。如果您对更多优化细节感兴趣,可以查看Anna Migas的这篇文章。

因此,正如@Meiko建议的那样,最好的解决方案是仅对缩放和平移属性进行动画处理。下面是一个代码示例(和 JSFiddle)

var button = document.getElementsByTagName('button')[0],
  container = document.getElementsByTagName('div')[0];
button.addEventListener('click', function() {
  container.classList.toggle('open');
})
.container,
ul {
  width: 100%;
}
ul {
  overflow: hidden;
  
  /* reset default browser styles */
  padding: 0;
  margin: 0;
}
li {
  display: inline-block;
  width: calc(50% - 2px);
  position: relative;
  transition: transform 1s;
  
  /* Just some style */
  font-family: sans-serif;
  color: #fff;
  text-align: center;
  text-transform: uppercase;
  padding: 1em 0;
}
li::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  display: block;
  width: 100%;
  height: 100%;
  background-color: red;
  z-index: -1;
  transition: transform 1s;
}
li:first-child::before {
  background-color: green;
}
.open li:first-child {
  transform: translateX(-100%);
}
.open li:nth-of-type(2) {
  transform: translateX(-50%);
}
.open li:nth-of-type(2)::before {
  transform: scaleX(2);
}
<div class="container">
  <ul>
    <li>Test</li>
    <li>Test</li>
  </ul>
</div>
<button type="button">Toggle translation</button>

优点:

  • 只使用一点点Javascript来切换类,
  • 浏览器支持非常好(需要特定于供应商的属性和一些测试),
  • 在 GPU 内存上非常快速和轻巧。

缺点:

  • 在使用方面非常有限(第二个单元格的实际宽度保持不变),
  • 需要更多的CSS行。

JS动画(带GSAP)

此解决方案由 @Tahir Ahmed 提出,并使用 GSAP 库。作为旁注,我真的认为这是这种动画最好的js库。以下是它如何工作(和JSFiddle)的片段:

var button = document.getElementsByTagName('button')[0],
  timeline = new TimelineMax({ paused: true });
  
timeline.to('ul', 1, { width: '200%', xPercent: -50 });
button.addEventListener('click', function() {
  timeline.progress() > 0 ? timeline.reverse() : timeline.play();
})
.container {
  width: 100%;
  overflow: hidden;
}
ul {
  width: 100%;
  
  /* reset default browser styles */
  padding: 0;
  margin: 0;
}
li {
  display: inline-block;
  width: calc(50% - 2px);
  background-color: red;
  
  /* Just some style */
  font-family: sans-serif;
  color: #fff;
  text-align: center;
  text-transform: uppercase;
  padding: 1em 0;
}
li:first-child {
  background-color: green;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.18.2/TweenMax.min.js"></script>
<div class="container">
  <ul>
    <li>Test</li>
    <li>Test</li>
  </ul>
</div>
<button type="button">Toggle translation</button>

优点:

  • 真的很灵活,天空是极限!
  • 您可以对display等属性进行动画处理(在 CSS 中不能),
  • 与所有浏览器兼容(低至IE6)。

缺点:

  • 需要第三方库(约30kb),
  • 对于GPU来说似乎有点困难(尽管需要更多的测试才能确定)。

最后,这真的取决于你需要的动画,但如果它变得比移动容器复杂一点,那么我会选择 GSAP。

相关内容

  • 没有找到相关文章

最新更新