在 CSS 网格布局中使用 CSS 过渡

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/43911880/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 12:33:17  来源:igfitidea点击:

Using CSS transitions in CSS Grid Layout

csscss-transitionscss-grid

提问by Dan

I am trying to get my sticky header to have a transition effect so it eases in rather than just a snap movement.

我试图让我的粘性标题具有过渡效果,因此它可以减轻而不仅仅是快速移动。

What am I doing wrong?

我究竟做错了什么?

Here's my a working version:

这是我的工作版本:

http://codepen.io/juanmata/pen/RVMbmr

http://codepen.io/juanmata/pen/RVMbmr

Basically the following code adds the class tiny to my wrapper class, this works fine.

基本上下面的代码将类 tiny 添加到我的包装类中,这很好用。

$(window).on('load', function() {
    $(window).on("scroll touchmove", function () {
        $('.wrapper').toggleClass('tiny', $(document).scrollTop() > 0);
    });
});

Here's the CSS part:

这是 CSS 部分:

.wrapper {
    grid-template-rows: 80px calc(75vh - 80px) 25vh 80px;
    -o-transition: all 0.5s;
    -moz-transition: all 0.5s;
    -webkit-transition: all 0.5s;
    transition: all 0.5s;
}
.tiny {
    grid-template-rows: 40px calc(75vh - 40px) 25vh 80px;
}

So the header does shrink as it should but there is no animation, have I missed something or does transitions simply not work with grid?

所以标题确实缩小了,但没有动画,我错过了什么还是过渡根本不适用于网格?

Here's a link to the css-grid docs.

这是 css-grid 文档的链接。

https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout

https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout

$(window).on('load', function() {
  $(window).on("scroll touchmove", function() {
    $('.wrapper').toggleClass('tiny', $(document).scrollTop() > 0);
  });
});
* {
 margin:0;
 padding:0;
}

.wrapper {
 display: grid;
 grid-gap: 0px;
 grid-template-columns: 1fr 1fr 1fr 1fr;
 grid-template-rows: 80px calc(75vh - 80px) 25vh 80px;
 grid-template-areas:
  "head head head head"
  "main main main main"
  "leader leader leader leader"
  "foot foot foot foot";
 background-color: #fff;
 color: #444;
}
.tiny {
 grid-template-rows: 40px calc(75vh - 40px) 25vh 80px;
}
.box {
 background-color: #444;
 color: #fff;
 border-radius: 5px;
 font-size: 150%;
}
.box .box {
 background-color: lightcoral;
}

.head {
 grid-area: head;
 background-color: #999;
 z-index: 2;
 display: grid;
 grid-gap: 0px;
 grid-template-columns: 20% 1fr;
 -o-transition: all 0.5s;
 -moz-transition: all 0.5s;
 -webkit-transition: all 0.5s;
 transition: all 0.5s;
 position: sticky;
 top: 0;
}

.logo{
        height: inherit;
        grid-column: 1;
        grid-row: 1;
        background-color:red;
        position: relative;
        overflow: hidden;
    }
.logo img {
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        display: block;
        max-width: 100%;
        height: auto;
    }
.main {
 grid-area: main;
 /* CSS Grid */
 z-index: 1;
 grid-column: head-start / head-end;
 grid-row: head-start / leader-start;
 background-color: red;
}
.leader {
 grid-area: leader;
 z-index:1;
 display: grid;
 grid-gap: 0px;
 grid-template-columns: repeat(4, 1fr  );
}
.foot {
 grid-area: foot;
 z-index:1;
}
<div class="wrapper">
  <div class="box head">
    <div class="box logo">
      <a href="#"><img src="https://unsplash.it/200/300/?random" /></a>
    </div>
    <div class="box nav">nav</div>
  </div>
  <div class="box main">main</div>
  <div class="box leader">
    <div class="box leader-1">1</div>
    <div class="box leader-2">2</div>
    <div class="box leader-3">3</div>
    <div class="box leader-4">4</div>
  </div>
  <div class="box foot">foot</div>
</div>

采纳答案by Michael Benjamin

According to the spec, transitions should work on grid-template-columnsand grid-template-rows.

根据规范,转换应该适用于grid-template-columnsgrid-template-rows

7.2. Explicit Track Sizing: the grid-template-rowsand grid-template-columnsproperties

Animatable:as a simple list of length, percentage, or calc, provided the only differences are the values of the length, percentage, or calc components in the list

7.2. Explicit Track Sizing: thegrid-template-rowsgrid-template-columns属性

Animatable:作为长度、百分比或计算的简单列表,提供的唯一区别是列表中的长度、百分比或计算组件的值

So, if my interpretation is correct, as long as the only changes are to the values of the properties, with no changes to the structure of the rule, transitions should work. But they don't.

所以,如果我的解释是正确的,只要唯一的变化是属性的值,规则的结构没有变化,过渡就应该起作用。但他们没有



UPDATE

更新

This does work but is so far only implemented in Firefox. Follow here for other browser updates. https://codepen.io/matuzo/post/animating-css-grid-layout-properties

这确实有效,但目前仅在 Firefox 中实现。按照此处获取其他浏览器更新。 https://codepen.io/matuzo/post/animating-css-grid-layout-properties

