I have a div that grows in height as an animation. Instead of growing outside of the viewable area (and user having to scroll down), I'd like the window to automatically scroll with the div height. Locking the scroll position at the bottom of the page would work.
!!This is in React!!
I've tried millions of google/SO answers, none work/ arent specific enough.
code https://github.com/coryb08/corydbaker npm install && npm start
You provided very little information, but since we know it's in React, you could use JavaScript to make sure your div is scrolled all the way to the bottom at all all times.
class FullMenu extends Component {
constructor() {
super()
this.state = {
class: "",
div: ""
}
this.scrollToBottom = this.scrollToBottom.bind(this);
}
componentDidMount() {
setInterval(this.scrollToBottom, 20);
}
scrollToBottom() {
var scrollingElement = (document.scrollingElement || document.body); /* you could provide your scrolling element with react ref */
scrollingElement.scrollTop = scrollingElement.scrollHeight;
}
render() {
return (
<div id="FullMenu">
{this.state.div}
<div id="triangleDiv">
<img
className={this.state.class}
onClick={() => {
this.setState({ class: "bounce" })
let that = this
setTimeout(function() {
that.setState({
class: "",
div: <div className="menuDiv" />
})
}, 1000)
}}
src={triangle}
id="triangle"
/>
</div>
</div>
)
}
}
Note that above solution keeps the window scrolled at all times. If you wanted to scroll it only during animation, then you should use react's CSSTransitionGroup and use clearInterval to stop this behavior in transitionEnd lifecycle hook.
You can use CSS alone
all you have to do is set the div styling
display: flex;
flex-direction: column-reverse
this should flip the div scroll and position it at the bottom
Related
I am making the clone of a webpage which is made in JS but I am developing it by HTML, CSS, JS. Its navBar looks like this . Here is the link if you want to experience yourself link.
So, I have tried to implement this using IntersectionObserver API as well as by using window.addEventListener(). I don't want to implement this by using scroll event Listener because it is too heavy for end user.
const intersectionCB = ([entry]) => {
const elem = entry.target;
if (!entry.isIntersecting) {
elem.classList.add('nav__2-sticky');
// observer.unobserve(navBar);
} else {
elem.classList.remove('nav__2-sticky');
}
};
const observer = new IntersectionObserver(intersectionCB, {
root: null,
threshold: 0
});
observer.observe(navBar);
In HTML file
<div class="nav__2">
<div class="row nav__2--content">
<div class="logo-container">
<img src="img/logo-black.png" alt="" class="logo" />
</div>
........
In SCSS file
.nav {
&__2 {
top: 8rem;
position: absolute;
left: 0;
width: 100%;
&-sticky {
position: fixed;
top: 0;
}
}
}
You might understand what is happening. When navBar gets out of the view, (navBar is positioned at 8rem from top!). I append nav__2-sticky class (which is positioned fixed at 0 from top) to appear on the screen. Due to which entry.isIntersecting becomes true and elem.classList.remove('nav__2-sticky'); is executed. As a result navBar again gets out of the view and again elem.classList.add('nav__2-sticky') is executed. This cycle of adding and removing classes due to entry.isIntersecting becoming True and False is creating a problem for me. This happens in such speed that it shows abnormal behaviour.
So, is there any proper solution for this? I would also like to hear other solutions that might work.
I used scroll event after all. Here is the code, I think I don't need to explain. You will get more detailed explanation here link
const initialCords = navBar.getBoundingClientRect();
document.addEventListener('scroll', () => {
if (window.scrollY > initialCords.top) {
navBar.classList.add('nav__2-sticky');
} else {
navBar.classList.remove('nav__2-sticky');
}
});
Another angle could be to run the intersection observer on an element that is out of view (below the bottom of the screen) and not only the navbar itself
I'm trying to build a react Chat app and I was going to use the infinite scroll but it doesn't work the way I wanted it to. So I built one myself. I used useref to determine the height and if it reaches to the top it will add more chats. kinda like fb messenger's chat. The problem now is that when I add more chats, once it reaches the top, the scroll bar will continue to go up and not stick in place unlike how react-infinite scroll works.
May I know how I can go through this? Here is my code.
for the scroll:
const onScroll = () => {
if (topDiv.current) {
const { scrollTop, scrollHeight, clientHeight } = topDiv.current;
if(scrollTop === 0){
props.fecthMoreChat()
}
}
};
return(
<div id='scrollableDiv' ref={topDiv} onScroll={()=> onScroll()} style={{height:'100%', padding:'20px', display:'flex', flexDirection:'column', backgroundColor:'#efefef', overflowY:'scroll'}}>
{/* <div style={{visibility:'hidden'}} ref={topDiv}></div> */}
{currentChat.map((chat, index)=>{
return(
<div key={index} style={{textAlign:chat.sender===username?'right':'left'}}>
{chat.message}
</div>
)
})}
<div style={{visibility:'hidden'}} ref={botMsg}></div>
</div>
)
So the answer was actually pretty simple. I just took the current scroll height, saved it in a variable, then waited for the re-render and took the new scroll height. Basically, just subtract the old scroll height with the new scroll height and use that number to set scroll by using scrollTo(). Here is the code:
const onScroll = async () => {
if (chatDiv.current) {
const { scrollTop, scrollHeight, clientHeight } = chatDiv.current;
if(scrollTop === 0){
const pastScroll = scrollHeight
await props.fecthMoreChat()
const currentScroll = (await chatDiv.current.scrollHeight-pastScroll)
await chatDiv.current.scrollTo(0, currentScroll)
}
}
};
I wanted to know if there is a way to readjust tabs underneath a snackbar when it pops up at the top of the page? Like let's say tabs are at the very top of the page, snackbar with a height of 10px pops up at the top of the page then I want the snackbar to be the top element and the tabs to move underneath it when it is shown without them overlapping on each other?
Here's a stackblitz that might do what you want
https://stackblitz.com/edit/angular-f9k7ev
Basically what I'm doing is triggering some code (button, event, whatever) to set my snackbar to open up top, and adding a class to our container (here, a div, for you, your tabs) to move them down by an arbitrary value (here we do 10em) using CSS. We also listen to our afterDismissed() subscription to come back and then remove that class.
constructor(private _snackBar: MatSnackBar) {}
openSnackBar() {
const ourSnackbar = this._snackBar.openFromComponent(PizzaPartyComponent, {
duration: this.durationInSeconds * 1000,
verticalPosition: 'top'
});
ourSnackbar.afterDismissed().subscribe(() => this.removeOurClass());
let elements = document.getElementsByTagName("div");
Array.from(elements).forEach(element => {
element.classList.add('moved');
});
}
removeOurClass() {
let elements = document.getElementsByTagName("div");
Array.from(elements).forEach(element => {
element.classList.remove('moved');
});
}
and our CSS
.moved {
margin-top: 10em;
}
and the HTML we're moving (not the snackbar), the div we look for.
<div class="mat-app-background basic-container">
<snack-bar-component-example>loading</snack-bar-component-example>
</div>
I've got the following React app where I'm using react-spring to animate between routes and animate different elements based on the current scroll position.
When I use overflow: scroll on the Home component I'm then unable to return anything from my handleScroll method (it just returns 0):
handleScroll(e) {
let windowScrollPosition = window.scrollY
this.setState({ windowScrollPosition: windowScrollPosition }, () => console.log(this.state.windowScrollPosition, 'this.state.windowScrollPosition'))
}
Is there a way around this?
I need to use overflow: scroll to solve this issue unfortunately.
Any help is much appreciated!
Well that would make sense. If you have set an element to scroll that is 100% height then the window would never scroll the element would.
So you need to get the scroll position from the element with elem.scrollTop
You can create a ref to the element in React
constructor(props) {
super(props);
this.scrollContainer = React.createRef();
}
return (
<div className="scroll-container" ref={this.scrollContainer}></div>
)
And then in your handle scroll method use:
handleScroll(e) {
let windowScrollPosition = this.scrollContainer.current.scrollTop | window.scrollY;
this.setState({ windowScrollPosition: windowScrollPosition }, () => console.log(this.state.windowScrollPosition, 'this.state.windowScrollPosition'))
}
I've encountered an issue while trying to achieve a parallax style effect for one of my components. Currently, I am transforming the inline style by setting a scroll listener once the component mounts and changing the component state upon scroll. However, the inline style does not seem to change during re-rendering even though I have checked the output of the state in the render function and seems to have correct outputs. I tried checking previous answers, but I haven't been able to correct this issue.
Currently, my setup is as follows:
class Home extends React.Component {
constructor(props) {
super(props);
this.state = {
style: {
transform: 'translateY(0)'
}
};
this.parallax = this.parallax.bind(this);
}
componentDidMount() {
window.addEventListener('scroll', this.parallax);
}
componentWillUnMount() {
window.removeEventListener('scroll', this.parallax);
}
parallax() {
function onScroll() {
let scrolled = window.pageYOffset;
this.setState({
style: {
transform: `translateY(${scrolled})`
}
});
}
if(window.pageYOffset < window.innerHeight) {
window.requestAnimationFrame(onScroll.bind(this));
}
}
render() {
return (
<div className="home-wrapper" style={this.state.style}>
</div>
);
}
}
If anyone has any suggestions I will appreciate it. Thanks!
Initially it works fine because you have translateY(0) and in css 0 is fine without 'px' but once you update you are trying to do translateY(35) but css expects a px value so just change to translateY(${scrolled}px)