【问题标题】:Using CSS transitions in CSS Grid Layout在 CSS 网格布局中使用 CSS 过渡
【发布时间】:2017-10-10 05:56:36
【问题描述】:

我正在尝试让我的粘性标题具有过渡效果,以便它缓和而不仅仅是快速移动。

我做错了什么?

这是我的工作版本:

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

基本上,下面的代码将类 tiny 添加到我的包装类中,这工作正常。

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

这是 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;
}

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

这是 css-grid 文档的链接。

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>

【问题讨论】:

    标签: css css-transitions css-grid


    【解决方案1】:

    经过数小时的反复试验,我终于找到了一种为网格列设置动画的方法。 这会导致列间距变为 0,并且悬停的字段扩大其宽度。

    这是我目前得到的:

    $('.cards').each(function(){
      let cols = window.getComputedStyle($(this).get(0));
      let colGapAmount = cols.getPropertyValue("grid-template-columns").split(" ").length - 1;
      let card = $(this).find('.card');
      let standardColWidth = parseInt(card.css('width'), 10);
      let colGapSpace = colGapAmount * parseInt($(this).css('column-gap'), 10);
      let newSize = (standardColWidth + colGapSpace) + 'px';
      //Set Values
      $(this).closest('.cards').get(0).style.setProperty('--scaledSize', newSize);
      $(this).closest('.cards').get(0).style.setProperty('--normalSize', standardColWidth + 'px');
    });
    
    $('.card').hover(function(){
      $(this).closest('.cards').addClass('noGap');
    },
    function(){
      $(this).closest('.cards').removeClass('noGap');
    });
    .cards {
         --normaleSize: 100%;
         --scaledSize: unset;
         display: grid;
         grid-template-columns: 1fr 1fr 1fr 1fr 1fr;
         column-gap: 20px;
         transition: column-gap 1s ease-in-out;
    }
     .cards .card {
         transition: width 1s ease-in-out;
         border: 1px solid black;
         width: var(--normalSize);
    }
     .cards .card:hover {
         width: var(--scaledSize);
    }
     .cards.noGap {
         column-gap: 0px;
    }
     
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <section class="cards">
      <div class="card">1</div>
      <div class="card">2</div>
      <div class="card">3</div>
      <div class="card">4</div>
      <div class="card">5</div>
    </section>
    
    <section class="cards" style="margin-top: 3rem">
      <div class="card">1</div>
      <div class="card">2</div>
      <div class="card">3</div>
      <div class="card">4</div>
      <div class="card">5</div>
    </section>

    【讨论】:

      【解决方案2】:

      我找到了一种解决方法,但它要求至少有一个其他列填满宽度。要转换的列必须是grid-template-columns 中的auto。另一个必须是1fr,否则auto 列将使用这个缺失的空间。此外,要转换的列在两种状态下都必须具有绝对宽度。

      这里是:

      CodePen

      document.querySelector('.js-button').addEventListener('click', function() {
        document.querySelector('.js-grid').classList.toggle('grid--full')
      })
      .grid {
        display: grid;
        grid-template-columns: 1fr auto 1fr;
        grid-template-rows: 100px;
        grid-gap: 20px;
        transition: all 1s;
      }
      
      .item {
        background-color: #D73B38;
        color: #ffffff;
        padding: 10px;
        border-radius: 5px;
        border: none;
        transition: 1s;
      }
      
      .grid .item:nth-child(3n + 2) {
        width: 200px;
        background: blueviolet; 
      }
      .grid--full .item:nth-child(3n + 2) {
        width: 300px;
        background: cadetblue;
      }
      
      button {
        background-color: #123456;
        color: #ffffff;
        margin: 2rem 0;
        padding: 1.4rem;
        border: none;
        border-radius: 5px;
        text-transform: uppercase;
        font-size: 1.2rem;
      }
      <p>Fork from <a href="https://codepen.io/matuzo/pen/rmQvMG">Manuel Matuzovic</a></p>
      
      <button class="js-button">Animate</button>
      
      <div class="grid js-grid">
        <article class="item">
          <h2>Element 1</h2>
        </article>
        <article class="item">
          <h2>Element 2</h2>
        </article>
        <article class="item">
          <h2>Element 3</h2>
        </article>
        <article class="item">
          <h2>Element 4</h2>
        </article>
        <article class="item">
          <h2>Element 5</h2>
        </article>
        <article class="item">
          <h2>Element 6</h2>
        </article>
      </div>

      它使用选择器:nth-child(3n + 2) 在网格的所有列中执行此操作。但如果您只想更改网格的一个块,也可以使用。

      【讨论】:

        【解决方案3】:

        我使用 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>

        【讨论】:

        • 可惜他们的执照不是麻省理工学院
        • @Alter 如果是这样,那么它将像无数其他工具一样无人维护:) GSAP 已经存在 很长 时间了,这要归功于它的许可。 greensock.com/licensing
        【解决方案4】:

        在我的例子中,我尝试使用以下代码打开侧边栏菜单:

        .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;
        }
        

        过渡不适用于网格模板列。这是我的解决方案:

        .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;
        }
        

        也许,它可以帮助某人。

        【讨论】:

          【解决方案5】:

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

          jsFiddle

          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>

          【讨论】:

            【解决方案6】:

            作为一种解决方法,您可以使用网格项的大小来代替grid-template-columnsgrid-template-rows

            你可以这样做:

            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>

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

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

            不幸的是,它有很多 javascript,如果 grid-template-columnsgrid-template-rows 可以动画就好了。

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

            【讨论】:

            • 请不要发布只链接到外部网站的答案;当这些网站出现故障时,您的答案对读者就失去了用处!
            • 感谢@TylerH,我在答案中添加了coden-p。
            • 2x2 示例是该线程中唯一正确的答案。顺便说一句,我使用(无处不在)auto 而不是1fr。使用转换进行类切换也对我有用。
            【解决方案7】:

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

            这是一个例子: 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; }
            }
            

            【讨论】:

              【解决方案8】:

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

              7.2. Explicit Track Sizing: the grid-template-rows and grid-template-columns properties

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

              所以,如果我的解释是正确的,只要唯一的变化是属性的值,规则的结构没有变化,转换应该可以工作。 但他们没有


              更新

              这确实有效,但目前只在 Firefox 中实现。关注这里 其他浏览器更新。 https://codepen.io/matuzo/post/animating-css-grid-layout-properties

              ~@bcbrian在 cmets 中的贡献


              这是我创建的一个测试:

              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

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

              【讨论】:

              • 嗨,迈克尔,感谢您的回答。尽管您的背景是动画的,但您的网格框不是。我设法通过给每个选定的 div 一个高度标签并基本上覆盖该 div 的网格模板列来使框动画化,它可以工作,但它更像是一种 hack。
              • 是的,过渡只对高度和背景颜色起作用。这就是我的回答(见最后一句话,在代码 sn-p 下方)。
              • 错过了那部分。我会将其标记为已回答,因为我们无法继续使用它。
              • 也就是说,一般来说网格列/行不会有任何动画,还是仍在进行中?如果是这样,有人会如何使用 CSS 网格?如果你不能有过渡,这样你就可以在一个统一的解决方案中制作动画侧边栏等,那有什么意义呢?如果它仍在进行中,是否有任何文章说明他们何时会认为这会完成?谢谢
              • 这确实有效,但目前仅在 Firefox 中实现。在此处关注其他浏览器更新。 codepen.io/matuzo/post/animating-css-grid-layout-properties
              猜你喜欢
              • 1970-01-01
              • 2021-05-03
              • 2020-03-30
              • 1970-01-01
              • 2014-01-18
              • 1970-01-01
              • 1970-01-01
              • 2017-09-16
              相关资源
              最近更新 更多