~ a contribution in the comments by @bcbrian

~ @bcbrian在评论中的贡献



Here's a test I created:

这是我创建的一个测试:

grid-container {
  display: inline-grid;
  grid-template-columns: 100px 20vw 200px;
  grid-template-rows: repeat(2, 100px);
  background-color: black;
  height: 230px;
  transition: 2s;
  
  /* non-essential */
  grid-gap: 10px;
  padding: 10px;
  box-sizing: border-box;
}

grid-container:hover {
  grid-template-columns: 50px 10vw 100px;
  grid-template-rows: repeat(2, 50px);
  background-color: red;
  height: 130px;
  transition: 2s;
}

grid-item {
  background-color: lightgreen;
}
<grid-container>
  <grid-item></grid-item>
  <grid-item></grid-item>
  <grid-item></grid-item>
  <grid-item></grid-item>
  <grid-item></grid-item>
  <grid-item></grid-item>
</grid-container>

jsFiddle demo

jsFiddle 演示

In the test, the transition works on the height and background color, but not on grid-template-rowsor grid-template-columns.

在测试中,过渡适用于高度和背景颜色,但不适用于grid-template-rowsgrid-template-columns

回答by Erik

As a workaround, you can work with the size of the grid items instead with grid-template-columnsor grid-template-rows.

作为一种解决方法,您可以使用grid-template-columns或来处理网格项目的大小grid-template-rows

You could do:

你可以这样做:

grid-container {
  display: inline-grid;
  grid-template-columns: 100px 20vw 200px;
  background-color: black;
  height: 230px;
  transition: 2s;
  
  /* non-essential */
  grid-gap: 10px;
  padding: 10px;
  box-sizing: border-box;
}

grid-container:hover {
  background-color: red;
  height: 130px;
}

grid-item {
  height: 100px;
  transition: height 2s;
  background-color: lightgreen;
}

grid-container:hover .first-row {
  height: 25px;
}

grid-container:hover .last-row {
  height: 75px;
}
<grid-container>
  <grid-item class='first-row'></grid-item>
  <grid-item class='first-row'></grid-item>
  <grid-item class='first-row'></grid-item>
  <grid-item class='last-row'></grid-item>
  <grid-item class='last-row'></grid-item>
  <grid-item class='last-row'></grid-item>
</grid-container>

Here's another 2x2 example: https://codepen.io/erik127/pen/OvodQR

这是另一个 2x2 示例:https: //codepen.io/erik127/pen/OvodQR

and here a more extensive example where you can add more columns or rows: https://codepen.io/erik127/pen/rdZbxL

这是一个更广泛的示例,您可以在其中添加更多列或行:https: //codepen.io/erik127/pen/rdZbxL

Unfortunately it's a lot of javascript, it would be nice if grid-template-columnsand grid-template-rowswould be animatable.

不幸的是,它有很多 javascript,如果grid-template-columns并且grid-template-rows是可动画的,那就太好了。

