An isometric hairline vending machine drops one accent can from its bottom shelf into the tray, where it lands with a small bounce. The front panel is cut with real holes, so the can falls behind it.
Also known as: hairline animation, isometric vending machine, vending machine css animation.
<div class="hln-vending-drop" role="img" aria-label="A vending machine dropping a can">
<svg viewBox="-110 -60 220 120" aria-hidden="true">
<g transform="translate(-.9 14.1) scale(.86)">
<polygon points="-28,14 2,29 2,-33 -28,-48"/>
<polygon points="0,-62 30,-47 2,-33 -28,-48"/>
<line class="hln-vending-drop-l" x1="-2" y1="-57" x2="20" y2="-46"/>
<line class="hln-vending-drop-l" x1="-10" y1="-53" x2="12" y2="-42"/>
<line class="hln-vending-drop-l" x1="-18" y1="-49" x2="4" y2="-38"/>
<clipPath id="hln-vending-drop-win"><rect transform="matrix(1 -.5 0 -1 2 29)" x="3" y="20" width="16" height="38"/><rect transform="matrix(1 -.5 0 -1 2 29)" x="3" y="5" width="16" height="8"/></clipPath>
<g transform="matrix(1 -.5 0 -1 2 29)"><rect class="hln-vending-drop-w" x="3" y="20" width="16" height="38"/><rect class="hln-vending-drop-w" x="3" y="5" width="16" height="8"/></g>
<g clip-path="url(#hln-vending-drop-win)"><polygon class="hln-vending-drop-l" points="13,-6.5 21,-2.5 5,5.5 -3,1.5"/><g><path d="M13.1,-9.75 V-3.25 A2.4,1.2 0 0 0 17.9,-3.25 V-9.75 Z"/><ellipse cx="15.5" cy="-9.75" rx="2.4" ry="1.2"/></g><g><path d="M5.1,-5.75 V0.75 A2.4,1.2 0 0 0 9.9,0.75 V-5.75 Z"/><ellipse cx="7.5" cy="-5.75" rx="2.4" ry="1.2"/></g><g><path d="M1.1,-3.75 V2.75 A2.4,1.2 0 0 0 5.9,2.75 V-3.75 Z"/><ellipse cx="3.5" cy="-3.75" rx="2.4" ry="1.2"/></g><polygon class="hln-vending-drop-l" points="13,-18.5 21,-14.5 5,-6.5 -3,-10.5"/><g><path d="M13.1,-21.75 V-15.25 A2.4,1.2 0 0 0 17.9,-15.25 V-21.75 Z"/><ellipse cx="15.5" cy="-21.75" rx="2.4" ry="1.2"/></g><g><path d="M9.1,-19.75 V-13.25 A2.4,1.2 0 0 0 13.9,-13.25 V-19.75 Z"/><ellipse cx="11.5" cy="-19.75" rx="2.4" ry="1.2"/></g><g><path d="M5.1,-17.75 V-11.25 A2.4,1.2 0 0 0 9.9,-11.25 V-17.75 Z"/><ellipse cx="7.5" cy="-17.75" rx="2.4" ry="1.2"/></g><g><path d="M1.1,-15.75 V-9.25 A2.4,1.2 0 0 0 5.9,-9.25 V-15.75 Z"/><ellipse cx="3.5" cy="-15.75" rx="2.4" ry="1.2"/></g><polygon class="hln-vending-drop-l" points="13,-30.5 21,-26.5 5,-18.5 -3,-22.5"/><g><path d="M13.1,-33.75 V-27.25 A2.4,1.2 0 0 0 17.9,-27.25 V-33.75 Z"/><ellipse cx="15.5" cy="-33.75" rx="2.4" ry="1.2"/></g><g><path d="M9.1,-31.75 V-25.25 A2.4,1.2 0 0 0 13.9,-25.25 V-31.75 Z"/><ellipse cx="11.5" cy="-31.75" rx="2.4" ry="1.2"/></g><g><path d="M5.1,-29.75 V-23.25 A2.4,1.2 0 0 0 9.9,-23.25 V-29.75 Z"/><ellipse cx="7.5" cy="-29.75" rx="2.4" ry="1.2"/></g><g><path d="M1.1,-27.75 V-21.25 A2.4,1.2 0 0 0 5.9,-21.25 V-27.75 Z"/><ellipse cx="3.5" cy="-27.75" rx="2.4" ry="1.2"/></g><g class="hln-vending-drop-can"><g class="hln-vending-drop-a"><path d="M9.1,-7.75 V-1.25 A2.4,1.2 0 0 0 13.9,-1.25 V-7.75 Z"/><ellipse cx="11.5" cy="-7.75" rx="2.4" ry="1.2"/></g></g></g>
<g transform="matrix(1 -.5 0 -1 2 29)"><path d="M0,0 h28 v62 h-28 Z M3,20 h16 v38 h-16 Z M3,5 h16 v8 h-16 Z" fill-rule="evenodd"/><rect class="hln-vending-drop-o" x="3" y="20" width="16" height="38"/><rect class="hln-vending-drop-o" x="3" y="5" width="16" height="8"/><line class="hln-vending-drop-l" x1="3" y1="2.5" x2="25" y2="2.5"/><rect class="hln-vending-drop-l" x="21.5" y="42" width="1.6" height="1.6" rx="0.3"/><rect class="hln-vending-drop-l" x="23.9" y="42" width="1.6" height="1.6" rx="0.3"/><rect class="hln-vending-drop-l" x="21.5" y="44.6" width="1.6" height="1.6" rx="0.3"/><rect class="hln-vending-drop-l" x="23.9" y="44.6" width="1.6" height="1.6" rx="0.3"/><rect class="hln-vending-drop-l" x="21.5" y="47.2" width="1.6" height="1.6" rx="0.3"/><rect class="hln-vending-drop-l" x="23.9" y="47.2" width="1.6" height="1.6" rx="0.3"/><rect class="hln-vending-drop-l" x="21.5" y="49.8" width="1.6" height="1.6" rx="0.3"/><rect class="hln-vending-drop-l" x="23.9" y="49.8" width="1.6" height="1.6" rx="0.3"/><rect class="hln-vending-drop-l" x="21.5" y="36" width="4" height="1.4" rx="0.5"/><line class="hln-vending-drop-l" x1="5" y1="54" x2="9" y2="58"/><line class="hln-vending-drop-l" x1="5" y1="50" x2="12" y2="57"/></g>
</g>
</svg>
</div>.hln-vending-drop {
--c: var(--hln-color, #ff4f2e);
font-size: var(--hln-size, 16px);
position: relative;
display: grid;
place-items: center;
width: 22em;
height: 12em;
border-radius: 0.75em;
background: #f6f5f1;
overflow: hidden;
}
.hln-vending-drop svg {
width: 100%;
height: 100%;
overflow: visible;
fill: #ffffff;
stroke: #1c1d21;
stroke-width: 1.25;
stroke-linejoin: round;
stroke-linecap: round;
}
.hln-vending-drop svg * {
vector-effect: non-scaling-stroke;
}
.hln-vending-drop .hln-vending-drop-o {
fill: none;
}
.hln-vending-drop .hln-vending-drop-l {
stroke: #9a9ca3;
}
.hln-vending-drop .hln-vending-drop-w {
fill: #ffffff;
stroke: none;
}
.hln-vending-drop .hln-vending-drop-a {
stroke: var(--c);
}
.hln-vending-drop .hln-vending-drop-can {
transform: matrix(1, 0, 0, 1, 0, 17);
animation: hln-vending-drop-drop 5s infinite;
}
@keyframes hln-vending-drop-drop {
0% { transform: matrix(1, 0, 0, 1, 0, -3); opacity: 0; }
3% { transform: matrix(1, 0, 0, 1, 0, -3); opacity: 0; animation-timing-function: cubic-bezier(.22,1,.36,1); }
10% { transform: matrix(1, 0, 0, 1, 0, 0); opacity: 1; }
20% { transform: matrix(1, 0, 0, 1, 0, 0); opacity: 1; animation-timing-function: cubic-bezier(.55,0,.85,.3); }
29% { transform: matrix(1, 0, 0, 1, 0, 17); opacity: 1; animation-timing-function: linear(0, 0.035, 0.125, 0.247, 0.384, 0.524, 0.655, 0.771, 0.87, 0.948, 1.008, 1.05, 1.077, 1.091, 1.095, 1.091, 1.083, 1.071, 1.058, 1.045, 1.032, 1.021, 1.012, 1.005, 0.999, 0.995, 0.993, 0.991, 0.991, 0.991, 0.992, 0.993, 1); }
42% { transform: matrix(1, 0, 0, 1, 0, 17); opacity: 1; }
84% { transform: matrix(1, 0, 0, 1, 0, 17); opacity: 1; }
90% { transform: matrix(1, 0, 0, 1, 0, 17); opacity: 0; }
100% { transform: matrix(1, 0, 0, 1, 0, -3); opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
.hln-vending-drop * {
animation: none !important;
}
}
@media (prefers-reduced-motion: reduce) {
.hln-vending-drop, .hln-vending-drop *, .hln-vending-drop::before, .hln-vending-drop::after, .hln-vending-drop *::before, .hln-vending-drop *::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}--hln-color on the element or a parent.
Currently previewing #3b82f6.--hln-size. Every other dimension is in
em, so the whole thing scales together. Currently previewing 16px.transition or animation
shorthand. Staggered delays are relative, so they keep their rhythm.