How to animate sections in pure CSS when scrolling the page? - html

I am looking for a way to animate (with #keyframes, transform...) some elements when the user scrolls the page. For example:
When offset is 0: div has height: 100px.
When offset is between 0 and 100: div is height: 50px and color: blue.
And so on...
Is is possible using pure CSS?
If it is not, what are the most efficient ways to do it with HTML or Javascript?

The most efficient way to animate an element's style properties depending on scroll position will probably be to add a class with a scroll function:
Working Example
myID = document.getElementById("myID");
var myScrollFunc = function() {
var y = window.scrollY;
if (y > 500) {
// myID.style.backgroundColor = "blue"; // you can add individual styles
myID.className = "blue" // or add classes
} else {
// myID.style.backgroundColor = "red";
myID.className = "red"
}
};
window.addEventListener("scroll", myScrollFunc);
body {
height: 1100px;
}
#myID {
position: fixed;
height: 100px;
line-height: 20px;
transition: all 1s;
}
.blue {
background: blue;
animation: myAnimation 1s both;
}
.red {
background: red;
}
#keyframes myAnimation {
0% {
border-radius: 0px;
line-height: 10px;
}
100% {
border-radius: 100%;
line-height: 100px;
}
}
<div id="myID" class="red">Hello world</div>
Docs:
.scrollY
.className
.addEventListener

Methinnks it's not possible to 'spy' scroll with pure css. If you want, you can do this with jQuery:
$(document).scroll(function() {
var pos = parseInt($(document).scrollTop())
if(pos == 0) {
$('.yourDivClass').css({
height : '100px' ,
color : '#fff'
})
}
if (pos > 0 && pos <= 100) {
$('.yourDivClass').css({
height : '50px' ,
color : 'blue'
})
}
console.log(pos)
})
and of course if you wanna get a smooth transition, you supposed to declare transitions in your css file
.yourDivClass {
transition: height 0.5s ease
}

Scrolling is an event. Once you scroll the page, the event gets triggered and something happens. You cannot control events using Pure CSS. Period.
Some people would argue that even :hover is an event. Yes, and it is for some strange reason, implemented in CSS, but not others.

With pure CSS: no.
But you can have a class with keyframed animation associated with it, and then say when the element is scrolled into view, to add the class to the element. This will make it start doing the animation.

You can use Waypoints.js to set what happens when you reach a specific element of a page.

Related

Change scrollbar style if it is at the top

I know it is possible to change a scrollbar using just CSS, but I wanted to remove the border radius of the scrollbar if it is at the top of its track. Is this possible?
1.setting up .myCss class with pseudo webkit-scroll in the CSS.
2.adding event Listener on the window object with event of scroll
which gives me the scrollY position every time i scroll and saving it in scroll.
3.if scroll is equal to 0 add myCss Class. and if its not I am removing it.
additions: setting condition to change when it hits the bottom.
firefox:window.scrollMaxY
chrome:document.documentElement.scrollHeight - document.documentElement.clientHeight
console.log(window.scrollMaxY) //FireFox (Max Scroll Height)
console.log(window.scrollY) //(current Scroll Height)
console.log(document.documentElement.scrollHeight - document.documentElement.clientHeight) //Chrome (Max Scroll Height)
window.addEventListener("scroll", (event) => {
let scroll = this.scrollY;
if (scroll == 0) {
document.body.classList.add("myCss")
}
else if(scroll==(document.documentElement.scrollHeight - document.documentElement.clientHeight)) {
document.body.classList.add("myCss")
}
else{
document.body.classList.remove("myCss")
}
});
p {
background-color: aqua;
width: 100vw;
height: 300vh
}
.myCss::-webkit-scrollbar {
background-color: gray;
width: 10px;
}
.myCss::-webkit-scrollbar-thumb {
background-color: white;
border-radius: 5px;
}
<p></p>

How to make input field on full screan on position absolute

In header i have search field, which should have with same lice container.
Some how i need to make biger input, example:
[![enter image description here][1]][1]
My code jsFiddle
$(".search-input").on("mousedown", function () {
$(this).addClass('active');
$('.search_container').addClass('test')
});
$(".cancel-icon").on("mousedown", function () {
$('#search-content').hide();
$('.search-input').removeClass('active');
$('.search-input').val('');
$('.search_container').removeClass('test')
});
For some reason input don't wanna go biger -_-
create one more class of your name. I just call it as .some and it to div.search-field when input is active and remove it when cancel-icon is clicked.
.some{
flex-shrink: 0;
width: 100%;
transition: width 1s;
}
.search-field{
...
width: 50%;
...
}
$(".search-input").on("mousedown", function () {
...
$('.search-field').addClass('some');
});
$(".cancel-icon").on("mousedown", function () {
...
$('.search-field').removeClass('some');
});
display: flex making the .search-field shrink. In order to avoid that I added flex-shrink: 0
Updated
Added transition: width 1s to animate a width of .search-field and added an extra style width: 50% to an existing .search-field which doesn't change the existing size but it will make impact in transition.

