Coder Social home page Coder Social logo

animate-css-grid's Introduction

Animate CSS Grid

Performantly animate all CSS grid properties, including:

grid-column and grid-row

grid-column and grid-row

grid-template-columns

grid-template-columns

grid-gap

grid-gap

Why use animate-css-grid?

This library uses transforms to transition between different layout states, which means, in comparison to pure CSS animations, it offers:

  • better performance
  • more flexibility in terms of what properties can be animated
  • more configurable animations (easing options, staggers)

Want to have a look for yourself? Feel free to check out this Mondrian animated with CSS keyframes and compare it with the same UI animated with animate-css-grid.

How to use it

Just call the wrapGrid method on your grid container, and optionally provide a config object as a second argument. If the grid is removed from the page, the animations will automatically be cleaned up as well.

yarn add animate-css-grid or npm install animate-css-grid

import { wrapGrid } from 'animate-css-grid'

const grid = document.querySelector(".grid");
wrapGrid(grid);

Or from a script tag:

<script src="https://unpkg.com/animate-css-grid@latest"></script>

<script>
  const grid = document.querySelector(".grid");
  animateCSSGrid.wrapGrid(grid, {duration : 600});
</script>

Optional config object:

{
  // int: default is 0 ms
  stagger: 100,
  // int: default is 250 ms
  duration: 500,
  // string: default is 'easeInOut'
  easing: 'backInOut',
  // function: called with list of elements about to animate
  onStart: (animatingElementList)=> {},
  // function: called with list of elements that just finished animating
  // cancelled animations will not trigger onEnd
  onEnd: (animatingElementList)=> {}
}

Available easing functions:

  • 'linear'
  • 'easeIn' / 'easeOut' / 'easeInOut'
  • 'circIn' / 'circOut' / 'circInOut'
  • 'backIn' / 'backOut' / 'backInOut'
  • 'anticipate'

Learn more about available easing functions here.

Two functions are returned by the wrapGrid call that you probably won't need to use:

import { wrapGrid } from animateCSSGrid

const grid = document.querySelector(".grid");
const { unwrapGrid, forceGridAnimation } = wrapGrid(grid);

// if you want the grid to transition after updating an inline style
// you need to call forceGridAnimation
grid.style.width = '500px'
forceGridAnimation()

// if you want to remove animations but not the grid itself
unwrapGrid()

Requirements

  1. The updates to the grid will have to come from addition or removal of a class or element. Currently, inline style updates will not trigger transitions. (Although you can manually trigger transitions in that case by calling forceGridAnimation())
  2. Important If a grid item has children, they should be surrounded by a single container element. This is so we can apply a counter scale and prevent children elements from getting warped during scale transitions of the parent.

Example:

<!-- grid class -->
<ul class="some-grid-class-that-changes">
  <li class="grid-item">
    <!-- each grid item must have a single direct child -->
    <div>
      <h3>Item title</h3>
      <div>Item body</div>
    </div>
  </li>
<div>

How it works

The script registers a MutationObserver that activates when the grid or one of its children adds or loses a class or element. That means there's no need to remove the animations before removing the grid, everything should be cleaned up automatically. It uses the FLIP animation technique to smoothly update the grid, applying a counter transform to the children of each item so that they do not appear distorted while the transition occurs.

It should work on container elements without CSS grid applied as well, but was developed and tested with CSS grid in mind.

Usage with Frameworks

The animate-css-grid library can easily be used with frameworks like React or Vue.

Check out the React example or the Vue example on Codepen!

animate-css-grid's People

Contributors

aholachek avatar alicer avatar dependabot[bot] avatar sustained avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

animate-css-grid's Issues

onStart children elements exhausts browser

I'm trying to use onStart/onEnd to add/remove a class from the grid's children (About 20 in length), but even just onStart exhausts my browser and causes it to hang.

My JS:

const { unwrapGrid, forceGridAnimation } = wrapGrid(collectionGrid, {
  duration: 250,
  stagger: 10,
  onStart: (elements) => {
    for (let i = 0; i < elements.length; i++) {
      const element = elements[i];
      element.classList.add('transitioning')
    }
  }
});

Swapping grid areas resizes grid item before moving.

