{"id":17224650,"url":"https://github.com/marnusw/react-css-transition-replace","last_synced_at":"2025-05-16T12:12:41.330Z","repository":{"id":36166130,"uuid":"40470211","full_name":"marnusw/react-css-transition-replace","owner":"marnusw","description":"A React component to animate replacing one element with another.","archived":false,"fork":false,"pushed_at":"2023-05-17T12:18:47.000Z","size":11771,"stargazers_count":296,"open_issues_count":15,"forks_count":49,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-04-09T08:02:51.400Z","etag":null,"topics":["animate-replacing","animation","css","react","transition"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/marnusw.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2015-08-10T07:55:10.000Z","updated_at":"2025-03-31T09:38:20.000Z","dependencies_parsed_at":"2024-06-18T13:35:00.082Z","dependency_job_id":"e63e584a-1c65-4f3d-802b-b660c42941f9","html_url":"https://github.com/marnusw/react-css-transition-replace","commit_stats":{"total_commits":157,"total_committers":13,"mean_commits":"12.076923076923077","dds":"0.14649681528662417","last_synced_commit":"4ecdd2ab2aeb8c157095232a1656048b32466bfd"},"previous_names":[],"tags_count":29,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marnusw%2Freact-css-transition-replace","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marnusw%2Freact-css-transition-replace/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marnusw%2Freact-css-transition-replace/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marnusw%2Freact-css-transition-replace/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/marnusw","download_url":"https://codeload.github.com/marnusw/react-css-transition-replace/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253475278,"owners_count":21914379,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["animate-replacing","animation","css","react","transition"],"created_at":"2024-10-15T04:11:39.296Z","updated_at":"2025-05-16T12:12:39.143Z","avatar_url":"https://github.com/marnusw.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# React CSS Transition Replace\n\nA [React](http://facebook.github.io/react/) component to animate replacing one element with another.\n\nWhile [`ReactCSSTransitionGroup`](https://facebook.github.io/react/docs/animation.html) does a great job\nof animating changes to a list of components and can even be used to animate the replacement of one item\nwith another, proper handling of the container height in the latter case is not built in. This component\nis designed to do exactly that with an API closely following that of `ReactCSSTransitionGroup`.\n\nUsing `react-css-transition-replace` provides two distinct benefits:\n\n- It automatically handles the positioning of the animated components, and\n- _allows changes in the height of container to be handled and animated with ease when\n  various content heights differ, even when absolute positioning is used._\n\nAnimations are fully configurable with CSS, including having the entering component wait to enter until\nthe leaving component's animation completes. Following suit with the\n[React.js API](https://facebook.github.io/react/docs/animation.html) the one caveat is\nthat the transition duration must be specified in JavaScript as well as CSS.\n\n[Live Examples](https://marnusw.github.io/react-css-transition-replace) |\n[Change Log](/CHANGELOG.md) |\n[Upgrade Guide](/UPGRADE_GUIDE.md)\n\n## Installation\n\nInstall via `npm`:\n\n```\nnpm install --save react-css-transition-replace\n```\n\n## Important Note\n\nAll functional child components must be wrapped in `forwardRef` to work correctly.\n\n## Usage\n\nA `ReactCSSTransitionReplace` component can only have a single child. Other than that, the basic usage\nfollows the exact same API as `ReactCSSTransitionGroup`, with support for `transitionEnter`, `transitionLeave`\nand `transitionAppear`. When the `key` of the child component changes, the previous component is animated out\nand the new component animated in. During this process:\n\n- All leaving components continue to be rendered; if the animation is slow there may be multiple components\n  in the process of leaving.\n- The entering component is positioned on top of the leaving component(s) with `absolute` positioning.\n- The height of the container is set to that of the leaving component, and then immediately to that of the\n  entering component. If the `transitionName` is a `String` the `{animation-name}-height` class name is applied\n  to it, and if `transitionName` is an `Object` the `transitionName.height` class will be used if present.\n- The leaving component will be passed an `isLeaving` prop while transitioning out.\n\nThis provides many possibilities for animating the replacement as illustrated in the examples below.\n\nAdditionally, the boolean property `changeWidth` can be used to animate changing the width of the component.\nThis change will happen at the same time as changing the height. Animating this change should be done using\nthe same class name that is used for animating the change in height.\n\nIt is also possible to remove the child component (i.e. leave `ReactCSSTransitionReplace` with no children)\nwhich will animate the `height` going to zero along with the `leave` transition. Similarly, a single child\ncan be added to an empty `ReactCSSTransitionReplace`, triggering the inverse animation.\n\nBy default a `span` is rendered as a wrapper of the child components. Each child is also wrapped in a `span`\nused in the positioning of the actual rendered child. These can be overridden with the `component` and\n`childComponent` props respectively.\n\n### Cross-fading two components\n\nThe `ReactCSSTransitionReplace` component is used exactly like its `ReactCSSTransitionGroup` counterpart:\n\n```javascript\nimport ReactCSSTransitionReplace from 'react-css-transition-replace';\n\nrender() {\n  return (\n    \u003cReactCSSTransitionReplace transitionName=\"cross-fade\"\n                               transitionEnterTimeout={1000} transitionLeaveTimeout={1000}\u003e\n      \u003cSomeComponent key=\"uniqueValue\"/\u003e\n    \u003c/ReactCSSTransitionReplace\u003e\n  );\n}\n```\n\nTo realize cross-fading of two components all that remains is to define the enter and leave opacity\ntransitions in the associated CSS classes:\n\n```css\n.cross-fade-leave {\n  opacity: 1;\n}\n.cross-fade-leave.cross-fade-leave-active {\n  opacity: 0;\n  transition: opacity 1s ease-in;\n}\n\n.cross-fade-enter {\n  opacity: 0;\n}\n.cross-fade-enter.cross-fade-enter-active {\n  opacity: 1;\n  transition: opacity 1s ease-in;\n}\n\n.cross-fade-height {\n  transition: height 0.5s ease-in-out;\n}\n```\n\nNote the additional `.cross-fade-height` class. This indicates how the container height is to be\nanimated if the heights of the entering and leaving components are not the same. You can see this\nin action [here](http://marnusw.github.io/react-css-transition-replace#cross-fade).\n\n### Fade out, then fade in\n\nTo fade a component out and wait for its transition to complete before fading in the next, simply\nadd a delay to the `enter` transition.\n\n```css\n.fade-wait-leave {\n  opacity: 1;\n}\n.fade-wait-leave.fade-wait-leave-active {\n  opacity: 0;\n  transition: opacity 0.4s ease-in;\n}\n\n.fade-wait-enter {\n  opacity: 0;\n}\n.fade-wait-enter.fade-wait-enter-active {\n  opacity: 1;\n  /* Delay the enter animation until the leave completes */\n  transition: opacity 0.4s ease-in 0.6s;\n}\n\n.fade-wait-height {\n  transition: height 0.6s ease-in-out;\n}\n```\n\n_Note:_ The `transitionEnterTimeout` specified in the JS must be long enough to allow for the delay and\nthe duration of the transition. In this case:\n\n```javascript\n\u003cReactCSSTransitionReplace transitionName=\"fade-wait\"\n                           transitionEnterTimeout={1000} transitionLeaveTimeout={400}\u003e\n```\n\nSee the live example [here](http://marnusw.github.io/react-css-transition-replace#fade-wait).\n\n### React-Router v4\n\nAnimated transitions of react-router v4 routes is supported with two caveats shown in the example below:\n\n1. The current `location` must be applied to the `Switch` to force it to maintain the previous matched route on\n   the leaving component.\n2. If the `Switch` might render `null`, i.e. there is no catch-all `\"*\"` route, the `Switch` must be wrapped in a\n   `div` or similar for the leave transition to work; if not the previous component will disappear instantaneously\n   when there is no match.\n\n```javascript\n\u003cRouter\u003e\n  \u003cdiv className=\"router-example\"\u003e\n    \u003cul\u003e\n      \u003cli\u003e\n        \u003cLink to=\"/\"\u003eHome\u003c/Link\u003e\n      \u003c/li\u003e\n      \u003cli\u003e\n        \u003cLink to=\"/one\"\u003eOne\u003c/Link\u003e\n      \u003c/li\u003e\n      \u003cli\u003e\n        \u003cLink to=\"/two\"\u003eTwo\u003c/Link\u003e\n      \u003c/li\u003e\n      \u003cli\u003e\n        \u003cLink to=\"/three\"\u003eThree (no match)\u003c/Link\u003e\n      \u003c/li\u003e\n    \u003c/ul\u003e\n    \u003cRoute\n      render={({ location }) =\u003e (\n        \u003cReactCSSTransitionReplace\n          transitionName=\"fade\"\n          transitionEnterTimeout={500}\n          transitionLeaveTimeout={500}\n        \u003e\n          \u003cdiv key={location.pathname}\u003e\n            \u003cSwitch location={location}\u003e\n              \u003cRoute path=\"/\" exact component={Home} /\u003e\n              \u003cRoute path=\"/one\" component={One} /\u003e\n              \u003cRoute path=\"/two\" component={Two} /\u003e\n            \u003c/Switch\u003e\n          \u003c/div\u003e\n        \u003c/ReactCSSTransitionReplace\u003e\n      )}\n    /\u003e\n  \u003c/div\u003e\n\u003c/Router\u003e\n```\n\nSee the live example [here](http://marnusw.github.io/react-css-transition-replace#react-router-v4).\n\n### Hardware acceleration for smoother transitions\n\nFor smoother transitions hardware acceleration, which is achieved by using translate3d instead of the 2D\ntranslations, should be used whenever possible. For example, to realize a mobile app transition between\npages one might use:\n\n```css\n.page-enter,\n.page-leave {\n  position: absolute;\n  -webkit-transition: transform 250ms ease-in-out, opacity 250ms ease-in-out;\n  transition: transform 250ms ease-in-out, opacity 250ms ease-in-out;\n}\n\n.page-enter {\n  left: 100vw;\n}\n\n.page-enter.page-enter-active {\n  -webkit-transform: translate3d(-100vw, 0, 0);\n  transform: translate3d(-100vw, 0, 0);\n}\n\n.page-leave {\n  left: 0;\n}\n\n.page-leave.page-leave-active {\n  -webkit-transform: translate3d(-100vw, 0, 0);\n  transform: translate3d(-100vw, 0, 0);\n}\n```\n\n```javascript\n\u003cReactCSSTransitionReplace\n  transitionName=\"page\"\n  transitionEnterTimeout={250}\n  transitionLeaveTimeout={250}\n\u003e\n  \u003cdiv key=\"page01\"\u003eMy page 01 content\u003c/div\u003e\n\u003c/ReactCSSTransitionReplace\u003e\n```\n\n## Tips\n\n1.  In general animating `block` or `inline-block` level elements is more stable that `inline` elements. If the\n    height changes in random ways ensure that there isn't a `span` or other inline element used as the outer\n    element of the components being animated.\n2.  The `overflow` of the container is set to `'hidden'` automatically, which changes the behaviour of\n    [collapsing margins](https://css-tricks.com/what-you-should-know-about-collapsing-margins/) from the default\n    `'visible'`. This may cause a glitch in the height at the start or end of animations. To avoid this you can:\n    - Keep the overflow hidden permanently with custom styles/classes if that will not cause undesired side-effects.\n    - Only use\n      [Single-direction margin declarations](http://csswizardry.com/2012/06/single-direction-margin-declarations/)\n      to avoid collapsing margins overall.\n    - Turn this feature off by setting the `overflowHidden={false}` prop when hidden overflow is not needed,\n      for example when transitions are in place and content is of the same height.\n3.  If the `.*-height` class (or `transitionName.height`) is not specified the change in container height will not\n    be animated but instead jump to the height of the entering component instantaneously. It can, therefore, be\n    omitted if all content is known to be of the same height without any adverse side-effects, and absolute positioning\n    related height issues will still be avoided.\n\n## Contributing\n\nPRs are welcome.\n\n## License\n\nThis software is free to use under the MIT license.\nSee the [LICENSE file](/LICENSE.md) for license text and copyright information.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmarnusw%2Freact-css-transition-replace","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmarnusw%2Freact-css-transition-replace","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmarnusw%2Freact-css-transition-replace/lists"}