Translate an element along one axis while keeping the other as is

I have a HTML element which has transform: translateX(some_percent) applied.
Is there a way to animate this element along the y-axis without changing the translation along the x-axis?
//EDIT
To clarify, some_percent is unknown and there is no way of accessing it.
I am interested if this is possible in general, without changing the html. It seems to me as if a translation is always a vector of (x,y) with translateY just being a shorthand for translate(0,y).
You could use a wrapping element and animate that:
HTML
<div id="outter">
<div id="img">
</div>
</div>
CSS
#img {
width: 250px;
height: 150px;
background-image: url('http://placehold.it/250x150');
transform: translateX(22%);
}
#outter {
transform: translateY(40%);
}
JS
var transY = 10;
var times = 0;
var x = function() {
if (times > 5) {
times = 0;
}
document.getElementById("outter").style.transform = 'translateY(' + times * transY + '%)';
times++;
setTimeout(x, 1000);
};
x();
https://jsfiddle.net/nayk1uLz/2/
the first parameter is the X axis and the second the Y ;).
transform: translate(50%, 50%);
Here is a jsfiddle : https://jsfiddle.net/fugfswmt/
Here's my solution proposal using a CSS Custom Property (a.k.a CSS Variable):
div {
width: 5rem;
height: 5rem;
text-align: center;
line-height: 5rem;
transition: transform 300ms;
}
#red {
background-color: red;
--some_percent: 24%; /* Default value */
transform: translateX(var(--some_percent)); /* Unknown value */
}
#red.translate-y {
transform: translateX(var(--some_percent)) translateY(50%); /* Any value */
}
<!-- Adding a click event just for demo purposes -->
<div id="red" style="--some_percent: 42%" onclick="this.classList.toggle('translate-y')">Click Me</div>
I'm guessing that if your some_percent value is unknown, you're setting it inline (after some server-side calculation, maybe?), so a pure CSS solution could be to set this unknown value as a CSS variable inline and use it as a constant on translateX and adjust translateY to whatever value you need.

Style the body during ng-view ng-animate

I'm using ng-view with ng-animate like so:
HTML
<body>
<div ng-view></div>
</body>
CSS
.view.ng-enter,
.view.ng-leave { transition: all 600ms ease-out; }
.view.ng-enter {
position: absolute;
top:0; left:240px;
width: 100%;
opacity: 0; }
.view.ng-enter.ng-enter-active {
opacity: 1;
left: 0; }
.view.ng-leave {
position: relative;
left: 0;
opacity: 1; }
.view.ng-leave.ng-leave-active {
opacity: 0;
left: -240px; }
Now throughout my app there are links that will change the view. The animation of the view changing works perfectly.
I now want to add animation to the body whenever the view changes. So basically, whenever .view.ng-view is active, a style needs to be applied to the body, which should be removed when the view animation is no longer active. How on earth do I do that?
I have trying to find this for a while myself, it works fine if you are adding and removing classes, but with ng-view its unique in that it's transition of 2 routes, and I haven't seen anything related to an emitter or anything. You have a few options though.
Here's a plunker;
1) The easy answer would be to add and remove an animation with a $timeout, with the same duration as the css for .view.
$rootScope.$on('$routeChangeSuccess', function(e, curr, prev) {
var body = $document.find('body');
$animate.addClass(body, 'overlay');
$timeout(function() {
$animate.removeClass(body, 'overlay');
}, 1000);
2) Another way is inside of the enter function you can put something in front of the done callback like, jQuery or TweenMax in this case.
app.animation('.view', function() {
return {
enter: function(element, done) {
TweenMax.from(element, 1, {
color: 'red',
onComplete: function() {
$log.debug('done');
done();
}
});
},
...
I would proberly look into something like jQuery to add a class to the body when the ng-view is active.
You could also have look into the ngAnimate which is explaining to perfection:
link to a very precise description of ngAnimate

Jquery slideToogle to right

I have this very simple code:
$(document).ready(function() {
$('.content>div').hide();
$('.content>h3').click(function() {
$(this).next().slideToggle('fast');
$(this).toggleClass('active');
});
});
it causes of course that my div slides out from top to bottom. Could you help me add to this code or command the line that in result it will be slide out from right to left??
.slideToggle() animates the height of the matched elements so you will likely have to rely on a different function/method - but this is not that difficult. You can do this either in JavaScript or use CSS3 animation properties. Depends on the use case but I'd probably use the CSS3 option because it is hardware accelerated on most devices so it is smoother.
Here's a simple sketch how that could be done
In the JavaScript file:
$('.content>h3').click(function() {
// just switch the class 'open' the rest is defined in CSS
$(this).next().toggleClass('open');
$(this).toggleClass('active');
});
And in the CSS file:
.content div {
width: 0;
overflow: hidden;
transition: width 1s ease-out;
}
.content div.open {
width: 100%;
}
Example:
http://jsbin.com/qebigohu/2/ (preview)
http://jsbin.com/qebigohu/2/edit (code)