Loading video...

Video Failed to Load

Go Home

CSS Trick! ⭐️ You can create this sparkly backdrop with a single element using mask-composite whilst animating the mask-position 😷 .canvas { background: var(--gradient); mask: var(--dots), var(--noise); mask-composite: intersect /* source-in, xor */; animation: flicker; } @​keyframes flicker { to { mask-position: 50% 50% , 0 50%; } }...

279,699 views • 2 years ago •via X (Twitter)

10 Comments

jhey ▲🐻🎈's profile picture
jhey ▲🐻🎈2 years ago

Here's that @CodePen link! 🚀 Can use this to mask out words and icons as well 🔥

jhey ▲🐻🎈's profile picture
jhey ▲🐻🎈2 years ago

Here's John's post showing how he the same effect but using <canvas> 🤙

jhey ▲🐻🎈's profile picture
jhey ▲🐻🎈2 years ago

Annnnnddd here's that Perlin Noise generator site ⚡️ Tinker with the values until you find something that works for you. Had to mess with the alpha and seed until I found something I liked 😁

Adam Rackis's profile picture
Adam Rackis2 years ago

C’mon bro crank that course / book out you’re killing us

Simon Vrachliotis's profile picture
Simon Vrachliotis2 years ago

HOW does your brain think of this stuff 🤯

jhey ▲🐻🎈's profile picture
jhey ▲🐻🎈2 years ago

It's weird in there 🙃

Dan ⚡️'s profile picture
Dan ⚡️2 years ago

this is not even from the future 👀 although it seems from the future

Viki ✨'s profile picture
Viki ✨2 years ago

Awesome trick 😎

jhey ▲🐻🎈's profile picture
jhey ▲🐻🎈2 years ago

Thanks Viki! 🤙

Joshua's profile picture
Joshua2 years ago

Your work has really been inspiring me lately.

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,739 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,179,941 views • 2 years ago

CSS Tip! ✨ It's 2024 and you have a new way to make animated borders 🚀 .glow::after { offset-path: rect(0 100% 100% 0 round var(--radius)); animation: loop; } @​keyframes loop { to { offset-distance: 100%; }} Using the offset-* properties you can animate elements along the perimeter of others 😍 The rect() value gained support in Safari 17.2 🙌 To start, you create an element and put it inside your main element. For example, you put a span inside the button 🤙 Click me! Make the element fill its parent with absolute positioning and inset [data-glow] { position: absolute; inset: 0; } Now the good part, you use a pseudoelement on that element and define an offset-path [data-glow]::after { content: ""; offset-path: rect(0 auto auto 0 round var(--radius)); animation: loop 2.6s infinite linear; } With the rect value, you are saying the path fills the parent container: top: 0 right: auto || 100% bottom: auto || 100% left: 0 Then you can use round to make sure the path uses the same radius as whatever the parent has The @​keyframes animation merely animates the offset-distance of that pseudoelement to 100% @​keyframes loop { to { offset-distance: 100%; }} You can see this more clearly in the video 🫶 The offset-* properties also include an offset-anchor property. This allows you to dictate which point of the element follows the path. For example: anchor-offset: 100% 50%; This means that the "right, center" of the element will follow the perimeter of the parent element 🤙 Lastly, the visuals 🎨 For color, you can use a gradient such as a linear gradient to fill the pseudo-element. [data-glow]::after { background: radial-gradient( circle at right, hsl(320 90% 100%), transparent 50% ); } Then clip away everything so you only have the border and can still have translucent backgrounds, etc. Use a mask with mask-composite ✨ A little transparent border trick: [data-glow] { border: 2px solid transparent; mask: linear-gradient(transparent, transparent), linear-gradient(white, white); mask-clip: padding-box, border-box; mask-composite: intersect; } Bit of a long one. Hope you find it useful 🙏 CodePen.IO link below 👇

jhey ʕ•ᴥ•ʔ

283,498 views • 2 years ago

007/100 Buttons. This button was way more complex than I first thought. I love the page transition on the Truus site that Dennis Snellenberg and Jordan Gilroy worked on. So I wanted to use that drawing SVG Path idea somehow and fit it into a button. In best case with a mask effect. The idea was to have an SVG path in the background that fills the button. At the same time, this path should also be used as a mask to reveal the differently colored text. The SVG should also be replaceable and work with other SVGs. For the path animation, I can use the DrawSVGPlugin from GSAP. Sounds like a solid plan. I built the button so far, and it worked great in Chrome and Firefox. In Safari, nope. I used an SVG mask that I referenced through CSS. But Safari can’t handle that properly when the path inside the mask is animated, so the animation lags. There was no simple solution for that. At least I didn’t find something. So I had to rebuild the button in another way. What I found was that the SVG mask animation works in Safari when the mask is placed on the desired element inside the SVG. That’s where foreignObject comes in, it allows you to use normal HTML elements inside an SVG. Using that, I rebuilt the hover text inside the SVG. I then referenced the mask on the foreignObject with a bit of JavaScript. And it worked! The button’s structure looks more complicated than I wanted it to be, but that happens quite often when you need to make something work across different browsers 😃 Crafting 100 Buttons with Osmo ⏳ Total time: 96h