I am trying to move my item to another grid area, this grid area is larger. The movement animation is working fine, but I am noticing that the item automatically resizes to fit the larger grid area before moving rather than resizing via animation on the way. I am trying to alleviate this with some scaling animation, but the overall item resizing immediately is very frustrating.

Codepen to illustrate:
https://codepen.io/BrianBenninger/pen/JqVgmg

Any thoughts? Am I missing something or is this working as expected?

Demo fails

Demo fails:

The console error is:
Loading failed for the <script> with source “file:///home/msdobrescu/grid/animate-css-grid-master/bundle.js”.

Add plain simple js file

Hello, please provide a simple javascript file to be included in any html and run, without the need of making bundles, or other stuff.

overflow-x causes odd behaviours

My issue is demonstrated in the following codepen. If you scroll somewhere within the content and then trigger an animation it seems to get confused (animate from scroll 0) but resolve itself. If you don't change the scroll position again and trigger the changes it seems happy. Scroll again, trigger an animation and, boom, you see the issue again. My guess is there's some internal caching going on which isn't accounting for scroll positioning?

https://codepen.io/anon/pen/RdGVow

My use case is I'm building a timeline view on top of a css grid. Timelines are infinitely long along x axis and therefore need scrolling. I could make the parent scrollable however some columns need to be sticky and due to sticky's relationship with it's parent container it needs to be the grid itself which is scrollable (ie. overflow-x: auto).

I'd be happy to look into a fix if I could get some pointers on where to start looking in the code! :)

Ps. Thanks for the library! Was great to drop in to my app so easily.

grid with css rotation not handled properly

Hi Aholachek !

First, many thanks for this css grid animation tool!

I am trying to use it in order to move an element from a grid-area to another.
It works well except when the current grid is rotated : the animation is then quite weird.
You'll find a short sample here: https://github.com/Ystalard/chess-board-grid-animation

  1. open sample.html on chrome
  2. click on rotate button
  3. click on move a piece button

It would be wonderfull if you find a solution!

Possibility to animate transitions on screen width change

I am looking for a way to animate item reordering when reducing/increasing screen width. Currently in the running demo the reordering happens without any animation. The animation itself should be similar to the animation when clicking the toggle grid-template-columns -button.

Doesn't animate additions in React

First off, 👏👏👏. This library is awesome and ridiculously easy to use!

I'm noticing that when i add elements to the grid in React, they simply pop into existence rather than animating in in some way. Is this as expected or is there some way to get an animation in this case?

As an example i've modified the codepen from the readme to add new elements to the grid whenever you click somewhere within the grid (like on an element).

Thanks!

Edit:
Just looked at the vanilla codepen and noticed this is also how it works with the add card button, so i suppose this is as expected. So this is more of a feature request than a bug i suppose.

Some properties are not animating

Good job on this library, it's really a shame that browsers do not support this by default.

I noticed there is one property that is not supported: the grid-area property on grid elements. Basically I use them to grow and shrink grid element to other rows and columns, very useful.

I also noticed that when I add elements to the grid, the other ones are also not animated while readjusting positions. Does this plugin support this?

Update: properties do animate only when classes are updated, not when inline styles are applied.

Can't import with Webpack

import { wrapGrid } from 'animateCSSGrid';

gives:

[12:42:04] Error in plugin 'webpack-stream' Message: ./src/js/app.js Module not found: Error: Can't resolve 'animateCSSGrid' in '/Users/davide/Sviluppo/Siti Web/Aikido/webstarter-dev/src/js' resolve 'animateCSSGrid' in '/Users/davide/Sviluppo/Siti Web/Aikido/webstarter-dev/src/js'

So I set the correct path as from npm install:

import { wrapGrid } from 'animate-css-grid';

No error in compiling, but this error in console:

TypeError: t is null

WebPack config:

`let webpackConfig = {
plugins: [
new webpack2.ProvidePlugin({
$: "jquery",
jQuery: "jquery"
}),
new webpack2.optimize.CommonsChunkPlugin({

        name: ['jquery'],
        // (the commons chunk name)

        filename: "vendors.js",
        // (the filename of the commons chunk)

        minChunks: 3,
        // (Modules must be shared between 3 entries)

        /*chunks: ["app", "fullpage", "carousel", "carousel_essenza"],*/
        // (Only use these entries)
    })
],
module: {
    rules: [
        {
            test: /.js$/,
            use: [
                {
                    loader: 'babel-loader'
                }
            ]
        }
    ]
}

}`

