{"id":3097,"date":"2021-12-08T15:49:37","date_gmt":"2021-12-08T15:49:37","guid":{"rendered":"https:\/\/rengga.dev\/blog\/?p=3097"},"modified":"2023-06-12T14:39:03","modified_gmt":"2023-06-12T14:39:03","slug":"css-tutorial-animxyz","status":"publish","type":"post","link":"https:\/\/rengga.dev\/blog\/css-tutorial-animxyz\/","title":{"rendered":"CSS Tutorial &#8211; AnimXYZ"},"content":{"rendered":"<p><span style=\"color: #ef3207;\"><a style=\"color: #ef3207;\" href=\"https:\/\/rengga.dev\/\" target=\"_blank\" rel=\"noopener\"><strong>Rengga Dev<\/strong><\/a> <\/span>&#8211; There are\u00a0quite a few CSS animation libraries. They tend to be a pile of class names that you can apply as needed like \u201cbounce\u201d or \u201cslide-right\u201d and it\u2019ll\u2026 do those things. They tend to be pretty opinionated with nice defaults, and not particularly designed around customization.<\/p>\n<p>It looks like\u00a0<a href=\"https:\/\/animxyz.com\/\" rel=\"noopener\">AnimXYZ<\/a>\u00a0is designed to be highly customizable, calling itself \u201cthe first composable CSS animation toolkit.\u201d<\/p>\n<p>You use as many of the different composable bits as you need to get the in\/out animation you want. Play with their builder and you\u2019ll see output like:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"html\">&lt;div\r\n  class=\"square-group\"\r\n  xyz=\"tall-2 duration-6 ease-out-back stagger-1 skew-left-2 big-25% fade-50% right-5\"\r\n&gt;\r\n  &lt;div class=\"square xyz-out\"&gt;&lt;\/div&gt;\r\n  &lt;div class=\"square xyz-out\"&gt;&lt;\/div&gt;\r\n  &lt;div class=\"square xyz-out\"&gt;&lt;\/div&gt;\r\n&lt;\/div&gt;<\/pre>\n<p>The class name\u00a0<code>xyz-out<\/code>\u00a0becomes\u00a0<code>xyz-in<\/code>\u00a0to trigger the opposite animation.<\/p>\n<p>All those attribute values are reminiscent of\u00a0<a href=\"https:\/\/tailwindcss.com\/\" rel=\"noopener\">Tailwind<\/a>. To use Tailwind effectively, the build process runs\u00a0<a href=\"https:\/\/purgecss.com\/\" rel=\"noopener\">PurgeCSS<\/a>\u00a0to remove all unused classes, which will serve a tiny fraction of the complete set of classes Tailwind offers. I think of that because the processed stylesheet of AnimXYZ is\u00a0<a href=\"https:\/\/cdn.jsdelivr.net\/npm\/@animxyz\/core@0.3.0\/dist\/animxyz.min.css\" rel=\"noopener\">~9.7 kB<\/a>\u00a0compressed, which is larger than the file size Tailwind uses as an\u00a0<a href=\"https:\/\/d.pr\/i\/LosLwa\">example<\/a>\u00a0on their marketing page.\u00a0<strong>The point being, if classes were used, there would probably be a more straightforward way of purging the unused classes<\/strong>, which I bet would make the size almost negligible. Perhaps the JavaScript framework-specific usage is more clever.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"css\">body {\r\n  background: #171c33;\r\n  margin: 0;\r\n}\r\n\r\n.square-group {\r\n  display: flex;\r\n  gap: 1rem;\r\n  align-items: center;\r\n  justify-content: center;\r\n  height: 100vh;\r\n}\r\n.square {\r\n  background: #57cbf2;\r\n  width: 8vw;\r\n  height: 8vw;\r\n}<\/pre>\n<p>But those criticisms aside, it\u2019s cool! Not only are there smart defaults that are highly composable, you have 100% control via CSS Custom Properties.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"js\">const squares = document.querySelectorAll(\".square\");\r\n\r\nsetInterval(() =&gt; {\r\n  squares.forEach((square) =&gt; {\r\n    square.classList.toggle(\"xyz-in\");\r\n    square.classList.toggle(\"xyz-out\");\r\n  });\r\n}, 1200);<\/pre>\n<p><iframe style=\"width: 100%;\" title=\"Playing with AnimXYZ\" src=\"https:\/\/codepen.io\/chriscoyier\/embed\/RwGqrEd?default-tab=result&amp;theme-id=dark\" height=\"300\" frameborder=\"no\" scrolling=\"no\" allowfullscreen=\"allowfullscreen\"><br \/>\nSee the Pen <a href=\"https:\/\/codepen.io\/chriscoyier\/pen\/RwGqrEd\"><br \/>\nPlaying with AnimXYZ<\/a> by Chris Coyier  (<a href=\"https:\/\/codepen.io\/chriscoyier\">@chriscoyier<\/a>)<br \/>\non <a href=\"https:\/\/codepen.io\">CodePen<\/a>.<br \/>\n<\/iframe><br \/>\nDon\u2019t miss the XYZ-ray button on the lower right of the website that lets you see what animations are powering what elements. It\u2019s also on the docs which\u00a0<a href=\"https:\/\/animxyz.com\/docs\/\" rel=\"noopener\">are super nice<\/a>.<\/p>\n<p>There is just something nice about declarative animations.\u00a0I remember chatting with Matt Perry\u00a0about Framer Motion and enjoying its approach.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Rengga Dev &#8211; There are\u00a0quite a few CSS animation libraries. They tend <a class=\"read-more\" href=\"https:\/\/rengga.dev\/blog\/css-tutorial-animxyz\/\" title=\"CSS Tutorial &#8211; AnimXYZ\" itemprop=\"url\"><\/a><\/p>\n","protected":false},"author":1,"featured_media":3773,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[11,2],"tags":[290,268,197,103,227],"newstopic":[573,572],"class_list":{"0":"post-3097","1":"post","2":"type-post","3":"status-publish","4":"format-standard","5":"has-post-thumbnail","7":"category-html-css","8":"category-web-design","9":"tag-animxyz","10":"tag-css-grid","11":"tag-css-tutorial","12":"tag-web-design","13":"tag-web-designer","14":"newstopic-css","15":"newstopic-html"},"_links":{"self":[{"href":"https:\/\/rengga.dev\/blog\/wp-json\/wp\/v2\/posts\/3097","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/rengga.dev\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/rengga.dev\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/rengga.dev\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/rengga.dev\/blog\/wp-json\/wp\/v2\/comments?post=3097"}],"version-history":[{"count":1,"href":"https:\/\/rengga.dev\/blog\/wp-json\/wp\/v2\/posts\/3097\/revisions"}],"predecessor-version":[{"id":3099,"href":"https:\/\/rengga.dev\/blog\/wp-json\/wp\/v2\/posts\/3097\/revisions\/3099"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/rengga.dev\/blog\/wp-json\/wp\/v2\/media\/3773"}],"wp:attachment":[{"href":"https:\/\/rengga.dev\/blog\/wp-json\/wp\/v2\/media?parent=3097"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/rengga.dev\/blog\/wp-json\/wp\/v2\/categories?post=3097"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/rengga.dev\/blog\/wp-json\/wp\/v2\/tags?post=3097"},{"taxonomy":"newstopic","embeddable":true,"href":"https:\/\/rengga.dev\/blog\/wp-json\/wp\/v2\/newstopic?post=3097"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}