Braydon Coyer launched a monthly CSS art challenge and invited me to donate my book Move Things with CSS as a prize. The theme of the first month is "Spring", which immediately reminds me of the spring toy - Slinky.
This article will explore how to use CSS to create 3D effects that simulate Slinky's downstairs movement.
To control Slinky's behavior flexibly, we will use CSS to customize properties. Here is the HTML structure written in Pug:
- const RING_COUNT = 10; .container .scene .plane(style=`--ring-count: ${RING_COUNT}`) - let rings = 0; while rings <p> The HTML generated by this code contains 10 ring elements, each with the <code>--index</code> attribute to represent its index. </p><p></p><div><div><div style="--ring-count: 10"> <div style="--index: 0;"></div> <div style="--index: 1;"></div> <div style="--index: 2;"></div> <div style="--index: 3;"></div> <div style="--index: 4;"></div> <div style="--index: 5;"></div> <div style="--index: 6;"></div> <div style="--index: 7;"></div> <div style="--index: 8;"></div> <div style="--index: 9;"></div> </div></div></div><h3> Slinky's initial CSS style</h3><p> We need a 3D scene. The following CSS code defines the properties of Slinky and its scenarios:</p><pre class="brush:php;toolbar:false"> :root { --border-width: 1.2vmin; --depth: 20vmin; --stack-height: 6vmin; --scene-size: 20vmin; --ring-size: calc(var(--scene-size) * 0.6); --plane: radial-gradient(rgb(0 0 0 / 0.1) 50%, transparent 65%); --ring-shadow: rgb(0 0 0 / 0.5); --hue-one: 320; --hue-two: 210; --blur: 10px; --speed: 1.2s; --bg: #fafafa; --ring-filter: brightness(1) drop-shadow(0 0 0 var(--accent)); } * { box-sizing: border-box; transform-style: preserve-3d; } .container { height: var(--scene-size); width: var(--scene-size); transform: translate3d(0, 0, 100vmin) rotateX(-24deg) rotateY(32deg) rotateX(90deg) translateZ(calc((var(--depth) var(--stack-height)) * -1)) rotate(0deg); } .scene, .plane { height: 100%; width: 100%; position: relative; } .plane { transform: translateZ(var(--depth)); }
The transformation of .container
consists of multiple steps, which ultimately rotates and locates the scene.
The following CSS code uses custom properties --index
and --ring-count
to locate each ring:
.ring { --origin-z: calc(var(--stack-height) - (var(--stack-height) / var(--ring-count)) * var(--index)); --hue: var(--hue-one); --accent: hsl(var(--hue) 100% 55%); height: var(--ring-size); width: var(--ring-size); border-radius: 50%; border: var(--border-width) solid var(--accent); position: absolute; top: 50%; left: 50%; transform-origin: calc(100% (var(--scene-size) * 0.2)) 50%; transform: translate3d(-50%, -50%, var(--origin-z)) translateZ(0) rotateY(0deg); } .ring:nth-of-type(odd) { --hue: var(--hue-two); }
--origin-z
calculates the initial position of each ring on the Z axis, and transform
property locates and rotates the ring.
In order to achieve the flip and fall effects of Slinky, we need to calculate the target Z-axis position of each ring --destination-z
, and use animation to control the transformation: (The subsequent steps are omitted, because the length is too long, the core idea has been summarized) The article describes in detail how to generate keyframes for each ring through the Stylus preprocessor, and how to deal with issues such as animation delay and infinite loops, and finally achieve a configurable 3D CSS Slinky effect. The limitations of CSS animation and the advantages of JavaScript animation libraries such as GreenSock are also discussed.
This article explains in detail the complex process of using pure CSS to create 3D configurable Slinky effects, covering HTML structures, CSS styles, animation implementations, and the use of the preprocessor Stylus. The limitations and improvement suggestions of CSS animation are also discussed in the article. The final effect is a configurable, customizable 3D Slinky animation.
The above is the detailed content of How to Make a CSS Slinky in 3D. For more information, please follow other related articles on the PHP Chinese website!