65 votes

Utilisation des transitions CSS dans la mise en page de la grille CSS

J'essaie de faire en sorte que mon en-tête adhésif ait un effet de transition pour qu'il s'installe en douceur plutôt que de se contenter d'un mouvement brusque.

Qu'est-ce que je fais de mal ?

Voici ma version de travail :

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

En gros, le code suivant ajoute la classe tiny à ma classe wrapper, cela fonctionne bien.

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

Voici la partie 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;
}

L'en-tête se rétrécit comme il se doit, mais il n'y a pas d'animation. Ai-je manqué quelque chose ou les transitions ne fonctionnent-elles tout simplement pas avec la grille ?

Voici un lien vers la documentation sur les grilles css.

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>

59voto

Michael_B Points 15556

Selon la spécification, les transitions doivent fonctionner sur grid-template-columns y grid-template-rows .

7.2. Dimensionnement explicite des voies : le grid-template-rows et grid-template-columns propriétés

Animable : comme une simple liste de longueur, de pourcentage, ou de calc, à condition que les seules différences sont les valeurs des éléments longueur, pourcentage ou calc. dans la liste

Donc, si mon interprétation est correcte, tant que les seules modifications portent sur les valeurs des propriétés, sans changement de la structure de la règle, les transitions devraient fonctionner. Mais ils ne le font pas. .


UPDATE

Cela fonctionne mais n'est pour l'instant implémenté que dans Firefox. Suivez ici pour les mises à jour des autres navigateurs. https://codepen.io/matuzo/post/animating-css-grid-layout-properties

~ une contribution dans les commentaires par @bcbrian


Voici un test que j'ai créé :

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>

Démonstration de jsFiddle

Dans le test, la transition fonctionne sur la hauteur et la couleur d'arrière-plan, mais pas sur les éléments suivants grid-template-rows o grid-template-columns .

14voto

Erik Points 89

Comme solution de contournement, vous pouvez travailler avec la taille des éléments de la grille à la place avec grid-template-columns o grid-template-rows .

Vous pourriez le faire :

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>

Voici un autre exemple de 2x2 : https://codepen.io/erik127/pen/OvodQR

et ici un exemple plus étendu où vous pouvez ajouter plus de colonnes ou de lignes : https://codepen.io/erik127/pen/rdZbxL

Malheureusement, il y a beaucoup de javascript, ce serait bien si grid-template-columns y grid-template-rows serait animable.

Une autre solution qui pourrait fonctionner dans certains cas (si les éléments de votre grille ne s'étendent pas sur plusieurs lignes) est l'utilisation de flexbox avec une grille.

9voto

Pep Santacruz Points 181

J'ai utilisé GSAP pour animer les propriétés grid-template-columns et 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>

7voto

Emre HIZLI Points 121

Pour l'instant, la transition sur le modèle de grille ne fonctionne pas. Mais vous pouvez utiliser la transformation comme ceci :

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>

2voto

MrRioku Points 523

Une autre approche consiste à utiliser transform . En fait, il pourrait même être meilleur parce que la transformation avec l'opacité peut atteindre 60fps parce qu'il est accéléré par le GPU au lieu de l'accélération du CPU (le navigateur doit faire moins de travail).

Voici un exemple : 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; }
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X