Loading video...

Video Failed to Load

Go Home

CSS Trick ๐Ÿค™ You can mask other elements with icons in CSS to create this glittery icon hover/interaction effect โœจ canvas { mask: url(/img/icons/next.svg); } Check this example, inspired by the new Vercel homepage treats that are dropping ๐Ÿ–ค (Had to have a go at whipping this up over...

210,485 views โ€ข 3 years ago โ€ขvia X (Twitter)

10 Comments

jhey โ–ฒ๐Ÿป๐ŸŽˆ's profile picture
jhey โ–ฒ๐Ÿป๐ŸŽˆ3 years ago

Here's that @CodePen link! ๐Ÿš€ This includes the exploded view stuff ๐Ÿ’ฃ

jhey โ–ฒ๐Ÿป๐ŸŽˆ's profile picture
jhey โ–ฒ๐Ÿป๐ŸŽˆ3 years ago

If you want a standalone version, this one's got you! ๐Ÿ‘‡

Ryan Florence's profile picture
Ryan Florence3 years ago

@vercel What's a snovra?

jhey โ–ฒ๐Ÿป๐ŸŽˆ's profile picture
jhey โ–ฒ๐Ÿป๐ŸŽˆ3 years ago

@vercel I did not see this until I posted it ๐Ÿคฆโ€โ™‚๏ธ Now people are pointing it out, I can't unsee it ๐Ÿ˜‚

Eduard Constantin's profile picture
Eduard Constantin3 years ago

@vercel I think this effect will look even better with this icons

jhey โ–ฒ๐Ÿป๐ŸŽˆ's profile picture
jhey โ–ฒ๐Ÿป๐ŸŽˆ3 years ago

@vercel It does look cool! ๐Ÿ’ฏ๐Ÿ‘

Erfan Ebrahimnia's profile picture
Erfan Ebrahimnia3 years ago

@vercel Beautiful ๐Ÿ˜ Are there performance aspects to consider with multiple canvas elements?

jhey โ–ฒ๐Ÿป๐ŸŽˆ's profile picture
jhey โ–ฒ๐Ÿป๐ŸŽˆ3 years ago

For sure! ๐Ÿ’ฏ And that's why I only activate the canvas particles on pointerenter and pointerleave โœจ GSAP has a great utility for this called gsap.ticker where you can control the fps as well as easily add and remove things to the ticker when needed ๐Ÿ˜Ž It saves having to manage requestAnimationFrame yourself ๐Ÿ™Œ

Aleks's profile picture
Aleks3 years ago

@vercel Too cool

jhey โ–ฒ๐Ÿป๐ŸŽˆ's profile picture
jhey โ–ฒ๐Ÿป๐ŸŽˆ3 years ago

@vercel Now I've got to get back to that tear strip ๐Ÿ˜ฉ๐Ÿ˜‚

Related Videos

CSS Trick! ๐Ÿค™ You can create gradient borders on translucent elements using mask-clip and mask-composite with a pseudo-element ๐Ÿ”ฅ .gradient-border::after { mask-clip: padding-box, border-box; mask-composite: intersect; mask: linear-gradient(transparent, transparent), linear-gradient(white, white); } It's the same "Transparent border trick" from before. But, now you apply it to a pseudo-element ๐Ÿ˜Ž The trick is to create a pseudo-element with a gradient background and then mask it so we only see the part we want, the border โœจ mask-clip defines the area affected by a mask. Similar to how you can define background-size. Using padding-box and border-box constrains the two masks. mask-composite is the magic part โœจ It defines a compositing operation for stacked mask layers. Using intersect means that the parts that overlap get replaced. And this seems to work in all browsers ๐Ÿ™Œ As for the rest of the styles... โ€“ Make sure you set pointer-events: none on the pseudo-element โ€“ Make sure it fills the parent element. You can use position: absolute and inset: 0 โ€“ Make sure the background fills the space including the border-width. You can use calc to achieve that: --bg-size: calc(100% + (2px * var(--border))); background: var(--gradient) center center / var(--bg-size) var(--bg-size); That's it! ๐Ÿš€ Gradient borders on translucent elements. You can set all the backdrop-filter: blur() you like! ๐Ÿ˜… CodePen.IO link below! ๐Ÿ‘‡

jhey ส•โ€ขแดฅโ€ขส”

269,945 views โ€ข 2 years ago

CSS Trick โšก๏ธ (ห—หห‹ rogie หŽหŠห— challenge edition ๐Ÿค™) You can create this secret code reveal with only CSS using :has() and trig functions ๐Ÿ”ฅ .digit::hover + .digit, .digit:has(+ .digit:hover) { --active: var(--lerp-1); } :root { --lerp-1: calc(sin(50deg)); } .digit { scale: calc(var(--active) + 0.5); } There are a couple of moving parts. The first thing we can do is set up a scale. :root { --lerp-0: 1; /* === sin(90deg) */ --lerp-1: calc(sin(50deg)); --lerp-2: calc(sin(45deg)); --lerp-3: calc(sin(35deg)); --lerp-4: calc(sin(25deg)); --lerp-5: calc(sin(15deg)); } The digit styles define scale and blur. They also dictate the transition duration .digit { transition: scale calc(((1 - var(--active, 0)) + 0.2) * 1s); } When a digit is hovered, then you can set the --active custom property based on the digit position ๐Ÿค™ The digit that is hovered. .digit:hover { --active: var(--lerp-0); } And the digit on either side of that hovered digit .digit:is(:hover, :focus-visible) + .digit, .digit:has(+ .digit:is(:hover, :focus-visible)) { --active: var(--lerp-1); } We can select the previous sibling using :has() and the next sibling with the sibling combinator (+) And that's it! โญ๏ธ That's how you create these hover scale interactions with CSS ๐Ÿ™Œ We're jus' waiting on Firefox for :has() support. When that lands, it'll likely break the internet ๐Ÿ˜… CodePen.IO link below! ๐Ÿ‘‡

jhey ส•โ€ขแดฅโ€ขส”

375,402 views โ€ข 2 years ago

CSS Tip! ๐Ÿค™ You can use mask-composite and some JavaScript to create this pointer proximity following glow border โœจ .glow { mask-composite: intersect; mask-clip: padding-box, border-box; mask: linear-gradient(#0000, #0000), conic-gradient(#0000 0deg, #โ€‹fff, #0000 45deg); } The trick is to mask a background-image with a combination of mask layers. mask-composite: intersect; means the mask used will be the intersection of the layers ๐Ÿ”ฅ use source-in, xor; in browsers that don't support intersect; In this demo, you can use pseudoelements and rely on scoped custom properties to do a lot of the heavy lifting for you ๐Ÿ™Œ Once you've masked the background, you need to update the starting angle of the conic-gradient on pointermove ๐Ÿ‘† You can work that out by getting the center point of each card and then calculating the angle between that and the pointer with Math.atan2 ๐Ÿค“ let ANGLE = Math.atan2( event?.y - CARD_CENTER[1], event?.x - CARD_CENTER[0] ) * 180 / Math.PI ANGLE = ANGLE < 0 ? ANGLE + 360 : ANGLE; CARD.โ€‹style.setProperty('--start', ANGLE + 90) You plug that into your conic-gradient mask as a custom property accounting for --spread โšก๏ธ conic-gradient(from calc((var(--angle) - (var(--spread) * 0.5)) * 1deg), #000 0deg, #โ€‹fff, #0000 calc(var(--spread) * 1deg)); To get the blur, you apply a blur to the glow container on each card ๐Ÿค™ .glows { filter: blur(calc(var(--blur) * 1px); } That's it! Layers of masks that are clipped and composited before being blurred ๐Ÿ˜Ž The added trick is to fade each one in when the pointer is in the defined proximity of the card. For example, don't show unless within 100px of a card. You can see that in the video. Check out the JavaScript code for that ๐Ÿซถ Couldn't resist making this one ๐Ÿ˜ CodePen.IO link below! ๐Ÿ‘‡

jhey ส•โ€ขแดฅโ€ขส”

1,180,399 views โ€ข 2 years ago

CSS Tip! โญ๏ธ You can use mix-blend-mode with scoped custom properties to create this inverted :hover effect ๐Ÿค™ button > span { left: calc(var(--x, 0) * 1px); top: calc(var(--y, 0) * 1px); mix-blend-mode: difference; ๐Ÿ‘ˆ } The cool trick is that using mix-blend-mode acts like a color inverter which works well with monochromatic controls ๐Ÿ˜ Saves defining the :hover colors, etc. It works it out for you! As for how to move that spot around? A teeny bit of JavaScript ๐Ÿค const UPDATE = ({target, x, y }) => { const bounds = target.getBoundingClientRect() targetโ€‹.style.setProperty('--x', x - bounds.left) targetโ€‹.style.setProperty('--y', y - boundsโ€‹.top) } const BTNS = document.querySelectorAll('button') BTNS.forEach(BTN => BTN.addEventListener('pointermove', UPDATE)) On :hover you can use a scoped custom property to change the size of the spot button:is(:hover, :focus-visible) { --active: 1; } button span { transform: translate(-50%, -50%) scale(calc(var(--active, 0) * 3); transition: transform 0.25s; } But, what about the bouncy easy? You can use linear() where supported to create a bouncy transition โœจ @โ€‹supports (transition-timing-function: linear(0, 1)) { button:is(:hover, :focus-visible) span { transition-duration: 0.5s; transition-timing-function: linear( 0, 0.5007 7.21%, 0.7803 12.29%, ... ); } } That's it! Thanks for the challenge Alohe ๐Ÿค™ CodePen.IO link below! ๐Ÿ‘‡

jhey ส•โ€ขแดฅโ€ขส”

152,923 views โ€ข 2 years ago

CSS Trick ๐Ÿ You can create that Apple-style blowout text effect with CSS scroll animations and fixed positioning โšก๏ธ .word { animation: blowout; animation-timeline: --section; } @โ€‹keyframes blowout { 0%, 95% { background: transparent; } to { transform: translateZ(99vh); background: #000; } } The trick here is to fix the position of some things in your layout and then animate them based on their non-fixed containers โญ๏ธ The .word is position: fixed within a that has a height of 200vh section { view-timeline: --section; } section:first-of-type { height: 200vh; } Every section has a view-timeline: --section that creates a scoped ViewTimeline for each section's children ๐Ÿค™ As that first section scrolls out of view, you increase its opacity and move it on the z-axis towards you. That gives it the impression of scaling up ๐Ÿ†™ .word { animation: blowout, fade-in; animation-timing-function: ease-in; animation-fill-mode: both; animation-timeline: --section; animation-range: exit-crossing 10% exit 0%; } You can use the exit-crossing range combined with the exit range to get a timing you like โœจ Definitely experiment with these ranges to see how they play. The timing function creates interesting effects too! At the same time as the text scales up, you need to fade in the video and the text that goes with it. Again, you can use the parent container's ViewTimeline --section p, video { animation: fade-in, fade-out; animation-timing-function: ease-in; animation-fill-mode: both; animation-timeline: --section; } p { animation-range: entry 10% entry 35%, exit 0% exit 25%; } video { animation-range: entry 0% entry 25%, exit 10% exit 35%; } The timings are slightly different here. Again, you can play with them to get something that feels right for you! @โ€‹keyframes fade-in { to { opacity: 1; }} @โ€‹keyframes fade-out { to { opacity: 0; }} Theoretically, you should be able to do something with animation-direction: reverse/alternate like yesterday's demo video { animation: fade 2 both linear alternate-reverse; } The trick with this effect is all about timing and creating containers that are bigger than the content and using them to drive the animations ๐ŸŽ๏ธ The scroll-driven signature is a bonus! โœ๏ธ Perhaps a follow-up on that one ๐Ÿค™ As always, any questions, requests, etc. Hit me up! With this demo, the GreenSock ScrollTrigger code is included where the CSS scroll-driven animations API is not supported ๐Ÿ™Œ That means you could use this demo today! CodePen.IO link below! ๐Ÿ‘‡

jhey ส•โ€ขแดฅโ€ขส”

270,144 views โ€ข 2 years ago