Video summary
The video introduces "Props for That," a library developed by Adam that bridges the gap between JavaScript logic and CSS styling, allowing developers to pass dynamic data directly into stylesheets with minimal code. The core philosophy behind this tool is to shift as much computation as possible from JavaScript observers to CSS variables, thereby reducing overhead and improving performance. By simply adding an HTML attribute like `data-props-for`, users can expose a wide range of real-time information such as viewport dimensions, scroll velocity, input colors, and precise cursor positions directly to their stylesheets without writing complex event listeners or managing state in JavaScript files.
A significant portion of the demonstration focuses on performance optimization, specifically how the library handles visibility tracking efficiently. The speaker explains that unlike traditional methods where an element might continue consuming processing power even when scrolled off-screen, this library automatically stops updating props for elements that are no longer visible in the viewport. This ensures that resources are only spent on active content. Furthermore, the tool provides two distinct types of values: "live" variables that update constantly as a user scrolls or moves their mouse, and "const" variables that act like flags, changing state only once when an element enters or leaves the screen to trigger one-time animations without unnecessary re-calculations during scrolling.
The practical application shown involves creating complex scroll-driven animations using purely CSS calculations based on these passed values. The presenter demonstrates how to use `calc()` functions within custom properties to create effects like glowing gradients that follow a cursor, opacity transitions that fade elements in as they appear, and 3D perspective twists that rotate cards into place only when visible. By manipulating the live visibility state with simple math—such as calculating an angle based on whether an element is currently on-screen—the speaker achieves sophisticated entrance animations where items twist from different angles before settling flat. This approach eliminates the need for verbose JavaScript to manage scroll positions or hover states, resulting in cleaner code that leverages CSS's native capabilities while maintaining high performance and browser compatibility.
Read the full video transcript
Hello, my friend and friend. If you want
to know how we can do something like
this with these like animations that
come in as we're sliding down here and
and do this type of effect all with one
line of JavaScript, I guess. You're in
the right place cuz this is where we're
going to see how this works and it's all
being made possible thanks to Adam's
props for that. So, the link for this is
in the description, but you can see this
is what JS knows, now CSS knows. And I
talked last week about how it's a good
idea to pass as much information to CSS
as possible. There's some things that is
annoying to do that for and Adam has
solved the problem here. We have our
FPS, our viewport size, our scroll
velocity, the color of inputs live being
updated. You can see the cursor
position, all sorts of different things
that are being passed through and it's
all incredibly easy to do and quite
performant. So, I'm going to just going
to jump to the docs really fast to say
if we go to get started, all we need to
do you have your NPM install props for
that.
And there's a few different things
depending on how you want to set things
up. So, if you do want to use this,
depends a little bit on your project,
but it's incredibly easy to do. Let's
dive in and see how easy this actually
is to use. All right. So, I've set up a
nice page here, I think, and I want to
wire this up to to make it more
interactive and more fun. So, all I'm
doing in my JavaScript is importing the
props for that /auto. And then we can
dive in and actually start using these.
And to be able to do that, there's a few
different things we have to do. Or
actually, it's not a few. There's one
thing really that we need to do,
which is I'm going to come over into my
HTML. I have this card here with a twist
and we're going to look at that in a
minute, but I just have to come here for
a data props for. And I have to list out
the different things that I want to look
for. In this case, what I want to be
looking for is my pointer local. But
yeah, what that's going to be doing
then, let's actually go look in my dev
tools.
We can go on this card and
Oh, I put prop for. Sorry, that should
have been props for.
On that and I knew it wasn't working. So
if I go take a look now, there we go. I
can see the local the live local pointer
X ratio and the Y ratio and there's also
a pointer inside that's on there. And
what that's doing is no matter where I
am, it's giving me live updates and the
live inside is whether or not I'm on top
of it. So it's sort of like a hover
detection that we can be using. Now one
thing you might be worried about right
away is like, "Oh my goodness, this
could be terrible for performance." If
it's always tracking all of that, but as
soon as that element is off the page,
you can see like I've scrolled away,
it's not tracking it anymore. So it's
only tracking these whatever props
you're looking for if the element is
visible on the page, which is a good
thing cuz if not you're just wasting
processing power. So yeah, there's a lot
of performance things that Adam is baked
into here, which is super awesome.
So I'm getting my local my pointer local
and now I want to use it. So I have set
up some gradients here on here that you
might have noticed. I'm doing this. This
is like a texture with an SVG. I have
this gradient, which is the background,
the glowing one. Then I have a solid
color coming in here for the background
color cuz if I didn't have that just
really fast, it would be really blue. We
get something like that that looks
really ugly. And then I have this radio
gradient, which is set to my border box,
which is giving me sort of the shine at
the top. I've done a more in-depth video
on how this works. So I'll link to that
in the description if you're interested.
And the this code is also available. But
you'll notice here I have set up this X
and Y values that aren't anything right
now. It's just using these fallbacks
instead.
So what I could do is go and use the
props for to get an X and a Y value. Now
the prop that we're getting from Adam's
prop for that is this, the live local
pointer X ratio and we have the Y ratio
as well that we're coming in. But any
prop, I might have mentioned it, they're
always unitless and this is on purpose
so we can use them however you want to
be using them. In this case, I wanted as
a percentage based on where I'm hovered
on top. You can see I've actually broke
it now cuz it's passing those values in
as the X and Y.
And so what I'm going to do is a calc on
them. And we want to do this on both so
we can say this is a calc. Open that
calc up. We're going to come over here,
close it, and say this is times 100% to
add the unit uh onto there. And now we
can see it actually follows my mouse
around. And this is so incredibly easy.
I don't have to wire up any JavaScript
or anything. The props are just getting
passed through and and it's working. Uh
you can see I did a few fancy things
with clamps here just to make sure that
when I move far enough off it doesn't
keep on following me away. Uh but yeah,
that works fantastic and all my other
ones aren't wired up yet. So I'm going
to quickly go through and just add these
on there, but we're going to be adding
one more other thing at the same time,
uh which is visibility. And we're going
to see two different options here, but
we're going to start with the
visibility. And I just added it to all
of my different cards so we can see this
is working on all of them, uh which is
fantastic, but there is another custom
property that's now being used on these.
So if we go and take a look or not a
Yeah, custom property I should be
saying.
Uh we have this live visible of one. And
we also have a const has entered of one.
So with props for that, there's two
different types of props we get. There's
the live ones which are constantly being
updated, and there's the const which
aren't, right? So the const has entered,
uh we might have to actually refresh the
preview here. So let's refresh that.
And we can grab this first card, and we
can see that the const has entered is
actually currently one.
Uh but if we go and look in the next
section and my sticky wrap, the const
has entered is zero uh right there. And
if I start scrolling down, now that has
switched over to one. It has entered, so
it's one. The live visible is also one.
But if I keep scrolling, the live
visible is switched back over to zero,
whereas the const has entered has state
as number one.
So, the visib the live visible is always
updating live where the const will only
update the one time. It's more of a
constant as you'd expect. Now, it does
switch at one point cuz we're tracking
if it's entered or not, but it just
means we can do either a scroll driven
animation, which we can do with CSS now.
Browser support's getting better, but
it's not perfect. So, this could be a
nice way to do this for the time being,
but there's also scroll triggered
animations which we can't quite do yet
in CSS. They're on their way,
but we can use this for that type of
thing. So, how can we use it? Well, we
can do a few different fun things. Let's
go to these twist ins now that I have. I
already have a class set up here for a
twist in.
For these, let's just to give these a
little bit of of fun animation as we're
going down the page. So, the first thing
we could do here is this new opacity of
var
live visible, which is the proper
getting. So, this one will be visible.
Actually, let's do a transition
of opacity as well. I'm going to make it
really long just for demo purposes, but
I wouldn't actually do 5 seconds. But
then if I scroll down, you can see that
one slowly starts fading in as we get
there. Again, don't do 5 seconds,
but we're triggering that to happen.
Now, once they've left again because I'm
using live visible, that means it's also
switching back to zero. So, if I start
scrolling back up, they're going to
start fading back in this way.
>> [clears throat]
>> That's fine. I I don't mind that too
much, but this is where the const might
actually be a better option cuz I sort
of like it when things only fire once.
For the time being though, I think I'll
leave it as this just cuz it makes it
easier for when I'm demoing things. But
if I was doing this for production, I'd
probably use the const instead of the
live value here. Now, really fast, one
way that we could actually use this now
is to come in with a transform on this
to give us some perspective on these.
All right, so it's sort of at this weird
angle. They're all going to be like
that. I think let's just
drop this opacity transition for the
time being so we actually see things.
So this is already kind of fun, but it'd
be nice if like they're sort of angled
and then they turn in.
The other thing I'm going to do is I'm
actually going to switch these for a
variable we'll do that after
just cuz I don't want them all facing
the same way. I want the other ones
flipped the other way, but we can fix
that after.
But this is where we can get kind of
interesting cuz our is our live visible
or the const is either a one or a zero.
I actually want this to become zero once
it's visible. So how can we do that? So
I'm going to come here and say is
visible and we're going to say this is a
calc of one minus my var of live
visible.
Visible.
Cool.
So this if it is visible, the number
will actually be zero. It's kind of
backwards in a way.
I suppose.
But what we're saying is
1 minus 0 would still be 1 and a 1 minus
1 would become 0, right? So maybe if you
have a better name for this, please let
me know in the comments. But what I'm
going to do is put this in a calc calc
of the 25 degrees
times my var
is visible.
And what this is going to do is there
you go. You can see it's actually we
don't have it applied anymore. And we're
going to say the same thing here. I
guess I should have done both of these
calcs at the same time. 25 degrees times
var is visible. Maybe I should do active
or something like that instead of
visible.
On screen. I'm not sure. Anyway,
so the idea is it's -25 * 1 if it's off
the screen. No, sorry. Yeah, times 1 cuz
it's 1 minus 0.
So anyway, we get if it is visible, it's
going to undo its thing and then on our
transition, let's just take opacity off
here. We can say this is 5 seconds. So
now as I let's see transition. Oh, that
one is visible, but the next one that
comes in should be at an angle and it
twists into place and then the next one
twists into place.
And obviously the 5 seconds is way too
long for these types of things, but
we're triggering the animation based on
when it's coming in. Again, I don't
really want them reverse doing but it's
better for demos. So we can see it
always working.
But I'd probably make that the const.
Cool. So that's working.
The last thing I'm going to do is just
the value here. I'm going to do this as
my var
twist Y
negative 25. So we have a default value
on there.
And let's copy this.
Paste. That becomes an X.
And that was a negative eight.
And I guess this would be sort of our
starting position, but it just means on
the ones that I've done the negative
order on, I can also come on these and
say that the twist Y is 25 degrees. My
twist X is eight degrees. So they're
opposite from one another. Maybe that
stays at negative.
Let's see. When I get down to there,
that one's coming in that way.
And when I get to there, that one's
coming in that way. I think that's
exactly what I wanted.
So they're opposite from what they were
along the way there.
And of course then this could be
something like I don't know
0.75
instead. So it's a little bit more
snappy.
And we get those
coming in as we're scrolling down and we
still have all of these different
effects that are working.
I think this is fantastic. You can see
how easy that was not having to
set up our all of the observers, all
these different things. Don't have to
worry about the JavaScript. I just want
to say a very big thank you to Adam for
setting all of this up, enabling so
much. And of course, there's so much
more. Go check it out. The link for it
is in the description. I also want to
say a big thank you to my enabler of
awesome, Johnny, as well as all my other
patrons and channel members for their
continued support. And of course, until
next time, don't forget to make your
corner of the internet just a little bit
more awesome. And this is going to help
you do it. So, go forth and make some
cool stuff.