Eduard Bodak

67,154 views • 2 months ago

When I saw the mask "Tribes of the Calf" from Kanbas I knew I had to make it into reality. The jewelry and gold really made it stand out for me. Since Sam Spratt's The Masquerade was revealed, I have been spending time sculpting and dissecting the mask to recreate it in 3D as faithfully as possible. I delved into the creation of this mask for many reasons. I love a good challenge and this mask surely was one for me. Creating something in 3D from a 2D image is not easy, and especially when the source has generative nature, some stuff is hard to interpret, but I tried my best to make sure the visual integrity of the mask is as close to the original as possible. Splitting the whole mask into parts, filling the missing pieces so I can build the textures was quite a lot of work. I tried to present the mask in my own style with a slightly different colorway to adapt to the mask itself. Please enjoy this short animation, and turn on sound🔊 This piece is my statement that I am here to stay. That I have a voice that often feels being lost in the void. That I have been creating and posting digital art for over 20 years now and will continue until I'm gone. I have a story to tell and I want to be heard. The space we have here is small, and is shrinking day by day. It doesn't have to be like that. We need to support each other and push ourselves and people here, otherwise we are all doomed. As Kanbas has put in their observation of the mask: "Inspirational. Emotional. Natural." This is what our space can be, and this is me making a statement with this homage. I will share a 4k still below as well as a short video showing the 3D GLB interactive model together with a yt link to the 4k video since compression here is pretty bad.

shoneec

17,531 views • 1 year ago

God of War Laufey THE MASK theory: First, I want you to see this video carefully and then read this theory. In this video, Sekhmet, the Egyptian Goddess of war, plucks out the mask splinter from Faye's hand and says. "Another mask, this looks important to you. You think it will set you free." Now if you read my previous theory that says Athena created the Afterlife for Gods, that is Everywhen ( I will link it below) This is mask is planted by Athena herself in every mythology, and her plan is to make every god obsessed with the thought of "what happens after a death of god, where do they go" and the curiosity drives the Gods crazy, so they wear the mask and are pulled into the rift, yes the masks kills them and pulls them into the Everywhen. Odin was a victim of it, he cared more for mask than Ragnarok itself, which was supposed to be the end of him but the obsession with question " What happens to God after death" drove him so crazy he didn't care about anything else. I think Sekhmet and Begtse are victims of that mask as well, the line " You think it will set you free " feels very deep, almost like she tried finding the answers of afterlife, wanting to be free of the mortal plane and this mask came as a hope to her, so she tried and got pulled here. Now why would Athena or whoever the creator of this place would do that? I am not sure but I now can't stop thinking about it. Also makes sense why would faye and other creatures just end up there, are they all gods? or just victim of the mask. For faye it feels like the splinter of the mask brought her here. This theory might feel stupid when the games come out and none of this is true but still fun ig 🗿 Lemme know your thoughts!

Yash

162,538 views • 1 month ago

CSS Tip! 🎠 You can create a responsive infinite marquee animation with container queries and no duplicate items 🤙 li{ animation: slide; } @​keyframes slide { to { translate: 0% calc(var(--i) * -100%);}} The trick is animating the items, not the list 😎 More tricks 👇 To get this one working, you need to animate the items and not the list (Watch the video first?). Each item needs to know its row index (--i) in the list and the parent needs to know how many rows are in the list: ul { --count: 12; } li:nth-of-type(1), li:nth-of-type(2) { --i: 0; } li:nth-of-type(3), li:nth-of-type(4) { --i: 1; } Once you have that, translate each item based on its row index in the list li { translate: 0% calc((var(--count) - var(--i)) * 100%); } Now for the animation. The key here is that each row has an animation-delay calculated from its index (--i). That number is offset to make it negative so the animation start is offset ✨ ul { --duration: 10s; } li { --delay: calc((var(--duration) / var(--count)) * (var(--i) - 8)); animation: slide var(--duration) var(--delay) infinite linear; } Make sure to wrap that animation in: @​media (prefers-reduced-motion: no-preference) { ... } Lastly, the fun parts! 🤓 To create the "vignette" mask. Use a layered mask on the container 😷 .scene { --buff: 3rem; height: 100%; width: 100%; mask: linear-gradient(transparent, white var(--buff) calc(100% - var(--buff)), transparent), linear-gradient(90deg, transparent, white var(--buff) calc(100% - var(--buff)), transparent); mask-composite: intersect; } To create the 3D skewed effect, use a chained transform (Try toggling it in the demo ⚡️): .grid { transform: rotateX(20deg) rotateZ(-20deg) skewX(20deg); } As for the responsive part, use container queries! 🔥 article { container-type: inline-size; } When the article (card) is narrower than 400px update the grid and animation settings 🤙 Double the rows means double the duration! @​container (width < 400px) { .grid { --count: 12; grid-template-columns: 1fr; } li:nth-of-type(1) { --i: 0; } li:nth-of-type(2) { --i: 1; } li:nth-of-type(3) { --i: 2; } li:nth-of-type(4) { --i: 3; } li { --duration: 20s; } } CSS has the magic to be able to update those animations at runtime based on your custom property values 😎 An added bonus in this demo is that it doesn't require any JavaScript at all, for any of it 🤯 We can use CSS :has() for those toggles that update the styles, even the theme toggle! 🫶 Any questions, let me know! Make sure to check out the video. Will do a walkthrough one to follow-up 🤙 CodePen.IO link below! 👇