Is there a license?

Hello, I can't find any reference to a license for this repo. Would you be able to add one?

Optimising for performance

Great library! We have implemented this library to our website but are having some problems with animation jankiness on lower end smartphones. As you can see in https://www.conforama.es the header uses this library to animate a collapsing/expanding effect during scroll. Do you have some suggestions we could add in order to make animations smoother? We have already tried the "will-change: transform" rule however this resulted in more not less jankinness.

Not working on Blazor.

So I tried to do this example in my blazor project but it doens't work. I debbuged the JS and the query, to find the element with class .grid, returns null. Im not sure if it is the problem. Here you have a BlazzorFiddle showing that its not working. Thank you for your attention.

clarification on nesting containers.

Could you elaborate slightly on the librarys behavior on nested grids.

https://stackblitz.com/edit/css-grid-animation-fmgt5r?file=src/app/app.component.ts

lets say we have

gridcontainer1
    child1
    child2
    nestChild3
        gridcontainer2
            baby1
            baby2

Is the follwing true?

when I use wrapGrid(gridcontainer1);

auto-transitions (class toggle) and calling forceGridAnimation() will ONLY apply to child1, child2, nestChild3.

Stuff happening inside of nestChild3, (eg. gridcontainer2, baby1, baby2) will not be picked up by wrapGrid(gridcontainer1);

In order to get animations for gridcontainer2 I will have to instatiate wrapGrid(gridcontainer2); to deal with that?

Vue example

This is cool, good work and thank you.

But I use Vue and not React.

If I create a Vue version of the React example CodePen will you accept a P/R to add it to the README?

Style added by JS is lost after animation

When I add a custom style to an element with JS like
node.style.transform = "rotate(" + (Math.floor(Math.random() * 20) - 10).toString() + "deg)";
and then do an action that animates the grid, the previous rotation is lost.

I guess this is due to the fact, that the animation mechanism uses transform for itself and just overwrites everything that was there before.

Is it possible to keep all previously defined styles and only add the transforms for the animation of the grid?

Allow changing duration after animation was enabled

I'm using animate-css-grid to move objects around in a simulation I'm playing. I'm letting people change the playback speed. Therefore, I'd like to be able to change the duration parameter after I've called animateCSSGrid.wrapGrid. Can that be done somehow?

Fade out and fade in?

Is it possible to add fade out and fade in effects for elements going to be hidden/removed and shown/added?
On the github samples there are fade-in classes, but they don't seem to be used. What is their purpose?

Allow usage with server side rendering / gatsby

Hello,

first let me thank you a lot for providing and supporting such an easy to use library.

I'd like to use it within one of my Gatsby projects. Gatsby compiles a static version of each page/route and therefore the build fails if the code tries to access window.

Usually, we can come around this issue by checking for typeof window !== 'undefined' before it is used anywhere, but that doesn't work in this case. It seems window is accessed/required right after importing. Can you follow me?

Sadly, I'm not really sure how to resolve this problem, but I'm trying to investigate the webpack build.

Inner content resizes immediately - incorrect transform scaling?

Minimal reproducible example: https://codesandbox.io/s/hungry-chaum-jmmzi

Press the "change" button to see the issue.

The green "card" text expands to the full width of the end state and the container slowly expands to meet the size. The span element and the content container div are both set to width: 100% but the transform seems to be expanding the content to 2x its expected size which causes it to overflow.

If I set transform: none !important; to the content container div (child of the grid item) then the green box is consistently the same width as its container throughout the animation, but the text is skewed.

Any guidance (especially if I've misunderstood how the library works!) would be great, thanks in advance.

Angular intergration

Hi,

I've prepared Angular integration for your project. It would be nice to add it to "Usage with Frameworks" section next to Vue and Ract. Link

Unwrap grid doesn't actually unwrap?

I unwrap the grid, but when I try to rewrap it with wrapGrid I get uncaught exceptions? It looks like the unwrap is only for removing the observers/listeners - it doesn't clear up any state.

Delay render inside the cell

I am very new in CSS.
I am using react with your library, I am rendering some text inside the grid cell on click, But I want to render it after the cell got bigger, But I am unable to do that. It gets rendered instantaneously after the click. Is there any way in your library to achieve this.

Convert project to ES Module

Angular compiler gives a warning about optimization bailouts.

category.component.ts depends on 'animate-css-grid'. CommonJS or AMD dependencies can cause optimization bailouts.

This is currently not a bug, but for the sake of maintainability and a sign of life, this library should be updated :)

