├── .gitignore ├── README.md ├── index.js ├── index.test.js └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | coverage/ 2 | node_modules/ 3 | npm-debug.log 4 | yarn-error.log 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PostCSS will change transition 2 | [PostCSS]: https://github.com/postcss/postcss 3 | 4 | 7 | 8 | [PostCSS] plugin to generate will-change for transition props. 9 | 10 | This plugin adds `will-change` property after `transition` property to speed up animations. 11 | 12 | Can be combined with [postcss-will-change](https://github.com/postcss/postcss-will-change) plugin. 13 | 14 | 15 | 16 | ```css 17 | .foo { 18 | transition: opacity 0.2s ease, width 0.2s ease; 19 | } 20 | ``` 21 | 22 | ```css 23 | .foo { 24 | transition: opacity 0.2s ease, width 0.2s ease; 25 | will-change: opacity, width; 26 | } 27 | ``` 28 | 29 | ## Important note 30 | 31 | Make sure that if you use this plugin it does not contradict with `will-change` idea. Please see links below: 32 | 33 | - https://developer.mozilla.org/en-US/docs/Web/CSS/will-change 34 | - https://www.sitepoint.com/introduction-css-will-change-property/ 35 | - https://css-tricks.com/almanac/properties/w/will-change/ 36 | 37 | ## Usage 38 | 39 | ```js 40 | postcss([ require('postcss-will-change-transition') ]) 41 | 42 | // with fallback plugin: 43 | postcss([ require('postcss-will-change-transition'), require('postcss-will-change') ]) 44 | ``` 45 | 46 | See [PostCSS] docs for examples for your environment. 47 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | const postcss = require('postcss'); 2 | const cssProps = require('css-properties-values'); 3 | 4 | const transitionProps = cssProps.map(prop => prop.property); 5 | 6 | module.exports = postcss.plugin('postcss-will-change-transition', function () { 7 | return function (css) { 8 | css.walkDecls('transition', function (decl) { 9 | const already = decl.parent.some(elem => 10 | elem.type === 'decl' && elem.prop === 'will-change' 11 | ); 12 | 13 | if (already || /all/.test(decl.value)) { 14 | return; 15 | } 16 | 17 | const value = decl.value 18 | .split(',') 19 | .map(str => str.trim().split(' ')) 20 | .filter(splitted => transitionProps.includes(splitted[0])) 21 | .map(splitted => splitted[0]) 22 | .join(', '); 23 | 24 | if (!value) { 25 | return; 26 | } 27 | 28 | decl.cloneAfter({ 29 | prop: 'will-change', 30 | value 31 | }); 32 | }); 33 | }; 34 | }); 35 | -------------------------------------------------------------------------------- /index.test.js: -------------------------------------------------------------------------------- 1 | const postcss = require('postcss'); 2 | 3 | const plugin = require('./'); 4 | 5 | function run(input, output) { 6 | return postcss([ plugin ]).process(input).then(result => { 7 | expect(result.css).toEqual(output); 8 | expect(result.warnings().length).toBe(0); 9 | }); 10 | } 11 | 12 | it('adds will-change prop', () => { 13 | const input = ` 14 | a { 15 | transition: opacity 0.2s ease, width; 16 | } 17 | `; 18 | const output = ` 19 | a { 20 | transition: opacity 0.2s ease, width; 21 | will-change: opacity, width; 22 | } 23 | `; 24 | 25 | return run( 26 | input, 27 | output 28 | ); 29 | }); 30 | 31 | it('does not override existing properties', () => { 32 | return run('a{ transition: opacity 0.2s ease, width; will-change: top; }', 33 | 'a{ transition: opacity 0.2s ease, width; will-change: top; }'); 34 | }); 35 | 36 | it('does not get confused by other selectors', () => { 37 | const input = ` 38 | a { 39 | will-change: initial; 40 | } 41 | 42 | b { 43 | transition: top .2s ease-in-out, left 5s linear; 44 | } 45 | `; 46 | const output = ` 47 | a { 48 | will-change: initial; 49 | } 50 | 51 | b { 52 | transition: top .2s ease-in-out, left 5s linear; 53 | will-change: top, left; 54 | } 55 | `; 56 | return run(input, output); 57 | }); 58 | 59 | it('ignore `all` prop', () => { 60 | const input = ` 61 | a { 62 | transition: all .2s ease-in-out; 63 | } 64 | `; 65 | const output = ` 66 | a { 67 | transition: all .2s ease-in-out; 68 | } 69 | `; 70 | return run(input, output); 71 | }); 72 | 73 | it('ignore `all` shorthands', () => { 74 | const input = ` 75 | a { 76 | transition: .25s; 77 | } 78 | 79 | b { 80 | transition: 0.25s; 81 | } 82 | 83 | c { 84 | transition: 0.25s ease; 85 | } 86 | `; 87 | const output = ` 88 | a { 89 | transition: .25s; 90 | } 91 | 92 | b { 93 | transition: 0.25s; 94 | } 95 | 96 | c { 97 | transition: 0.25s ease; 98 | } 99 | `; 100 | return run(input, output); 101 | }); 102 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "postcss-will-change-transition", 3 | "version": "1.2.0", 4 | "description": "PostCSS plugin to generate will-change for transition props", 5 | "keywords": [ 6 | "postcss", 7 | "css", 8 | "postcss-plugin", 9 | "will-change", 10 | "transition" 11 | ], 12 | "author": "Anatoly Ostrovsky ", 13 | "license": "MIT", 14 | "repository": "megatolya/postcss-will-change-transition.git", 15 | "dependencies": { 16 | "css-properties-values": "1.0.0", 17 | "postcss": "^6.0.1" 18 | }, 19 | "devDependencies": { 20 | "eslint": "^3.19.0", 21 | "eslint-config-postcss": "^2.0.2", 22 | "jest": "^20.0.0", 23 | "lint-staged": "^3.4.1", 24 | "pre-commit": "^1.2.2" 25 | }, 26 | "scripts": { 27 | "lint-staged": "lint-staged", 28 | "test": "jest --colors --silent=false --coverage index.test.js && eslint *.js" 29 | }, 30 | "jest": { 31 | "coverageThreshold": { 32 | "global": { 33 | "statements": 100 34 | } 35 | } 36 | }, 37 | "eslintConfig": { 38 | "extends": "eslint-config-postcss/es5", 39 | "env": { 40 | "jest": true 41 | } 42 | }, 43 | "lint-staged": { 44 | "*.js": "eslint" 45 | }, 46 | "pre-commit": [ 47 | "lint-staged" 48 | ] 49 | } 50 | --------------------------------------------------------------------------------