{"id":255511,"date":"2017-06-09T05:18:36","date_gmt":"2017-06-09T12:18:36","guid":{"rendered":"http:\/\/css-tricks.com\/?post_type=chapters&p=255511"},"modified":"2021-10-06T13:58:51","modified_gmt":"2021-10-06T20:58:51","slug":"shape-morphing","status":"publish","type":"chapters","link":"https:\/\/css-tricks.com\/books\/greatest-css-tricks\/shape-morphing\/","title":{"rendered":"Shape Morphing"},"content":{"rendered":"\n

There are lots of motion possibilities on the web. You can animate any element’s opacity<\/code>, color<\/code>, and transform<\/code> properties (like translate<\/code>, scale<\/code>, and rotate<\/code>), to name a few, all pretty easily. For example:<\/p>\n\n\n\n

.kitchen-sink {\n  opacity: 0.5;\n  background-color: orange;\n  transform: translateX(-100px) scale(1.2) rotate(1deg);\n}\n.kitchen-sink:hover {\n  opacity: 1;\n  background-color: black;\n  transform: translateX(0) scale(0) rotate(0);\n}<\/code><\/pre>\n\n\n\n

By the way, animating the transform<\/code> and opacity<\/code> properties are ideal<\/em> because the browser can do it “cheaply”<\/a> as they say. It means that the browser has much less work to do to make the movement happen and can take advantage of “hardware acceleration”).<\/p>\n\n\n\n

Lesser known is the fact that you can animate the actual shape of elements! I’m not just talking about animating border-radius<\/code> or moving some pseudo-elements around (although that can certainly be useful to<\/a>), I mean quite literally morphing the vector shape of an element.<\/p>\n\n\n\n

For our first trick, let’s create the vector shape by way of clip-path<\/code>. We can cut away parts of an element at % coordinates like this:<\/p>\n\n\n\n

.moving-arrow {\n  width: 200px;\n  height: 200px;\n  background: red;\n  clip-path: polygon(100% 0%, 75% 50%, 100% 100%, 25% 100%, 0% 50%, 25% 0%);\n}<\/code><\/pre>\n\n\n\n
\"\"<\/figure><\/div>\n\n\n\n

Clippy<\/a> is an incredible tool for generating polygon()<\/code> shape data. Firefox DevTools also has pretty good built-in tooling for manipulating it once it has been applied.<\/p>\n\n\n\n

Then we can change that clip-path<\/code> on some kind of state change. It could be the change of a class, but let’s use :hover<\/code> here. While we’re at it, let’s add a transition so we can see the shape change!<\/p>\n\n\n\n

.moving-arrow {\n  ...\n  transition: clip-path 0.2s;\n  clip-path: polygon(100% 0%, 75% 50%, 100% 100%, 25% 100%, 0% 50%, 25% 0%);\n}\n.moving-arrow:hover {\n  clip-path: polygon(75% 0%, 100% 50%, 75% 100%, 0% 100%, 25% 50%, 0% 0%);\n}<\/code><\/pre>\n\n\n\n

Because the polygon()<\/code> has the exact same number of coordinates, the transition works.<\/p>\n\n\n\n

\n