I would do this by myself, but I'm stupid.

Animates from very start

``https://youtu.be/tQu8ojxiwT8

I may just be missunderstanding how it works, but here it goes.

I am trying to make a small animation with grid placements here. using a setup like this: {
grid-start: num,
grid-end: num,
row-span: num
}

And somehow, I get the result from that video.
It comes from the wrong direction, becomes larger than the grid itself sometimes. Many things that just looks weird.

Again, probably just something stupid on my end, but thought this was the fastest way to get a response 😓

here's my code:
`
import Layout from '@/components/basic/PublicLayout'
import { useEffect, useRef, useState } from 'react'
import { wrapGrid } from 'animate-css-grid'

export default function Home() {
    const [animationActive, setAnimationActive] = useState<boolean>(false)
    const [currAnimated, setCurrAnimated] = useState({
        box0 : {
            cols: 1,
            cole: 3,
            row: 1
        },
        box1 : {
            cols: 3,
            cole: 5,
            row: 1,
        },
        box2 : {
            cols: 1,
            cole: 4,
            row: 1,
        },
        box3 : {
            cols: 4,
            cole: 5,
            row: 1,
        },
    })
    const animation = {
        box0: [
            {
                cols: 1,
                cole: 3,
                row: 1,
            }, 
            {
                cols: 1,
                cole: 4,
               row: 1,
  },
  {
    cols: 1,
    cole: 4,
    row: 1,
  },
  {
    cols: 1,
    cole: 4,
    row: 1,
  },
  {
    cols: 1,
    cole: 4,
    row: 1,
  },
],
box1: [
  {
    cols: 3,
    cole: 5,
    row: 1,
  },
  {
    cols: 4,
    cole: 5,
    row: 1,
  },
  {
    cols: 4,
    cole: 5,
    row: 1,
  },
  {
    cols: 4,
    cole: 5,
    row: 2,
  },
  {
    cols: 4,
    cole: 5,
    row: 1,
  },
],
box2: [
  {
    cols: 1,
    cole: 4,
    row: 1,
  },
  {
    cols: 1,
    cole: 4,
    row: 1,
  },
  {
    cols: 1,
    cole: 3,
    row: 1,
  },
  {
    cols: 1,
    cole: 3,
    row: 1,
  },
  {
    cols: 1,
    cole: 3,
    row: 1,
  },
],
box3: [
  {
    cols: 4,
    cole: 5,
    row: 1,
  },
  {
    cols: 4,
    cole: 5,
    row: 1,
  },
  {
    cols: 3,
    cole: 5,
    row: 1,
  },
  {
    cols: 3,
    cole: 4,
    row: 1,
  },
  {
    cols: 3,
    cole: 5,
    row: 1,
  },
]

}
const gridRef = useRef(null)

useEffect(() => {
if (!gridRef) return
if (gridRef != null){
const current:any = gridRef.current
wrapGrid(current, {
stagger: 0,
duration: 500,
easing: 'easeInOut'
})
if (!animationActive) {
handleAnimation(0)
setAnimationActive(true)
}
}
}, [gridRef])

const handleAnimation = (interval:number) => {
let newInterval = 0
setCurrAnimated({
box0: animation.box0[interval],
box1: animation.box1[interval],
box2: animation.box2[interval],
box3: animation.box3[interval],
})

if (interval < animation.box0.length - 1) {
  newInterval = interval + 1
} else {
  newInterval = 0
}

console.log(newInterval)

setTimeout(() => {
  handleAnimation(newInterval)
}, 1500)

}

return (

  <div className='w-4/5 h-full mx-auto flex flex-col justify-center items-center gap-10'>
    <h1 className='text-4xl'>Management dashboard</h1>

    {
      <div ref={gridRef} className='grid grid-cols-4 grid-rows-2 w-80 h-40 gap-5 border-2 border-black overflow-hidden'>
        <div className={`bg-black w-full h-full ${`col-start-${currAnimated.box0.cols} col-end-${currAnimated.box0.cole}`} ${`row-span-${currAnimated.box0.row}`}`}></div>
        <div className={`bg-black w-full h-full ${`col-start-${currAnimated.box1.cols} col-end-${currAnimated.box1.cole}`} ${`row-span-${currAnimated.box1.row}`}`}></div>
        <div className={`bg-black w-full h-full ${`col-start-${currAnimated.box2.cols} col-end-${currAnimated.box2.cole}`} ${`row-span-${currAnimated.box2.row}`}`}></div>
        <div className={`bg-black w-full h-full ${`col-start-${currAnimated.box3.cols} col-end-${currAnimated.box3.cole}`} ${`row-span-${currAnimated.box3.row}`}`}></div>
      </div>
    }
  </div>

</Layout>

)
}
`

