css 如何平滑动画隐藏侧边栏的影响大小的其他领域

xa9qqrwz  于 2022-12-27  发布在  其他
关注(0)|答案(2)|浏览(217)

我的屏幕有3个水平对齐的主要区域:

侧边栏(1)可以折叠/隐藏(向左)。当隐藏时,释放的空间将提供给可视化(3),而菜单宽度(2)保持不变。
ATM我将内容排列如下:

*(1)、(2)和(3)的父容器:display: flex
***(1):**一米一分一秒
***(2):**一米二米一
***(3):**一米三分一秒

当折叠时,我只是为侧边栏设置width: 0
我知道我可以简单地动画/转换width更改,或者通过更改和动画/转换left属性或使用边距等来实现,但我能想到的所有这些解决方案都会触发浏览器布局步骤(更改widthleftmargin...),我希望避免这种情况,因为如here所述,这会导致动画性能下降。
理想情况下,我想保持与CSS过渡的属性,只触发浏览器组成的步骤,如translate等。
不幸的是,我想不出一种方法,既能使用那些“好的”CSS属性,又能满足我的目标,即把从隐藏的侧边栏释放的空间重新分配到可视化(3)。
有没有可能隐藏左边的边栏而不触发重新布局,但仍然重新分配释放的空间?如果没有,如何仍然可以做到这一点?
我想这是一个相当常见的用例在网络开发,所以链接到相应的文献,博客等是受欢迎的!
我在网上找到了很多关于隐藏边栏动画的例子,但是它们要么是对width属性进行动画处理,要么是没有将释放的空间重新分配给剩下的可见内容(例如,边栏只是简单地显示在主内容的“上方”等),所以到目前为止,我找到的例子都没有达到我所描述的目标......

yizd12fk

yizd12fk1#

请检查下面的HTMLJSCSS代码片段。您可以更改元素的实际宽度以完全匹配您需要的宽度。
操作侧边栏的width不是问题,性能是问题,正如您提供的link中所解释的那样,本文的最后一行是这样写的:
性能对用户来说很重要。Web开发人员需要构建React迅速、渲染流畅的应用程序。Google性能MavenPaul Lewis将帮助您消除jank,并创建性能保持在每秒60帧的Web应用程序。您将带着分析应用程序和确定jank原因所需的工具离开本课程。您将探索浏览器"的渲染管道,并发现有助于轻松构建高性能应用程序的模式。
因此,您可以使用JavascriptrequestAnimationFrame重新创建以下示例的逻辑,如here所示。

const side = document.querySelector('.side');
const sideToggle = document.querySelector('.sideToggle');
const main = document.querySelector('.main');
sideToggle.addEventListener('click', () => {
  if (!sideToggle.classList.contains('active')) {
    sideToggle.classList.add('active');
  } else {
    sideToggle.classList.remove('active');
  }

  if (!main.classList.contains('full')) {
    main.classList.add('full');
  } else {
    main.classList.remove('full');
  }
  if (!side.classList.contains('hidden')) {
    side.classList.add('hidden');
  } else {
    side.classList.remove('hidden');
  }
});
.container {
  display: inline-flex;
  flex-direction: row;
  align-items: stretch;
  align-content: space-evenly;
  justify-content: space-evenly;
  width: 100%;
}

.side {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  align-content: space-evenly;
  justify-content: space-evenly;
  background: #000;
  padding: 0;
  width: 20%;
  height: 100vh;
  transition: width 1s linear;
}

.side a {
  color: #fff;
  text-decoration: none;
  line-height: 1;
  height: 1.5rem;
  padding: 1rem;
}

.side a:hover {
  color: #000;
  background: #fff;
}

.side.hidden {
  width: 0;
  transition: width 1s linear;
}

.sideToggle {
  background: #000;
  color: #fff;
  width: 2rem;
  height: 2rem;
  position: fixed;
  right: .75rem;
  bottom: .75rem;
  border-radius: 50%;
  text-align: center;
  cursor: pointer;
  z-index: 1001;
}

.sideToggle:after {
  content: "\2630";
  font-size: 1.25rem;
  vertical-align: top;
}

.sideToggle.active:after {
  content: "\00D7";
  vertical-align: top;
  font-size: 1.75rem;
}

.main {
  background: red;
  width: 80%;
  height: 100vh;
  transition: width 1s linear;
  display: inline-flex;
  flex-direction: row;
  align-items: stretch;
  align-content: space-evenly;
  justify-content: space-evenly;
  width: 100%;
  color: #fff;
}

.main.full {
  width: 100%;
  transition: width 1s linear;
}

.left {
  width: 15rem;
  padding: 1rem;
}

.right {
  width: calc(100% - 15rem);
  background: indigo;
  padding: 1rem;
}
<div class="container">
  <div class="side">
    <a href="#">Home</a>
    <a href="#">Page 1</a>
    <a href="#">Page 2</a>
    <a href="#">Page 3</a>
  </div>
  <span class="sideToggle active"></span>
  <div class="main">
    <div class="left">
        this width is ment to be static
    </div>
    <div class="right">
        this width is ment to be dynamic 
    </div>
  </div>
</div>

这是另一种可能的方法,主要使用translateX,而不更改侧边栏的width
一个一个三个一个一个一个一个一个四个一个一个一个一个一个五个一个

nhaq1z21

nhaq1z212#

尽管user 2560539的解决方案很好,但它并不能满足我的要求,因为内容区域中有很多元素,对侧栏宽度的操作肯定会导致性能问题。
问题是,一旦你开始转换几何或位置属性(宽度、高度、边距、填充、上、左、下、右等),浏览器就会开始一次又一次地为动画中的每一帧重新计算布局。你可以在Chrome或Firefox的性能选项卡中看到这一点,即“布局偏移”。一旦你的DOM包含了很多节点,这就变得超级滞后了。
变换(平移、旋转、倾斜等)的速度要快得多,因为浏览器不需要一遍又一遍地计算所有关于几何和位置的值。浏览器以每个像素为基础计算所有内容。
所以我想出了另一个解决办法。我所做的是使用快速

transform: scaleX(1.1); //e.g. 1920px / 1745px

CSS属性来放大内容区域。因子1.1是由整个内容区域(不可见边栏)的宽度除以压缩内容区域(可见边栏)计算得出的。
记住这一点,你可以使用一个简单的翻译动画来翻译侧边栏和缩放内容区域。这里是一个codepen [从user 2560539那里偷来的,谢谢:)]:
https://codepen.io/enne87/pen/MWBaOrp
当然,内容会被扭曲,因为scaleX不仅缩放内容 Package 器,而且缩放它的所有子元素。如果这对你来说是个问题,你可以向扭曲的元素添加一个CSS类,它包含scaleX操作的逆操作:

.make-thinner-initally {
    transform: scaleX(0.9088); //e.g. 1745px / 1920px
}

动画一开始就将此类添加到元素中,动画结束后将其移除。
顺便说一下,Google Calendar在展开/折叠左侧栏时使用了非常类似的方法。

相关问题