jhey ʕ•ᴥ•ʔ

542,159 views • 2 years ago

A mess of additions to the Masquerade and Mask Market we announced in Toledo are now live. I walk through them in the video but the purpose is to continue to close the distance between each mask from one another and close the distance between each mask and the Masquerade itself, creating many tunnels to slip between Mask, Masquerade, Observation, Response, and back, burrowing between the links in the network. Changes to the Mask Market: Masks are now sorted by Chroma in a long gradient Masks can now be sorted by Region where its Observation was placed Masks can now be sorted by their adornments such as which Masks have horns or tusks Masks can now be sorted by their materials such as wood, stone, ebony, or feather Reserved Masks for the Exhibition Winners have been given a new Rank A strip of other Mask thumbnails if viewable when you go to each Mask page Sped up the page performance to load much quicker Changes to the Masquerade: All Masks are now viewable within the Masquerade viewer Masks can be viewed by hovering over each, or enlarged and cycled through in a gallery viewer The default ordering of observations is now randomized, making each time you revisit the page surface someone new. Replies are now collapsed helping with legibility Added Rank badging from the Market to the Observation panel (Finalist, Seer, Council, etc) There are some additional changes and tweaks from our Toledo experience which will be making their way in soon as well but I hope you enjoy the changes. My deep thanks to Nifty Gateway Studio for continuing to support this as a living and breathing record of this gathering rather than a “drop” or marketplace and to Lanett Bennett Grant for surfacing and working with us to make it better through her amazing Mask deep dives. The work continues.

Sam Spratt

21,368 views • 10 months ago

CSS Trick! ⚡️ You can use scroll-driven animation with background-attachment to create a dynamic glowing card scroller without JS 🔥 section { animation:vibe; animation-timeline:--list; } @​keyframes vibe { to{--hue:320;}} .glow {background: hsl(var(--hue) 80% 50%);} Here's how! 🤙 You can use the background-attachment trick used in other glow card demos 😎 article { background-attachment: fixed; } The difference here is that you aren't going to update the fixed background position with your pointer this time. It can remain fixed. The magic part is that as you scroll, the background will leave the card that's leaving and enter the card that's entering ✨ For the extra background glow, you can use a fixed pseudo element on the list container itself 💪 Once that's in place, you're only task is to change the color of the background as you scroll 🤔 Create a custom property declaration for the --hue @​property --base { inherits: true; syntax: ' '; initial-value: 0; } Then create an animation that updates this value @​keyframes accent { to { --hue: 320; }} The last piece is hooking it up to scroll and there is a little trick in here 👀 First, you need an inline scroll-timeline on the list ul { scroll-timeline: --list inline; } Then you can use timeline-scope to hoist that scroll-timeline up so a parent can use it. You then animate the custom property on this element and let the value cascade down to the places that need it 🔥 section { timeline-scope: --list; animation: accent both linear; animation-timeline: --list; } For example, the glow uses the --hue this way [data-glow] { background-image: radial-gradient( 150px 150px at 50% 50%, hsl(var(--hue) 100% 70% / 0.25), transparent ); } Lastly, scroll-snap is optional of course but plays nice with the scroll-driven animation demos ✨ The key for that is ul { scroll-snap-type: x mandatory; } li { scroll-snap-align: center; } That's it! Pretty fun trick to play with! 🤓 Any questions, let me know! Should we add it to the video walkthrough list? CodePen.IO link below! 👇

jhey ʕ•ᴥ•ʔ

116,462 views • 2 years ago