{"id":285936,"date":"2019-04-16T07:05:42","date_gmt":"2019-04-16T14:05:42","guid":{"rendered":"http:\/\/css-tricks.com\/?p=285936"},"modified":"2019-04-16T07:05:42","modified_gmt":"2019-04-16T14:05:42","slug":"the-power-of-named-transitions-in-vue","status":"publish","type":"post","link":"https:\/\/css-tricks.com\/the-power-of-named-transitions-in-vue\/","title":{"rendered":"The Power of Named Transitions in Vue"},"content":{"rendered":"
Vue offers several ways to control how an element or component visually appears when inserted into the DOM. Examples can be fading in, sliding in, or other visual effects. Almost all of this functionality is based around a single component: the transition component<\/strong>.<\/p>\n A simple example of this is with a single Several articles have been written that cover the transition component quite well, like articles from Sarah Drasner<\/a>, Nicolas Udy<\/a>, and Hassan Djirdeh<\/a>. Each article covers different aspects of Vue\u2019s transition component in detail. This article will expand on the topic by focusing on one aspect of the transition component; the fact that they can be \u201cnamed.”<\/p>\n <\/p>\n The initial change this attribute offers is that the CSS classes injected onto the element during the transition sequence will be prefixed by the given name. Basically, it would be Another thing to consider is that the name attribute can be bound:<\/p>\n In this example, the transition will be named the value This article is intended to explore these features and explain how to use them.<\/p>\n By default, when a transition component is used, it applies specific classes in a specific sequence to the element. These classes can be leveraged in CSS. Without any CSS, these classes, in essence, do nothing for the element. Therefore, there is a need for CSS of this nature:<\/p>\n This causes the element to fade in and out with a duration of half a second. A minor change to the transition provides for elegant visual feedback to the user. Still, there is an issue to consider. But first, what\u2019s different with a named transition?<\/p>\n Essentially the same CSS but with Naming transitions provides a level of control for developers throughout the project as to how different elements or components are inserted or removed visually. It is suggested that all transitions be named \u2014 even if there is just one \u2014 to establish the habit of doing so. Even if an app has only one transition effect, there may be a need to add a new one at a future point. Having already named existing transitions in the project eases the effort of adding a new one.<\/p>\n Naming transitions provides for a simple yet very useful process. A common practice might be to create the transition classes as part of the component that is using them. If another common practice of scoping styles for a component is done, those classes will only be available to that particular component. If two different components have similar transitions in their style blocks, then we are just duplicating code.<\/p>\n So, let\u2019s consider keeping CSS for transitions in the style block of the root of the app, typically the There are multiple ways to store these transition classes depending on your preferences and the needs of the project. The first, as mentioned earlier, is to keep it all in the style block of the This method allows for adjustments and additions to the collection of transitions outside of the Vue files. Another benefit of this setup is that such a file can be easily transferred between projects if they share transition effects. If one project gets a new transition, then it\u2019s easy enough to transfer the addition to another project without having to touch main project files.<\/p>\n If you\u2019re using CSS instead of Sass, then you can include the file as a requirement of the project. You can accomplish this by keeping the file in the assets folder of the project and placing a require statement in the Another option is keep the transition styles in a static CSS file that can be stored elsewhere, either in the public folder of the project or just on the server itself. Since this is a regular CSS file, no building or deployment would be required \u2014 just include a link reference in the This file could also potentially be stored in a CDN for all projects to share. Whenever the file is updated, the changes are immediately available everywhere it is referenced. If a new transition name is created, then existing projects can start using the new name as needed.<\/p>\n While we\u2019re building a collection of transitions to use throughout our project, let\u2019s consider users out there who may not want abrupt animations, or who may want no animations at all. Some people could consider our animations over-the-top and unnecessary, but for some, they can actually cause problems. Some time ago, WebKit introduced the In most cases, adding the media query as part of our collection of transitions is quite easy and should be considered. We can either reduce the amount of motion involved in the transition to reduce the negative effects or simply turn them off.<\/p>\n Here\u2019s a simple example from one of my demos<\/a> below:<\/p>\n In that example, I took what was a rather exaggerated transition and made it simpler. The animation is a slide that moves to the left with an elastic ease, then scales down and fades out as it moves away. If someone has the reduce motion preference set, then the animation becomes a much simpler transition with a shorter distance (which gives it a slower velocity) and keeps the fade. If we had wanted to turn them off, then we\u2019d only need to reference the classes with the transition property and set their value to To test this requires finding and selecting a checkbox on your respective OS. On Windows, you will find it in Control Panel > Ease of Access Center > Make the computer easier to see<\/kbd> section; look for “Turn off all unnecessary animations (when possible).” On a Mac, look under System Preferences > Accessibility > Display<\/kbd>; look for “Reduce motion.” The latest iOS devices have a similar setting under Accessibility<\/kbd> as well.<\/p>\n With this collection of transitions, there is the potential snag of a lack of flexibility with the effects. For instance, what if one element needs a slightly slower fade time? Let\u2019s say that everything else in the effect can stay the same, only the The easiest method is to use an inline style directly on the element within the transition component.<\/p>\n Such a change can also be done through the various ways Vue offers handling styles and classes<\/a>.<\/p>\n Let\u2019s say you are using the component element with the Even with this dynamic component, we have options to adjust properties of the transition effect. Again, we can apply an inline style on the component element, which will be placed on the root element of the component. The root element also receives the transition classes, so we would directly override their properties.<\/p>\n Another option is to pass in props to our components. That way, the desired changes can be applied through the component\u2019s code to its root element.<\/p>\n We can also override the properties of the transition\u2019s classes inside the component\u2019s style block, especially if it is scoped.<\/p>\n In this case, the component will have a fade duration of one second instead of the global duration of half-a-second. We can even take it a step further and have different durations for each side of the sequence.<\/p>\n Any of the global transition classes can be altered within the component when needed. Although this isn\u2019t quite as flexible as changing the property outside of a class structure, it can still be quite useful in certain circumstances.<\/p>\n As you can see, even with our collection of prebuilt transitions, we still have options for flexibility.<\/p>\n Even after all these interesting things we can do with Vue\u2019s transition component, yet another interesting feature waits to be explored. The This means that the transition can be changed to have different animation effects with different situations, based in code. For example, we could have a transition change because of the answer to a question, transitions decided from user interaction, and have a list use different transitions based on the current state of the list itself.<\/p>\n Let\u2019s look into these three examples.<\/p>\n In this example, we have a simple math question that must be answered. Two numbers are randomly selected and we are expected to provide the sum. Then the button is clicked to check the answer against the expected answer. A small notification appears above the equation that indicates whether the answer is true or false. If the answer is correct, the notification is given a transition that suggests a head nodding yes with an up and down animation. If your answer is incorrect, the notification goes side-to-side suggesting a head shaking no.<\/p>\n \nSee the Pen The logic behind this is not overly complicated, nor is the setup of the transition. Here\u2019s the HTML:<\/p>\n Rather simple in nature. We have a bound name on the transition and then a Here\u2019s the CSS for the transitions:<\/p>\n You\u2019ll see that I\u2019m using CSS animations to accomplish the up-and-down and side-to-side effects.<\/p>\n Here\u2019s some of the JavaScript:<\/p>\n There\u2019s the This is just a simple example. Another possible example is having a notification that has two different effects based on whether the notification is important or not. If the message is not overly important, then we can have a subtle animation that doesn\u2019t drive the user\u2019s eyes away from the current task. If it is important, we could use an animation that is more direct in nature in an effort to force the eyes up to the notification.<\/p>\n Another thing we can build is a carousel of some sort. This could be presentation slides, an image gallery, or a series of instructions. The basic idea is that we have a need to present information to the user in a sequence. In this presentation, the user gets to decide when to proceed and whether to move forward or to go backward.<\/p>\n \nSee the Pen This, again, is a rather simple setup. The example, more or less, is a slide presentation type of situation. The two buttons at the bottom shift between two components with a sliding transition. A real project would have more components or perhaps logic to change the contents of the components based on the current slide. This example shall stay simple to demonstrate the idea.<\/p>\n Here\u2019s the HTML:<\/p>\n You\u2019ll see that we\u2019re merely transitioning whenever the component is switched out by a bound Here\u2019s the CSS:<\/p>\n Here we have two transitions, one for when the user clicks on the \u201cnext\u201d button and the other is for the “prev<\/abbr>” button. Each essentially slides the component in the appropriate direction with the Now, for the JavaScript:<\/p>\n Each button calls the For our final example, we\u2019ll see how to change transitions based on the current state of a list inside a \nSee the Pen In this example, we are presented with a list of cities on the right and a blank list on the left. As cities are chosen on the right, they fill in the blanks on the left. The first city slides in from above while fading into view. The next cities before the last will slide in either from the right or the left, depending on the previous transition, and the last city slides in from below.<\/p>\n Here\u2019s the HTML:<\/p>\n As usual, a rather simple setup. Here are the transitions in CSS:<\/p>\n As you can see, a transition for each possible direction of the cities appearing the blank list.<\/p>\n Now, for our JavaScript:<\/p>\n The Another option to change transitions for a list is changing according to the type of items chosen; such as east coast versus west coast cities, each having different transitions. Consider changing the transition based on the current number of items added to the list; for instance, a different transition for every five items. <\/p>\n After all these examples and ideas, I hope that you will consider leveraging Vue\u2019s transition component in your own projects. Exploring the possibilities of adding transitions and animations to your apps to provide context and interest for your users. In many cases, additions such as these are rather simple to implement, almost to the point of it being a shame not to add them. Vue offers an exciting and highly useful feature, the transition component, out of the box and I can only encourage its usage.<\/p>\n Cheers.<\/p>\n","protected":false},"excerpt":{"rendered":" Vue offers several ways to control how an element or component visually appears when inserted into the DOM. Examples can […]<\/p>\n","protected":false},"author":259401,"featured_media":268986,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_bbp_topic_count":0,"_bbp_reply_count":0,"_bbp_total_topic_count":0,"_bbp_total_reply_count":0,"_bbp_voice_count":0,"_bbp_anonymous_reply_count":0,"_bbp_topic_count_hidden":0,"_bbp_reply_count_hidden":0,"_bbp_forum_subforum_count":0,"inline_featured_image":false,"c2c_always_allow_admin_comments":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"The Power of Named Transitions in Vue","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2},"_share_on_mastodon":"0","_share_on_mastodon_status":"%title% %permalink%"},"categories":[4],"tags":[1073,1090],"class_list":["post-285936","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-articles","tag-vue","tag-vue-transitions"],"acf":{"show_toc":"No"},"share_on_mastodon":{"url":"","error":""},"jetpack_publicize_connections":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2018\/03\/vue-circles.jpg?fit=1200%2C600&ssl=1","jetpack-related-posts":[{"id":250426,"url":"https:\/\/css-tricks.com\/intro-to-vue-5-animations\/","url_meta":{"origin":285936,"position":0},"title":"Intro to Vue.js: Animations","author":"Sarah Drasner","date":"February 3, 2017","format":false,"excerpt":"This is the fifth part in a five-part series about the JavaScript framework, Vue.js. In this last part of the series, we'll cover Animations (if you know me at all, you probably knew this was coming). This is not intended to be a complete guide, but rather an overview of\u2026","rel":"","context":"In "Articles"","block_context":{"text":"Articles","link":"https:\/\/css-tricks.com\/category\/articles\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2017\/01\/vue-5.jpg?fit=800%2C507&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2017\/01\/vue-5.jpg?fit=800%2C507&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2017\/01\/vue-5.jpg?fit=800%2C507&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2017\/01\/vue-5.jpg?fit=800%2C507&ssl=1&resize=700%2C400 2x"},"classes":[]},{"id":269431,"url":"https:\/\/css-tricks.com\/list-rendering-and-vues-v-for-directive\/","url_meta":{"origin":285936,"position":1},"title":"List Rendering and Vue\u2019s v-for Directive","author":"Hassan Djirdeh","date":"April 11, 2018","format":false,"excerpt":"List rendering is one of the most commonly used practices in front-end web development. Dynamic list rendering is often used to present a series of similarly grouped information in a concise and friendly format to the user. In almost every web application we use, we can see lists of content\u2026","rel":"","context":"In "Articles"","block_context":{"text":"Articles","link":"https:\/\/css-tricks.com\/category\/articles\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2018\/04\/vue-for-tweet-shuffle.gif?fit=800%2C400&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2018\/04\/vue-for-tweet-shuffle.gif?fit=800%2C400&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2018\/04\/vue-for-tweet-shuffle.gif?fit=800%2C400&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2018\/04\/vue-for-tweet-shuffle.gif?fit=800%2C400&ssl=1&resize=700%2C400 2x"},"classes":[]},{"id":280317,"url":"https:\/\/css-tricks.com\/animating-between-views-in-react\/","url_meta":{"origin":285936,"position":2},"title":"Animating Between Views in React","author":"Jeremias Menichelli","date":"December 21, 2018","format":false,"excerpt":"You know how some sites and web apps have that neat native feel when transitioning between two pages or views? Sarah Drasner has shown some good examples and even a Vue library to boot. These animations are the type of features that can turn a good user experience into a\u2026","rel":"","context":"In "Articles"","block_context":{"text":"Articles","link":"https:\/\/css-tricks.com\/category\/articles\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2018\/12\/view-transitions-featured.gif?fit=900%2C450&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2018\/12\/view-transitions-featured.gif?fit=900%2C450&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2018\/12\/view-transitions-featured.gif?fit=900%2C450&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2018\/12\/view-transitions-featured.gif?fit=900%2C450&ssl=1&resize=700%2C400 2x"},"classes":[]},{"id":261678,"url":"https:\/\/css-tricks.com\/creating-vue-js-transitions-animations\/","url_meta":{"origin":285936,"position":3},"title":"Creating Vue.js Transitions & Animations","author":"Nicolas Udy","date":"October 24, 2017","format":false,"excerpt":"My last two projects hurled me into the JAMstack. SPAs, headless content management, static generation... you name it. More importantly, they gave me the opportunity to learn Vue.js. More than \"Build a To-Do App\" Vue.js, I got to ship real-life, production-ready Vue apps. The agency behind Snipcart (Spektrum) wanted to\u2026","rel":"","context":"In "Articles"","block_context":{"text":"Articles","link":"https:\/\/css-tricks.com\/category\/articles\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2017\/10\/s_F5250556F7D3391E68057B73327023BE3FABE38B82BFDFDDC88FB44D203DAEA0_1507664011389_calvin-chin-1929.jpg?fit=1200%2C800&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2017\/10\/s_F5250556F7D3391E68057B73327023BE3FABE38B82BFDFDDC88FB44D203DAEA0_1507664011389_calvin-chin-1929.jpg?fit=1200%2C800&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2017\/10\/s_F5250556F7D3391E68057B73327023BE3FABE38B82BFDFDDC88FB44D203DAEA0_1507664011389_calvin-chin-1929.jpg?fit=1200%2C800&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2017\/10\/s_F5250556F7D3391E68057B73327023BE3FABE38B82BFDFDDC88FB44D203DAEA0_1507664011389_calvin-chin-1929.jpg?fit=1200%2C800&ssl=1&resize=700%2C400 2x, https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2017\/10\/s_F5250556F7D3391E68057B73327023BE3FABE38B82BFDFDDC88FB44D203DAEA0_1507664011389_calvin-chin-1929.jpg?fit=1200%2C800&ssl=1&resize=1050%2C600 3x"},"classes":[]},{"id":278891,"url":"https:\/\/css-tricks.com\/swipeable-card-stack-using-vue-js-and-interact-js\/","url_meta":{"origin":285936,"position":4},"title":"Swipeable card stack using Vue.js and interact.js","author":"Mateusz Rybczonek","date":"November 21, 2018","format":false,"excerpt":"I recently had an opportunity to work on a fantastic research and development project at Netguru. The goal of project (codename: \"Wordguru\") was to create a card game that anyone can play with their friends. You can see the outcome here. One element of the development process was to create\u2026","rel":"","context":"In "Articles"","block_context":{"text":"Articles","link":"https:\/\/css-tricks.com\/category\/articles\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2018\/11\/swipe-card-stack.gif?fit=1000%2C500&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2018\/11\/swipe-card-stack.gif?fit=1000%2C500&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2018\/11\/swipe-card-stack.gif?fit=1000%2C500&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2018\/11\/swipe-card-stack.gif?fit=1000%2C500&ssl=1&resize=700%2C400 2x"},"classes":[]},{"id":269409,"url":"https:\/\/css-tricks.com\/native-like-animations-for-page-transitions-on-the-web\/","url_meta":{"origin":285936,"position":5},"title":"Native-Like Animations for Page Transitions on the Web","author":"Sarah Drasner","date":"April 23, 2018","format":false,"excerpt":"Some of the most inspiring examples I\u2019ve seen of front-end development have involved some sort of page transitions that look slick like they do in mobile apps. However, even though the imagination for these types of interactions seem to abound, their presence on actual sites that I visit do not.\u2026","rel":"","context":"In "Articles"","block_context":{"text":"Articles","link":"https:\/\/css-tricks.com\/category\/articles\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2018\/04\/native-like-animations-vue-nuxt.gif?fit=640%2C320&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2018\/04\/native-like-animations-vue-nuxt.gif?fit=640%2C320&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2018\/04\/native-like-animations-vue-nuxt.gif?fit=640%2C320&ssl=1&resize=525%2C300 1.5x"},"classes":[]}],"jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/posts\/285936","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/users\/259401"}],"replies":[{"embeddable":true,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/comments?post=285936"}],"version-history":[{"count":19,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/posts\/285936\/revisions"}],"predecessor-version":[{"id":285987,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/posts\/285936\/revisions\/285987"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/media\/268986"}],"wp:attachment":[{"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/media?parent=285936"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/categories?post=285936"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/tags?post=285936"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}v-if<\/code> based on a Boolean. When the Boolean is true, the element appears. When the Boolean is false, the element disappears. Normally, this element would just pop in and out of existence, but with the transition component you can control the visual effect.<\/p>\n<transition>\r\n <div v-if=\"isVisible\">is this visible?<\/div>\r\n<\/transition><\/code><\/pre>\n<transition name=\"fade\">\r\n <div v-if=\"isVisible\">is this visible?<\/div>\r\n<\/transition><\/code><\/pre>\nfade-enter<\/code> instead of v-enter<\/code> from the example above. This single attribute can go well beyond this simple option. It can be used to leverage certain features of Vue and CSS which allows for some interesting outcomes.<\/p>\n<transition v-bind:name=\"currentTransition\">\r\n <div v-if=\"isVisible\">is this visible?<\/div>\r\n<\/transition><\/code><\/pre>\ncurrentTransition<\/code> resolves to. This simple change provides another level of options and features to an app\u2019s animations. With static and dynamic named transitions, a project can have a series of prebuilt transitions ready to apply throughout the entire app, components that can extend existing transitions applied to them, switch a transition being used before or after being applied, allowing users to choose transitions, and control how individual elements of a list transition into place based on the current state of that list.<\/p>\nWhat happens when transitions are named?<\/h3>\n
.v-enter,\r\n.v-leave-to {\r\n opacity: 0;\r\n}\r\n\r\n.v-enter-active,\r\n.v-leave-active {\r\n transition: 0.5s;\r\n}<\/code><\/pre>\n.fade-enter,\r\n.fade-leave-to {\r\n opacity: 0;\r\n}\r\n\r\n.fade-enter-active,\r\n.fade-leave-active {\r\n transition: 0.5s;\r\n}<\/code><\/pre>\nfade-<\/code> prefixed instead of v-<\/code>. This naming addresses the potential issue that can happen when using the default class names of the transition component. The v-<\/code> prefix makes the classes global in effect, especially if the CSS is placed in the style block of the app\u2019s root level. This would, in effect, make *all* transitions without a name attribute throughout the entire app use the same transition effect. For small apps this may suffice, but in larger, more complex apps, it may lead to undesirable visual effects, as not everything should fade in and out over half a second.<\/p>\nBuilding a collection of transition effects<\/h3>\n
app.vue<\/code> file. For most of my projects, I place them as the last section of the style block, making them easy to locate for adjustments and additions. Keeping the CSS in this location makes the transition effects available to every use of the transition component throughout the entire app. Here are examples from some of my projects.<\/p>\n.fade-enter,\r\n.fade-leave-to { opacity: 0; }\r\n.fade-enter-active,\r\n.fade-leave-active { transition: 0.5s; }\r\n\r\n.slide-enter {\r\n opacity: 0;\r\n transform: scale3d(2, 0.5, 1) translate3d(400px, 0, 0);\r\n}\r\n\r\n.slide-enter-to { transform: scale3d(1, 1, 1); }\r\n.slide-enter-active,\r\n.slide-leave-active { transition: 0.5s cubic-bezier(0.68, -0.55, 0.265, 1.55); }\r\n.slide-leave { transform: scale3d(1, 1, 1); }\r\n\r\n.slide-leave-to {\r\n opacity: 0;\r\n transform: scale3d(2, 0.5, 1) translate3d(-400px, 0, 0);\r\n}\r\n\r\n.rotate-enter { transform: perspective(500px) rotate3d(0, 1, 0, 90deg); }\r\n.rotate-enter-active,\r\n.rotate-leave-active { transition: 0.5s; }\r\n.rotate-leave-to { transform: perspective(500px) rotate3d(0, 1, 0, -90deg); }<\/code><\/pre>\napp.vue<\/code> file. You can also keep a Sass partial of all the transitions in the project\u2019s assets folder and import it into the app\u2019s style block.<\/p>\n<style lang=\"scss\">\r\n @import \"assets\/_transitions.scss\";\r\n<\/style><\/code><\/pre>\nmain.js<\/code> file.<\/p>\nrequire(\"@\/assets\/transitions.css\");<\/code><\/pre>\nindex.html<\/code> file.<\/p>\n<link rel=\"stylesheet\" type=\"text\/css\" href=\"\/css\/transitions.css\"><\/code><\/pre>\nNow, let\u2019s slow down a minute<\/h3>\n
prefers-reduced-motion<\/code><\/a> media query to assist with possible Vestibular Spectrum Disorder<\/strong> issues. Eric Bailey also posted a nice introduction<\/a> to the media query as well.<\/p>\n.next-enter {\r\n opacity: 0;\r\n transform: scale3d(2, 0.5, 1) translate3d(400px, 0, 0);\r\n}\r\n\r\n.next-enter-to { transform: scale3d(1, 1, 1); }\r\n.next-enter-active,\r\n.next-leave-active { transition: 0.5s cubic-bezier(0.68, -0.55, 0.265, 1.55); }\r\n.next-leave { transform: scale3d(1, 1, 1); }\r\n\r\n.next-leave-to {\r\n opacity: 0;\r\n transform: scale3d(2, 0.5, 1) translate3d(-400px, 0, 0);\r\n}\r\n\r\n\/* If animations are reduced at the OS level, use simpler transitions *\/\r\n@media screen and (prefers-reduced-motion: reduce) {\r\n .next-enter {\r\n opacity: 0;\r\n transform: translate3d(100px, 0, 0);\r\n }\r\n\r\n .next-enter-active,\r\n .next-leave-active { transition: 0.5s; }\r\n\r\n .next-leave-to {\r\n opacity: 0;\r\n transform: translate3d(-100px, 0, 0);\r\n }\r\n}<\/code><\/pre>\nnone<\/code>.<\/p>\nLet\u2019s stay flexible with our transitions collection<\/h3>\n
transition-duration<\/code> needs to be different. There are ways to adjust for that without having to create a whole new transition name.<\/p>\n<transition name=\"fade\">\r\n <div style=\"transition-duration: 6s;\" v-if=\"isVisible\">this has a different duration<\/div>\r\n<\/transition><\/code><\/pre>\nis<\/code> attribute for dynamic components such as this:<\/p>\n<transition name=\"fade\" mode=\"out-in\">\r\n <component :is=\"currentComponent\"><\/component>\r\n<\/transition><\/code><\/pre>\n<transition name=\"fade\" mode=\"out-in\">\r\n <component :is=\"currentComponent\" style=\"transition-duration: 6s;\"><\/component>\r\n<\/transition><\/code><\/pre>\n<transition name=\"fade\" mode=\"out-in\">\r\n <component :is=\"currentComponent\" duration=\"6s\"><\/component>\r\n<\/transition><\/code><\/pre>\n<template>\r\n <div :style=\"`transition-duration: ${duration}`\">component one<\/div>\r\n<\/template>\r\n\r\n<script>\r\nexport default {\r\n name: \"component-one\",\r\n props: {\r\n duration: String\r\n }\r\n};\r\n<\/script><\/code><\/pre>\n<style scoped>\r\n .fade-enter-active,\r\n .fade-leave-active { transition-duration: 1s; }\r\n<\/style><\/code><\/pre>\n<style scoped>\r\n .fade-enter-active { transition-duration: 1s; }\r\n .fade-leave-active { transition-duration: 2s; }\r\n<\/style><\/code><\/pre>\nDynamic transitions<\/h3>\n
name<\/code> attribute on the transition component can be dynamic in nature, meaning we can change the current transition in use at will.<\/p>\nExample 1: Change transition based on an answer<\/h4>\n
\nVueJS Dynamic Transitions: Change Transition Based on an Answer<\/a> by Travis Almand (@talmand<\/a>)
\non CodePen<\/a>.<\/span>\n<\/p>\n<transition :name=\"currentTransition\">\r\n <div id=\"notification\" :class=\"response.toString()\" v-if=\"answerChecked\">{{ response }}<\/div>\r\n<\/transition><\/code><\/pre>\nv-if<\/code> on the notification div. We also apply a true<\/code> or false<\/code> class to decorate the notification based on the response.<\/p>\n.positive-enter-active { animation: positive 1s; }\r\n@keyframes positive {\r\n 0% { transform: translate3d(0, 0, 0); }\r\n 25% { transform: translate3d(0, -20px, 0); }\r\n 50% { transform: translate3d(0, 20px, 0); }\r\n 75% { transform: translate3d(0, -20px, 0); }\r\n 100% { transform: translate3d(0, 0, 0); }\r\n}\r\n\r\n.negative-enter-active { animation: negative 1s; }\r\n@keyframes negative {\r\n 0% { transform: translate3d(0, 0, 0); }\r\n 25% { transform: translate3d(-20px, 0, 0); }\r\n 50% { transform: translate3d(20px, 0, 0); }\r\n 75% { transform: translate3d(-20px, 0, 0); }\r\n 100% { transform: translate3d(0, 0, 0); }\r\n}<\/code><\/pre>\nmethods: {\r\n randomProblem: function () {\r\n this.a = Math.floor(Math.random() * Math.floor(10));\r\n this.b = Math.floor(Math.random() * Math.floor(10));\r\n },\r\n check: function () {\r\n this.response = this.a + this.b === parseInt(this.answer);\r\n this.answerChecked = true;\r\n this.currentTransition = this.response ? 'positive' : 'negative';\r\n },\r\n reset: function () {\r\n this.answer = null;\r\n this.answerChecked = false;\r\n this.randomProblem();\r\n }\r\n}<\/code><\/pre>\nrandomProblem<\/code> method that sets up our equation. The check<\/code> method that decides on which transition effect to use based on comparing the provided answer with the correct answer. Then the simple reset<\/code> method that just, well, resets everything.<\/p>\nExample 2: Change transition based on user interaction<\/h4>\n
\nVueJS Dynamic Transitions: Change Transition Based on User Interaction<\/a> by Travis Almand (@talmand<\/a>)
\non CodePen<\/a>.<\/span>\n<\/p>\n<transition :name=\"currentTransition\" mode=\"out-in\">\r\n <component :is=\"slides[currentSlide]\"><\/component>\r\n<\/transition><\/code><\/pre>\nis<\/code> attribute on the component element.<\/p>\n.next-enter {\r\n opacity: 0;\r\n transform: scale3d(2, 0.5, 1) translate3d(400px, 0, 0);\r\n}\r\n\r\n.next-enter-to { transform: scale3d(1, 1, 1); }\r\n.next-enter-active,\r\n.next-leave-active { transition: 0.5s cubic-bezier(0.68, -0.55, 0.265, 1.55); }\r\n.next-leave { transform: scale3d(1, 1, 1); }\r\n\r\n.next-leave-to {\r\n opacity: 0;\r\n transform: scale3d(2, 0.5, 1) translate3d(-400px, 0, 0);\r\n}\r\n\r\n.prev-enter {\r\n opacity: 0;\r\n transform: scale3d(2, 0.5, 1) translate3d(-400px, 0, 0);\r\n}\r\n\r\n.prev-enter-to { transform: scale3d(1, 1, 1); }\r\n.prev-enter-active,\r\n.prev-leave-active { transition: 0.5s cubic-bezier(0.68, -0.55, 0.265, 1.55); }\r\n.prev-leave { transform: scale3d(1, 1, 1); }\r\n\r\n.prev-leave-to {\r\n opacity: 0;\r\n transform: scale3d(2, 0.5, 1) translate3d(400px, 0, 0);\r\n}\r\n\r\n\/* If animations are reduced at the OS level, use simpler transitions *\/\r\n@media screen and (prefers-reduced-motion: reduce) {\r\n .next-enter { opacity: 0; transform: translate3d(100px, 0, 0); }\r\n .next-enter-active,\r\n .next-leave-active { transition: 0.5s; }\r\n .next-leave-to { opacity: 0; transform: translate3d(-100px, 0, 0); }\r\n \r\n .prev-enter { opacity: 0; transform: translate3d(-100px, 0, 0); }\r\n .prev-enter-active,\r\n .prev-leave-active { transition: 0.5s; }\r\n .prev-leave-to { opacity: 0; transform: translate3d(100px, 0, 0); }\r\n}<\/code><\/pre>\ntransform<\/code> property, but with a few extras to create a kind of squeezing effect for a cartoonish feel. We also make use of prefers-reduced-motion<\/code> to change the animation to be a simpler fade with a small slide to the side in the appropriate direction.<\/p>\nmethods: {\r\n changeSlide: function (dir) {\r\n this.currentSlide = dir === 'next' ? this.currentSlide + 1 : this.currentSlide - 1;\r\n this.currentTransition = dir;\r\n }\r\n}<\/code><\/pre>\nchangeSlide<\/code> method on its click event and passes which direction it represents. Then we have some logic to keep track of what the current slide happens to be. A single line controls which transition to use. Since the \u201cnext\u201d button passes \u201cnext\u201d as the direction it corresponds to the \u201cnext\u201d transition in the CSS. Same for the “prev<\/abbr>” button. Each time the user clicks a button, the app automatically knows which transition to use. Thus, we have nice transition effects that provide context as to which direction the user is progressing through the sequence.<\/p>\nExample 3: Change transition based on list state<\/h4>\n
transition-group<\/code> component. The idea here is a list to be updated an item at a time with a different transition each time.<\/p>\n
\nVueJS Dynamic Transitions: Change Transition Based on List State<\/a> by Travis Almand (@talmand<\/a>)
\non CodePen<\/a>.<\/span>\n<\/p>\n<transition-group :name=\"currentListTransition\" tag=\"ul\" class=\"list\">\r\n <li v-for=\"(item, index) in selectedItems\" :key=\"item\">{{ item }}<\/li>\r\n<\/transition-group><\/code><\/pre>\n.top-enter-active,\r\n.top-leave-active { transition: 0.5s; }\r\n.top-enter,\r\n.top-leave-to {\r\n opacity: 0;\r\n transform: translate3d(0, -40px, 0);\r\n}\r\n\r\n.top-move {\r\n opacity: 0.5;\r\n transition: 0.5s;\r\n}\r\n\r\n.left-enter-active,\r\n.left-leave-active { transition: 0.5s; }\r\n.left-enter,\r\n.left-leave-to {\r\n opacity: 0;\r\n transform: translate3d(-40px, 0, 0);\r\n}\r\n\r\n.left-move {\r\n opacity: 0.5;\r\n transition: 0.5s;\r\n}\r\n\r\n.right-enter-active,\r\n.right-leave-active { transition: 0.5s; }\r\n.right-enter,\r\n.right-leave-to {\r\n opacity: 0;\r\n transform: translate3d(40px, 0, 0);\r\n}\r\n\r\n.right-move {\r\n opacity: 0.5;\r\n transition: 0.5s;\r\n}\r\n\r\n.bottom-enter-active,\r\n.bottom-leave-active { transition: 0.5s; }\r\n.bottom-enter,\r\n.bottom-leave-to {\r\n opacity: 0;\r\n transform: translate3d(0, 30px, 0);\r\n}\r\n\r\n.bottom-move {\r\n opacity: 0.5;\r\n transition: 0.5s;\r\n}\r\n\r\n\/* If animations are reduced at the OS level, turn off transitions *\/\r\n@media screen and (prefers-reduced-motion: reduce) {\r\n .top-enter-active,\r\n .top-leave-active { transition: none; }\r\n .top-move { transition: none; }\r\n .left-enter-active,\r\n .left-leave-active { transition: none; }\r\n .left-move { transition: none; }\r\n .right-enter-active,\r\n .right-leave-active { transition: none; }\r\n .right-move { transition: none; }\r\n .bottom-enter-active,\r\n .bottom-leave-active { transition: none; }\r\n .bottom-move { transition: none; }\r\n}<\/code><\/pre>\nmethods: {\r\n chooseCity: function (index) {\r\n let selectedLength = this.selectedItems.length;\r\n let citiesLength = this.cities.length;\r\n let clt = this.currentListTransition;\r\n \r\n if (selectedLength === 0) {\r\n clt = 'top';\r\n } else if (selectedLength > 0 && selectedLength < citiesLength - 1) {\r\n clt = clt === 'top' || clt === 'left' ? 'right' : 'left';\r\n } else if (selectedLength === citiesLength - 1) {\r\n clt = 'bottom';\r\n }\r\n \r\n this.currentListTransition = clt;\r\n this.selectedItems.push(this.cities[index]);\r\n document.querySelector(`.city:nth-child(${index + 1})`).classList.add('selected');\r\n },\r\n\r\n clearSelection: function () {\r\n this.currentListTransition = 'right';\r\n this.selectedItems = [];\r\n document.querySelectorAll('.city.selected').forEach(element => {\r\n element.classList.remove('selected');\r\n });\r\n }\r\n}<\/code><\/pre>\nchooseCity<\/code> method handles what happens as you choose each city. What we mostly care about is the series of if<\/code> and if<\/code>\/else<\/code> statements in the middle of the method. As cities are selected, the logic looks at the current length of the selectedItems<\/code> array that the selected cities eventually get pushed into. If the length is zero, then that\u2019s the first city, so the transition should have it come in from the top. If the length is between zero and the total number of our cities list, then the transition should be right or left. The new direction used is based on the direction of the previous transition direction. Then, finally, if we\u2019re on the last city to be chosen, it\u2019ll change to the bottom transition. Again we use prefers-reduced-motion<\/code>, in this case to turn off the transitions altogether.<\/p>\nSo long, and thanks for all the transitions<\/h3>\n