Typescript Intergration

Greetings,

I'm in the process of (trying) to import this library into my project (react using Typescript) and I've run into two problems that might be related and might not.

The first issue was the type for the document.querySelector(".grid") which was returning < Element > not < HTMLElement > got around this by setting the type in querySelector<HTMLElement>(".grid"). Once this was sorted, i thought it would be smooth sailing but then i ran into my second issue.

TypeError: Failed to resolve module specifier "animate-css-grid". Relative references must start with either "/", "./", or "../". once it compiles I get this error in my browser console. I've tried setting the path to be relative, but again there is some issue here cause it should detect this as a module in TS. If anyone else has had experience setting this up in TS I would be very much interested to hear how

Svelte Example?

Would absolutely love to see a svelte example :-)

I can try to hack away at it but I'm not especially good at that kind of thing :-(

Allow cubicBezier easing

Hi.
First of all - great library. Such a headache theres no nativ css animation for grid layout yet.
Ive got some requests from our designers regarding the easing function and do you have any plans for adding support for @popmotion/easing - cubicBezier() method to allow users of this library to create a custom easing function?

It would be greatly appreciated

Items fly-in from top-left of body, not grid-container

Hi,

I'm using animated-css-grid to animate a grid that has filtering applied. Items that match the filter stay in place (and slide onto their new position), whilst items that don't match the filter get removed (using display: none).

When removing items all works fine: the items that remain in place neatly shift positions.
However, when removing the filter I notice that the items which need to be re-added (because they got removed in the previous step) now fly in from the top-left of the body element.

In this scenario I expected them to fly-in from the the top-left of the wrapping grid element (or at least the first parent that has position: relative applied), and not the body.

I've re-created this filtering effect in this pen:

toggle-animation

Look closely at the top left corner of the page as the green items get removed and then re-added.

Is there a better way to do filtering?
If not: can the animation be adjusted to start relative to the container?

Regards,
Bramus!

Flexbox too?

Your lib is really awesome - would it be possible to support flexbox too or do you know of similar libs for flexbox? (I know browsers partially animate flexbox)

Events for animation start and finish

I'm looking forward solution to register events on start and on end of the animation. What will be the best solution and where to update source code?

Doesn't work with display: contents

Amazing lib, but given a simple layout like...

.grid
       .item
            .wrap
                p helo
                p belo
        .item
            .wrap
                p helo
                p belo

...and CSS like...

.grid {
   display: grid
}

.item {
  display: contents
}

... the animations will no longer work. They do, if the .items don't have display: contents on the them.

Would it be possible to make it work with display: contents? 🥺

Is it possible to make a grid column slide off-screen?

In the app I'm building I have a CSS grid layout with a side panel and a main content container. I want to be able to toggle this panel (ie, hide it) by clicking on a handle. I'm trying this library in order to be able to animate the CSS grid changes. What I do, is adding a class that sets the first grid column to 0.

.layout-landscape {
    display: grid;
    grid-template-columns: minmax(400px, 21%) auto;

    &.layout-landscape-collapsed {
        grid-template-columns: 0 auto;
    }
}

The desired effect is that the panel slides off-screen. The result of using this library is that it looks like it shrinks/expands (ie, panel content doesn't move to the left of the screen, it remains in place while the panel shrinks). I wanted to ask if it's possible to achieve the desired outcome of having the left panel slide off-screen.

Also, a possible bug, while the panel is shrinking, the content disappears. When the panel expands, the content is visible (and as I mentioned, remains fixed in place while the container expands).

Any way to exclude some children?

I've gotten it to work for my project, but I don't want some of the grid children to be animated. Is there any way to exclude a child of the grid from being animated?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.