├── .eslintrc.cjs ├── .gitignore ├── .prettierrc ├── LICENSE.md ├── README.md ├── demo ├── index.css ├── index.html ├── index.js └── package.json ├── dist ├── index.d.ts ├── index.d.ts.map ├── main.js ├── main.js.map ├── main.module.js └── main.module.js.map ├── examples ├── grid-column-optimized.gif ├── grid-gap-optimized-1.gif └── grid-template-columns-optimized-1.gif ├── package.json ├── src ├── index.ts └── types.ts ├── tsconfig.json └── yarn.lock /.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | 'env': { 3 | 'browser': true, 4 | 'es2021': true 5 | }, 6 | 'extends': [ 7 | 'eslint:recommended', 8 | 'plugin:@typescript-eslint/recommended' 9 | ], 10 | 'overrides': [ 11 | ], 12 | 'parser': '@typescript-eslint/parser', 13 | 'parserOptions': { 14 | 'ecmaVersion': 'latest', 15 | 'sourceType': 'module' 16 | }, 17 | 'plugins': [ 18 | '@typescript-eslint' 19 | ], 20 | 'rules': { 21 | 'indent': [ 22 | 'error', 23 | 2 24 | ], 25 | 'linebreak-style': [ 26 | 'error', 27 | 'unix' 28 | ], 29 | 'quotes': [ 30 | 'error', 31 | 'single' 32 | ], 33 | 'semi': [ 34 | 'error', 35 | 'always' 36 | ] 37 | } 38 | }; 39 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | *.log 4 | .vscode 5 | src/*.js 6 | .rpt2_cache 7 | dist 8 | .parcel-cache 9 | demo/dist/* 10 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "printWidth": 80, 4 | "trailingComma": "es5", 5 | "tabWidth": 2, 6 | "useTabs": false, 7 | "parser": "typescript", 8 | "overrides": [{ 9 | "files": "*.{scss,css}", 10 | "options": { 11 | "parser": "css", 12 | "singleQuote": false, 13 | "semi": true 14 | } 15 | }] 16 | } 17 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Alex Holachek 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Animate CSS Grid 2 | 3 | Performantly animate all CSS grid properties, including: 4 | 5 | ### `grid-column` and `grid-row` 6 | 7 | 8 | grid-column and grid-row 9 | 10 | 11 | 12 | ### `grid-template-columns` 13 | 14 | 15 | grid-template-columns 16 | 17 | 18 | ### `grid-gap` 19 | 20 | 21 | grid-gap 22 | 23 | 24 | 25 | #### [Fork Photo Grid Example on CodeSandbox](https://codesandbox.io/s/animate-css-grid-template-t6qsf) 26 | 27 | 28 | ## Why use animate-css-grid? 29 | 30 | This library uses transforms to transition between different layout states, which means, in comparison to [pure CSS animations](https://web.dev/css-animated-grid-layouts/), it offers: 31 | 32 | - better performance 33 | - more flexibility in terms of what properties can be animated 34 | - more configurable animations (easing options, staggers) 35 | 36 | Want to have a look for yourself? Feel free to check out [this Mondrian animated with CSS keyframes](https://codepen.io/aholachek/pen/poOeXBM) and compare it with [the same UI animated with animate-css-grid.](https://codepen.io/aholachek/pen/XWPMwEx) 37 | 38 | ## How to use it 39 | 40 | Just call the `wrapGrid` method on your grid container, and optionally provide a config object as a second argument. 41 | If the grid is removed from the page, the animations will automatically be cleaned up as well. 42 | 43 | 44 | `yarn add animate-css-grid` or `npm install animate-css-grid` 45 | 46 | ```js 47 | import { wrapGrid } from 'animate-css-grid' 48 | 49 | const grid = document.querySelector(".grid"); 50 | wrapGrid(grid); 51 | ``` 52 | 53 | Or from a script tag: 54 | 55 | ```html 56 | 57 | 58 | 62 | ``` 63 | 64 | Optional config object: 65 | 66 | ```js 67 | { 68 | // int: default is 0 ms 69 | stagger: 100, 70 | // int: default is 250 ms 71 | duration: 500, 72 | // string: default is 'easeInOut' 73 | easing: 'backInOut', 74 | // function: called with list of elements about to animate 75 | onStart: (animatingElementList)=> {}, 76 | // function: called with list of elements that just finished animating 77 | // cancelled animations will not trigger onEnd 78 | onEnd: (animatingElementList)=> {} 79 | } 80 | ``` 81 | 82 | Available easing functions: 83 | 84 | - `'linear'` 85 | - `'easeIn'` / `'easeOut'` / `'easeInOut'` 86 | - `'circIn'` / `'circOut'` / `'circInOut'` 87 | - `'backIn'` / `'backOut'` / `'backInOut'` 88 | - `'anticipate'` 89 | 90 | [Learn more about available easing functions here.](https://popmotion.io/api/easing/) 91 | 92 | Two functions are returned by the `wrapGrid` call that you probably won't need to use: 93 | 94 | ```js 95 | import { wrapGrid } from animateCSSGrid 96 | 97 | const grid = document.querySelector(".grid"); 98 | const { unwrapGrid, forceGridAnimation } = wrapGrid(grid); 99 | 100 | // if you want the grid to transition after updating an inline style 101 | // you need to call forceGridAnimation 102 | grid.style.width = '500px' 103 | forceGridAnimation() 104 | 105 | // if you want to remove animations but not the grid itself 106 | unwrapGrid() 107 | ``` 108 | 109 | ## Requirements 110 | 111 | 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()`) 112 | 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. 113 | 114 | Example: 115 | 116 | ```html 117 | 118 |