Another alternative which might work in some usecases (if your grid items don't span multiple rows) is the use of flexbox together with a grid.

另一种可能适用于某些用例(如果您的网格项不跨越多行)的替代方法是将 flexbox 与网格一起使用。

回答by Pep Santacruz

I used GSAP to animate the grid-template-columns and grid-template-rows properties:

我使用 GSAP 为 grid-template-columns 和 grid-template-rows 属性设置动画:

function changeGridTemplateColumns(pattern) {
  TweenMax.to(".container",
    1, {
      gridTemplateColumns: pattern
    }
  );
}

function changeGridTemplateRows(pattern) {
  TweenMax.to(".container",
    1, {
      gridTemplateRows: pattern
    }
  );
}

$(document).ready(
  function() {
    $(".el-a,.el-b,.el-c").mouseenter(
      function() {
        changeGridTemplateRows("2fr 1fr");
      }
    );
    $(".el-d,.el-e,.el-f").mouseenter(
      function() {
        changeGridTemplateRows("1fr 2fr");
      }
    );

    $(".el-a,.el-d").mouseenter(
      function() {
        changeGridTemplateColumns("2fr 1fr 1fr");
      }
    );

    $(".el-b,.el-e").mouseenter(
      function() {
        changeGridTemplateColumns("1fr 2fr 1fr");
      }
    );

    $(".el-c,.el-f").mouseenter(
      function() {
        changeGridTemplateColumns("1fr 1fr 2fr");
      }
    );

    $(".container").mouseleave(
      function() {
        changeGridTemplateColumns("1fr 1fr 1fr");
        changeGridTemplateRows("1fr 1fr");
      }
    );
  }
);
.container {
  width: 50vw;
  height: 50vw;
  margin: auto;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: repeat(2, 1fr);
  grid-template-areas: "a b c" "d e f";
}

.el-a {
  grid-area: a;
  background-color: skyblue;
}

.el-b {
  grid-area: b;
  background-color: darkseagreen;
}

.el-c {
  grid-area: c;
  background-color: coral;
}

.el-d {
  grid-area: d;
  background-color: gold;
}

.el-e {
  grid-area: e;
  background-color: plum;
}

.el-f {
  grid-area: f;
  background-color: beige;
}
<script src="https://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/2.0.2/TweenMax.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div class="container">
  <div class="el-a"></div>
  <div class="el-d"></div>
  <div class="el-b"></div>
  <div class="el-e"></div>
  <div class="el-c"></div>
  <div class="el-f"></div>
</div>

回答by Emre HIZLI

For now the transition on the grid template is not working. But you can use transform like this:

现在网格模板上的过渡不起作用。但是你可以像这样使用转换:

jsFiddle

js小提琴

var button = document.querySelector("#btnToggle");
button.addEventListener("click",function(){
 var content = document.querySelector(".g-content");
  if(content.classList.contains("animate"))
    content.classList.remove("animate");
  else
   content.classList.add("animate");
});
html,body{
  width:100%;
  height:100%;
  padding:0;
  margin:0;
}

.g-content{
  display:grid;
  height:100%;
  grid-template-columns: 200px 1fr;
  grid-template-rows:60px 1fr 30px;
  grid-template-areas: 
    "g-header g-header"
    "g-side g-main"
    "g-footer g-footer";
 overflow-x:hidden;
}

.g-header{
  grid-area:g-header;
  background:#2B4A6B;
  display:grid;
  grid-template-columns: max-content 1fr;
}

.g-header button{
  align-self:center;
  margin:0 5px;
}

.g-side{
  grid-area:g-side;
  background:#272B30;
  transition:all 0.5s;
}

.g-main{
  grid-area:g-main;
  background:#FFFFFA;
  transition:all 0.5s;
}

.g-footer{
  grid-area:g-footer;
  background:#7E827A
}

.animate .g-main{
  width:calc(100% + 200px);
  transform:translateX(-200px);
}

.animate .g-side{
  transform:translateX(-200px);
}  
<div class="g-content">
  <div class="g-header">
    <button id="btnToggle">
    Toggle
    </button>
  </div>
  <div class="g-side">
  </div>
  <div class="g-main">
  test
  </div>
  <div class="g-footer">
  </div>
</div>

回答by Dmitry Grinko

In my case I was trying to open sidebar-menu by using this code:

就我而言,我试图使用以下代码打开侧边栏菜单:

.wrapper{
  display: grid;
  grid-template-columns: 0 100%;
  transition: all 1s;
  .sidebar{
    background-color: blue;
  }
  .content{
    background-color: red;
  }
}
.wrapper.sidebar-open{
  grid-template-columns: 300px 100%;
  transition: all 1s;
}

but transition was not working for grid-template-columns. This is my solution:

过渡不适用于 grid-template-columns。这是我的解决方案:

.wrapper{
  display: grid;
  grid-template-columns: auto 100%;
  .sidebar{
    width: 0;
    background-color: blue;
    transition: all 1s;
  }
  .content{
    background-color: red;
  }
}
.sidebar.sidebar-open{
  width: 300px;
  transition: all 1s;
}

Perhaps, it helps someone.

也许,它可以帮助某人。

回答by Oneezy

Another approach is to use transform. It actually might even be better because transform along w/ opacity can achieve 60fps because it's GPU accelerated instead of CPU accelerated (browser has to do less work).

另一种方法是使用transform. 它实际上甚至可能更好,因为沿不透明度变换可以达到 60fps,因为它是 GPU 加速而不是 CPU 加速(浏览器必须做的工作更少)。

here's an example:https://codepen.io/oneezy/pen/YabaoR

这是一个例子:https : //codepen.io/oneezy/pen/YabaoR

.sides {
  display: grid;
  grid-template-columns: 50vw 50vw;
}

.monkey { animation: 0.7s monkey cubic-bezier(.86,0,.07,1) 0.4s both; }
.robot { animation: 0.7s robot cubic-bezier(.86,0,.07,1) 0.4s both; }

@keyframes monkey {
  0% { transform: translate(-50vw); }
  100% { transform: 0; }
}

@keyframes robot {
  0% { transform: translate(50vw); }
  100% { transform: 0; }
}

回答by Micha? Smoczyński

There is a way to resize grid elements on transition using only CSS, but if you want to resize it, you should use %'s properly, but in your examples problem exists because of sticky position. You have to add height on your .headelement and then change height after adding .tinyclass. Here you can check how I fixed it ( I guess that's the result which you wanted to have ):

有一种方法可以仅使用 CSS 在过渡时调整网格元素的大小,但是如果您想调整它的大小,您应该正确使用 %,但在您的示例中,由于位置粘滞而存在问题。您必须在.head元素上添加高度,然后在添加.tiny类后更改高度。在这里你可以检查我是如何修复它的(我想这就是你想要的结果):

Fiddle

小提琴

Michael answer should use %'s in your example because right now it has "blink" effect on hover, if changed to values from px on %'s it will work perfectly on resize. Here is that example changed on %'s:

迈克尔的回答应该在您的示例中使用 %'s 因为现在它在悬停时具有“闪烁”效果,如果更改为 %'s 上的 px 值,它将在调整大小时完美运行。这是在 % 上更改的示例:

Fiddle

小提琴