Turns out Chrome dropped the requirement to for the -webkit- prefix with v120, which is why this worked without it. If you're worried about browser support, you're probably best including both the prefixed and unprefixedd versions.
Regarding the magic number issue, my assumption is that the difference between the animation ranges is a variable of the height of the h2 element. Like, if h2's background starts and ends animation when the top edge of its css box passes the limit our vh values set, then there is technically a gap between when the h2 is done with its animation and when p starts its own. Just a wild guess.
Agreed, maybe end the h2 with contain and start the paragraph with cover with the same value so that header finishes just as p starts? That should deal with the unknown size of the h2. This is all completely new to me, so I could be totally wrong.
Same thoughts here too! DId someone tried it to confirm? Although we still rely on an arbitrary number that would harder to "guess" if the text line broke into two or more due to viewport width.
Most likely the h2 has 100% width, so the background animation goes from one edge of the screen to the other edge (Not just the width of the letters). We cant see it because of the clipping, but that would explain the delay between the animations.
@@WakeMtzI don't think so, the animation is done on the spans inside the h2 and p, not on the h2 and p themselves, and they aren't set to 100% width. Decided that I had done enough navel gazing and forked the codepen then made the changes I discussed, and it's close, but not quite spot on. The text in the paragraph starts filling in when the "a" at the end of "Palma" is about half full. On the other hand, if the header overflows into multiple lines, it adapts better than the magic number version. With a three line header, the paragraph starts filling at just about the same time the last letter of the header starts filling in. My first hunch was because of margin collapsing, as in the Chrome inspector, the content boxes of the two spans slightly overlapped, but I can't find any vertical margins to cause that. If you're curious to see how it looks, search codepen.io for "css-only text reveal on scroll" with forks enabled, mine is the one by "EricGeek"
I think the way to avoid magic numbers is to use cover for the start and contain for the end. That way, the first animation ends when the bottom of the h2 reaches the specified position and the second animation starts when the top of the p reaches that same position.
I feel like you could just use contain for the headline and cover for the text. That should mean it starts the animation for the headline once its fully visible and start the animation for the text, once it enters the viewport, which I suppose means, if their containers are touching, happens at the same time and therefore you could use the same numbers?
Got it to work perfectly by putting display inline only on the paragraph. Put onAnim class on both h1 and p then it flows without magic numbers. ```css p { display: inline; } .onAnim { color: hsl(0 0% 100% /0.3); background-image: linear-gradient(90deg, red, blue); background-clip: text; background-size: 0% 100%; background-repeat: no-repeat; animation: scroll-reveal linear forwards; animation-timeline: view(80% 15%); } @keyframes scroll-reveal { to { background-size: 100% 100%; } } ``` Thanks, this will be very useful once browser coverage is optimal.
Yep, I think they were for this effect because the device they are promoting wouldnt be more akin to display word by word. I think the smooth version wouldnt even show nicely on said device. They are chinese, so likely they developed it with chinese localization and character set - one character at a time
h2 span should be contain, essentially meaning the bottom reaches the number, then p span should be cover, essentially meaning the top reaches the number. You never tested with those settings.
The simple fact that you're facing a real-world-css-problem and trying to deal with it in real-time is one of that things that better bond you to your audience. The "only" (realy? 😅) difference is that you find - and know - the solutions in a few minutes (maybe seconds) instead of days or weeks, like some of your audience (me included hahaha). Thank you for bring all your great content and skills as always!
Regarding the magic number issue, my assumption is that the lag between the two animations is because the h2 is taking the full width of the container, so it resumes to fill the rest of the element (which is not having text in it). solution: display the h2 as an inline-block element instead of block
I was wondering if you would do a version where the animation highlights the paragraph word-by-word like in a original example (I guess that is only possible with JS). Turns out your gradient version looks smoother and nicer, great video.
I enjoyed watching you work through this and listening to your thoughts 🙂 also the little "it worked!" because that's exactly how I feel when I figure things out 🤣
Your solution is certainly nice, and is still a good exercise regardless, but a bit of OCD kicked in and had me mentally shouting at the screen that the orignal your copying is 'stepped' that is, it changes the color one word at a time, not in a gradiant like you did. Wonder if that is at all possible in CSS only? I'm guessing it would need JS.
You rock! I have an idea, probably animation range start must be the same number - the height of the paragraph, so if you use js for that and will set custom property for that, it would work probably and the event will start ideally, isn't it? Without js idk how to do that without magic numbering:)
You can also try experimenting with view-timeline-name. I think you can use the same timeline for both the h2 span and the p span, for example, define a named timeline for the h2 element, and use that timeline to define the event for both. You will probably not need magic numbers, because now view() creates two different timelines and the numbers do not match.
Believe me, I've been literally begging for vids on the View-Timeline API but this was just about Scroll Driven Timelines. The real magic will be when he uses both!
If the elements are stacked with no margin probably what would work is the top one has animation-range-end: contain (plus offset) and the next has to be animation-range-start: cover (plus same offset as). I didn't test it so idk if it would work... if so there is no need for magic numbers
Maybe use contain for the h2 end and cover for the p start and set both to 30vh and it is in sync. Because once the whole h2 is past the 30vh mark, then the just enters and thats when you want to start the animation
I just watch your video and try it and when I use px with animation-range-start and animation-range-end and that's work perfectly. by the way thank you for all your video that's help me a lot to learn new thing and become better.
Awesome ! I love that kind of video : I'm learning new stuff about css. I can do something pretty. AND I can see the way you are thinking to create css.
Really cool exercise! The boox site seems to apply the effect one whole word at a time, though. Would it be possible to do the same and keep it CSS-only?
Love the video! If you're looking for stuff to do, there's a challenge on frontend mentor called countdown timer that was WAY trickier than it looks on the outside. It was a lot of fun and I'd love to see your approach
This timing weirdness is bevause the animation is going over background of the element as a hole so it is timed over the box width of that h2 and not just the text. I wonder if you made the box better fit the text if less magic would be required. Just a thought. Nice work!
For a non-hardcoding sol u could prolly put all the text in one p tag n for the heading put it in a span with large font size. Not gr8 for acessibility but 🤷🏼
Original site was highlighting the whole words. I was very interested how you would do it in css, but your exapme highlights any part, including partial letters. Can you fix that?
Welll it's not the same this one is revealing everything partially, it's like at some point only half the word is white, in their version a word is either completely grayed out or completely white. I do admit though that it's crazy hard to do it like that with only css just use javascript in that case.
I guess if you subtract the height of the first element from the start point it will match in timing. This will solve problems with changing font sizes.
Cool. But you really need to check what happens with different window sizes (height, width...) and different font sizes. I have a feeling it might fall apart.
please i nned a help, background-clip text need color to be transparent or not ? if i set color to gray for eaxmple, background-cl;ip not working for me, can i someone help me please
I thought you’d use box-decoration-break: clone. That would theoretically work, but depends if the animation treats each cloned background as its own animation.
I wonder if that would work 🤔. I'd been planning another video looking at an underline gradient for links, so I knew I could just have them as inline elements 😅
Great Explanation Sir......Can You Create A Specific Videon On CSS perspective.....And 3d Zoom Animation On Scrolling.....And Other Great Things We Can Do With Css❤
14:30 - Given that the range-start is offset, the second (paragraph) cover/contain offset needs to include header height, and that gets rid of magic numbers.
Could you please make a tutorial on how to deal with tables with many columns on mobile view? I'm having trouble with tables that overflow when the viewport gets smaller. I would really appreciate it. very cool video btw, i've been looking for a text reveal on scroll css only video for a long time. love your video.
Hello Kevin, Happy Newyear! Thanks a lot for this amazing animation and the insights. I tried to apply the same inside Elementor using the html widget, however the animation is not working. I was able to replicate it in an html page. However in elementor its seems something is conflicting.
This is one awesome real-world example, Kevin. One question for a CSS novice like myself, why does the inline change fix the way the animation works at about 6:00 ? I could have never come up with that solution so maybe I am missing some key information on why the span changes the animation direction from top-down to left-right. Thank you
For a block element the gradient is applied to the whole rectangle. For inline text it only covers the line-height, and will wrap with the line of text.
Well the real world did it word per word (or even a couple of words at the time). You might like it better speed wise, but especially when you stop scrolling and half a letter is done, it looks weird. I guess doing it letter by letter is not possible using CSS...
Is it possible with CSS-only to run the animation only once? like on the first time user scrolls do a funcky animation but don't do it again? I know that's possible with adding some JS.
why not make the parent ".scroll-reveal" itself "inline"? and make the children also inline. and use to seperate h2 and p i was able to do it like that without magic numbering
It looks like each word is wrapped in its own . As the user scrolls, javascript adds a class to the spans, one-by-one, which changes the color of their contents from gray to white.
Hey! Thanks for the amazing content. Would it be possible to create the same effect with a text that has some words with different colors? Sorry repeating the comment, I commented on the wrong account before and couldn't find it to delete it. Thanks again!
Mmmmh, I'm not conviced this time, for a simple reason: as soon as you change the viewport size, you lose the timing effect. Basically, your code works just with those specific viewport sizes and for that specific text. Nevertheless, it's a brilliant solution for a very tricky problem, and has many potential uses.
Hi Kevin, I have one question about sass and I can;t find the answer. Let's say we have a button with data-theme="primary" and i want to use this value in scss to pass it to my mixin .button { @include myFancyMixin(
Turns out Chrome dropped the requirement to for the -webkit- prefix with v120, which is why this worked without it. If you're worried about browser support, you're probably best including both the prefixed and unprefixedd versions.
Hi! Please tell me where i can read about this change? Sorry for the bad English, but you're being watched all over the planet, I think that's okay =)
Nice work! Anywhere we can find this code example? I don't think I can see it on Codepen
Love these "real world" examples, Kevin. It would be cool if we had videos like these from time to time. Happy New Year
Regarding the magic number issue, my assumption is that the difference between the animation ranges is a variable of the height of the h2 element. Like, if h2's background starts and ends animation when the top edge of its css box passes the limit our vh values set, then there is technically a gap between when the h2 is done with its animation and when p starts its own. Just a wild guess.
Agreed, maybe end the h2 with contain and start the paragraph with cover with the same value so that header finishes just as p starts? That should deal with the unknown size of the h2. This is all completely new to me, so I could be totally wrong.
Would be good to see if this would solve the issue with a calc, 30vh - h2 font height.
Same thoughts here too!
DId someone tried it to confirm?
Although we still rely on an arbitrary number that would harder to "guess" if the text line broke into two or more due to viewport width.
Most likely the h2 has 100% width, so the background animation goes from one edge of the screen to the other edge (Not just the width of the letters).
We cant see it because of the clipping, but that would explain the delay between the animations.
@@WakeMtzI don't think so, the animation is done on the spans inside the h2 and p, not on the h2 and p themselves, and they aren't set to 100% width.
Decided that I had done enough navel gazing and forked the codepen then made the changes I discussed, and it's close, but not quite spot on. The text in the paragraph starts filling in when the "a" at the end of "Palma" is about half full. On the other hand, if the header overflows into multiple lines, it adapts better than the magic number version. With a three line header, the paragraph starts filling at just about the same time the last letter of the header starts filling in.
My first hunch was because of margin collapsing, as in the Chrome inspector, the content boxes of the two spans slightly overlapped, but I can't find any vertical margins to cause that.
If you're curious to see how it looks, search codepen.io for "css-only text reveal on scroll" with forks enabled, mine is the one by "EricGeek"
I think the way to avoid magic numbers is to use cover for the start and contain for the end. That way, the first animation ends when the bottom of the h2 reaches the specified position and the second animation starts when the top of the p reaches that same position.
Damn, you make the impossible possible Kevin. I can't even think of doing such things using pure CSS... JUST WOW 💕🦄
I feel like you could just use contain for the headline and cover for the text. That should mean it starts the animation for the headline once its fully visible and start the animation for the text, once it enters the viewport, which I suppose means, if their containers are touching, happens at the same time and therefore you could use the same numbers?
i agree. "contain" basically is basing off the bottom of the element, and cover off the top (if you're scrolling down at least), so that would work.
Got it to work perfectly by putting display inline only on the paragraph. Put onAnim class on both h1 and p then it flows without magic numbers.
```css
p {
display: inline;
}
.onAnim {
color: hsl(0 0% 100% /0.3);
background-image: linear-gradient(90deg, red, blue);
background-clip: text;
background-size: 0% 100%;
background-repeat: no-repeat;
animation: scroll-reveal linear forwards;
animation-timeline: view(80% 15%);
}
@keyframes scroll-reveal {
to {
background-size: 100% 100%;
}
}
```
Thanks, this will be very useful once browser coverage is optimal.
Yea, I have tested and it and it worked.
Dude you genius. I am full time backend developer but I can’t stop watching your videos 😂🙏
Kevin you are a pure css lover .
I first thought of making a gray overlay that scrolls away.
But this way is more to my liking.
Thanks.
To be completely fair, the original has the reveal applied one word at a time, so it’s a very different effect…
My thoughts too
Yep, I think they were for this effect because the device they are promoting wouldnt be more akin to display word by word. I think the smooth version wouldnt even show nicely on said device. They are chinese, so likely they developed it with chinese localization and character set - one character at a time
You’re the best!
h2 span should be contain, essentially meaning the bottom reaches the number, then p span should be cover, essentially meaning the top reaches the number. You never tested with those settings.
The simple fact that you're facing a real-world-css-problem and trying to deal with it in real-time is one of that things that better bond you to your audience. The "only" (realy? 😅) difference is that you find - and know - the solutions in a few minutes (maybe seconds) instead of days or weeks, like some of your audience (me included hahaha). Thank you for bring all your great content and skills as always!
bro make such a rich animation hppy new year website 🎉🎉🎉🎉🎉
Regarding the magic number issue, my assumption is that the lag between the two animations is because the h2 is taking the full width of the container, so it resumes to fill the rest of the element (which is not having text in it).
solution: display the h2 as an inline-block element instead of block
I was wondering if you would do a version where the animation highlights the paragraph word-by-word like in a original example (I guess that is only possible with JS). Turns out your gradient version looks smoother and nicer, great video.
I enjoyed watching you work through this and listening to your thoughts 🙂 also the little "it worked!" because that's exactly how I feel when I figure things out 🤣
Quite an interesting format of video💪🏻👍🏻👍🏻👍🏻
Or maybe calc(20vh + line-height of h2)
Your solution is certainly nice, and is still a good exercise regardless, but a bit of OCD kicked in and had me mentally shouting at the screen that the orignal your copying is 'stepped' that is, it changes the color one word at a time, not in a gradiant like you did. Wonder if that is at all possible in CSS only? I'm guessing it would need JS.
I actually like my version better, lol. But yeah, I think you need JS to do it word by word.
You rock! I have an idea, probably animation range start must be the same number - the height of the paragraph, so if you use js for that and will set custom property for that, it would work probably and the event will start ideally, isn't it? Without js idk how to do that without magic numbering:)
Thanks Kevin. I would love to see more of such videos. ❤
Happy new year 🎉
You always seem like you're just having a blast doing these!
I was trying to do this a week ago with just HavaScript and tailwind. Got close, but didnt quite get it lol. Thanks man.
CSS magician ❤
Thanks for making videos like this one it really helps me learn new things.
Thank you for sharing 😊
You can also try experimenting with view-timeline-name. I think you can use the same timeline for both the h2 span and the p span, for example, define a named timeline for the h2 element, and use that timeline to define the event for both. You will probably not need magic numbers, because now view() creates two different timelines and the numbers do not match.
Believe me, I've been literally begging for vids on the View-Timeline API but this was just about Scroll Driven Timelines. The real magic will be when he uses both!
If the elements are stacked with no margin probably what would work is the top one has animation-range-end: contain (plus offset) and the next has to be animation-range-start: cover (plus same offset as). I didn't test it so idk if it would work... if so there is no need for magic numbers
Nice work!
But, I think you missed something. The other site animates whole word at a time.
Maybe use contain for the h2 end and cover for the p start and set both to 30vh and it is in sync. Because once the whole h2 is past the 30vh mark, then the just enters and thats when you want to start the animation
best video before i go to sleep, i ll dream this.
Ok, now, reveal word after word, like the original;)
I just watch your video and try it and when I use px with animation-range-start and animation-range-end and that's work perfectly. by the way thank you for all your video that's help me a lot to learn new thing and become better.
Awesome ! I love that kind of video : I'm learning new stuff about css. I can do something pretty. AND I can see the way you are thinking to create css.
Always love your video and everytime there is something new for me to learn
Very cool! I’ve never been able to make background-clip: text work without prefixing it. It’s like magic! Which browser are you using here ?
Chrome, which surprised me when it worked, lol. Looks like they dropped requiring the prefix with v120
@@KevinPowell 🌟🌟🌟
wow, so many new interesting things for me to learn this new year!
Beautiful!! Only CSS!!
i wonder if there is a way to make this work with for example sup elements inside, which have a position:relative, or transform: translate on them.
Maybe calc(20vh + 1em) or something like that 🤔 ?
Instead of using magic numbers I think you could have used `calc(20vw + var(--_h2-font-size))` ?
Love this, I think Bramus Van Damme is the one who can explain the range stuff the best ;)
Thksss a lot!!!! ive been looking for this 10hr ago
Kevin, I love your videos. I am learning a lot of good information thanks to you. God bless you :)
I'm surprised you didn't add a bunch of outlines to the elements with changes in the outline colors to debug when things were triggering.
Really cool exercise! The boox site seems to apply the effect one whole word at a time, though. Would it be possible to do the same and keep it CSS-only?
No, I think for that you'd need JS. Or a lot of spans and magic numbers 😅
Even if you use JS, you'll 😢end up just building those spans at runtime, I think
Love the video! If you're looking for stuff to do, there's a challenge on frontend mentor called countdown timer that was WAY trickier than it looks on the outside. It was a lot of fun and I'd love to see your approach
This timing weirdness is bevause the animation is going over background of the element as a hole so it is timed over the box width of that h2 and not just the text.
I wonder if you made the box better fit the text if less magic would be required. Just a thought. Nice work!
For a non-hardcoding sol u could prolly put all the text in one p tag n for the heading put it in a span with large font size. Not gr8 for acessibility but 🤷🏼
I think i like it better with the blue to red gradient
Make the entire thing a span for the animation-range-start and animation-range-end !
Great job and a great effort, I just noticed that the original fills word by word idk
Original site was highlighting the whole words. I was very interested how you would do it in css, but your exapme highlights any part, including partial letters. Can you fix that?
Hey can we add more delay for animation if i adding animation-delay method it was not showing any effect is there any way to fix this ?
Welll it's not the same this one is revealing everything partially, it's like at some point only half the word is white, in their version a word is either completely grayed out or completely white. I do admit though that it's crazy hard to do it like that with only css just use javascript in that case.
word by word either requires JS or wrapping every word in a span and magic numbering everything, which I wasn't about to do 😅
I guess if you subtract the height of the first element from the start point it will match in timing. This will solve problems with changing font sizes.
Sorry. Adding the height to the start point.
I wonder if box-decoration-break would make this more controllable... Gonna need to try that one out myself. :D
Cool. But you really need to check what happens with different window sizes (height, width...) and different font sizes. I have a feeling it might fall apart.
please i nned a help, background-clip text need color to be transparent or not ? if i set color to gray for eaxmple, background-cl;ip not working for me, can i someone help me please
U’re great, keyframes usely helps with several animations..
Thanks!
Thank you so much!
I thought you’d use box-decoration-break: clone. That would theoretically work, but depends if the animation treats each cloned background as its own animation.
I wonder if that would work 🤔. I'd been planning another video looking at an underline gradient for links, so I knew I could just have them as inline elements 😅
Great Explanation Sir......Can You Create A Specific Videon On CSS perspective.....And 3d Zoom Animation On Scrolling.....And Other Great Things We Can Do With Css❤
wow that's amazing
Wasn't the original "revealing" by entire words? Your solution reveals half of the words.
Yeah but no way to do that with CSS only... mine doesn't do half words, it just gradually reveals as you scroll :)
14:30 - Given that the range-start is offset, the second (paragraph) cover/contain offset needs to include header height, and that gets rid of magic numbers.
Could you please make a tutorial on how to deal with tables with many columns on mobile view? I'm having trouble with tables that overflow when the viewport gets smaller. I would really appreciate it.
very cool video btw, i've been looking for a text reveal on scroll css only video for a long time. love your video.
Love this series! Can Kevin Code It!
Hello Kevin, Happy Newyear! Thanks a lot for this amazing animation and the insights. I tried to apply the same inside Elementor using the html widget, however the animation is not working. I was able to replicate it in an html page. However in elementor its seems something is conflicting.
Hello there, Kevin!
What would that "grid-column: breakout-left" be?
Couldn't find anything about it in any documentation I looked.
This is one awesome real-world example, Kevin.
One question for a CSS novice like myself, why does the inline change fix the way the animation works at about 6:00 ?
I could have never come up with that solution so maybe I am missing some key information on why the span changes the animation direction from top-down to left-right.
Thank you
For a block element the gradient is applied to the whole rectangle. For inline text it only covers the line-height, and will wrap with the line of text.
I should have gone into more detail there, but Shaun explained it nicely :)
@@shaunpatrick8345 Thank you very much for the explanation
Many thanks for the great tutorial! How do I get this to work in Firefox?
Hi Kevin.
Can u explain how to text-overflow ellipsis without "white-space: nowrap"?
Sir please make header scroll animation using css
h1 tag has a display block or the length of the background is greater than the text...... if you guys wana try it just remove the clip and try again
gsap premium has something similar, but this one's for free yay!
Maybe you can use something like `1lh`?
i wonder how does it work when you maximize the screen window
Something new to learn...
7:00
first I try by my own it then Ill watch the video
Awesome!
The original one actually did it word by word, would be really interesting how you could do that instead of an overlay that is just overlayed.
Genius!
Is it possible to have more smooth effect, using gsap that reveal is really smooth
I think mine is about as smooth as it can get 🤷
@@KevinPowell sorry, what I meant was fade effect is letter by letter
Can I do this with one word at a time instead of one character at a time?
Well the real world did it word per word (or even a couple of words at the time). You might like it better speed wise, but especially when you stop scrolling and half a letter is done, it looks weird.
I guess doing it letter by letter is not possible using CSS...
Hi Kevin, do you have a link to this test, thanks.
Is it possible with CSS-only to run the animation only once? like on the first time user scrolls do a funcky animation but don't do it again? I know that's possible with adding some JS.
why not make the parent ".scroll-reveal" itself "inline"?
and make the children also inline.
and use to seperate h2 and p
i was able to do it like that without magic numbering
Hi there! Trying to figure out how to manually insert this code into a Squarespace website. Is there something I can just copy and insert?
Is there any way to do it "word by word" like the original website with CSS only?
Hi kevin, love your tutorials ! Can you do it with the color and text content changing when hovering ?
To change the text itself, you either need different layers, and remove the opacity of one when hovering, or JS to actually change the content itself.
On the original example, it did a word at a time. I'm wondering how they accomplished that. I prefer your outcome though.
It looks like each word is wrapped in its own . As the user scrolls, javascript adds a class to the spans, one-by-one, which changes the color of their contents from gray to white.
@@TeianDown ah it's not pure css then
Amazing
Hey! Thanks for the amazing content. Would it be possible to create the same effect with a text that has some words with different colors? Sorry repeating the comment, I commented on the wrong account before and couldn't find it to delete it. Thanks again!
Mmmmh, I'm not conviced this time, for a simple reason: as soon as you change the viewport size, you lose the timing effect. Basically, your code works just with those specific viewport sizes and for that specific text. Nevertheless, it's a brilliant solution for a very tricky problem, and has many potential uses.
can i control background video with css scroll?
Hi Kevin, I have one question about sass and I can;t find the answer.
Let's say we have a button with data-theme="primary" and i want to use this value in scss to pass it to my mixin
.button {
@include myFancyMixin(