I have a ul
with a max-height
and overflow-y: auto
.
When the user enters enough li
elements, the ul
starts to scroll, but I want the last li
with the form
in it to always be present and viewable to the user.
I've tried implementing a scrollToBottom
function that looks like this:
scrollToBottom() { this.formLi.scrollIntoView({ behavior: 'smooth' }); }
But that just makes the ul
jump to the top of the screen and show the li
with the form in it as the only visible thing.
Is there a better way to accomplish this? Answers I find tend to be a bit older and use ReactDOM. Thanks!
CSS:
.prompt-box .options-holder { list-style: none; padding: 0; width: 95%; margin: 12px auto; max-height: 600px; overflow-y: auto; }
HTML:
<ul className='options-holder'> { this.state.items.map((item, index) => ( <li key={item.id} className={`option ${index === 0 ? 'first' : ''}`}> <div className='circle' onClick={this.removeItem} /> <p className='item-text'>{ item.text }</p> </li> )) } <li key={0} className={`option form ${this.state.items.length === 0 ? 'only' : ''}`} ref={el => (this.formLi = el)}> <div className='circle form' /> <form className='new-item-form' onSubmit={this.handleSubmit}> <input autoFocus className='new-item-input' placeholder='Type something and press return...' onChange={this.handleChange} value={this.state.text} ref={(input) => (this.formInput = input)} /> </form> </li> </ul>
Use element. scroll() to Scroll to Bottom of Div in JavaScript. You can use element.
To detect when a user scrolls to bottom of div with React, we can check if the sum of the scrollTop and clientHeight properties of a scrollable element is equal to the scrollHeight property of the same element. We call the useRef hook to create a ref and we assign the returned ref to the inner div, which is scrollable.
To handle the onScroll event in React: Set the onScroll prop on an element or add an event listener on the window object. Provide an event handler function. Access relevant properties on the event or window objects.
I have a container that fills the height of the page. This container has display flex and flex direction column. Then I have a Messages
component which is a ul
with one li
per message plus a special AlwaysScrollToBottom
component as the last child that, with the help of useEffect
, scrolls to the bottom of the list.
const AlwaysScrollToBottom = () => { const elementRef = useRef(); useEffect(() => elementRef.current.scrollIntoView()); return <div ref={elementRef} />; }; const Messages = ({ items }) => ( <ul> {items.map(({id, text}) => <li key={id}>{text}</li>)} <AlwaysScrollToBottom /> </ul> ) const App = () => ( <div className="container"> <Messages items={[...]}> <MessageComposer /> </div> )
The CSS is
.container { display: flex; height: 100vh; flex-direction: column; } ul { flex-grow: 1; overflow-y: auto; }
MessageComposer
has been omitted for brevity, it contains the form, the input field, etc. to send messages.
Use react-scroll library. However you will have to explicitly set ID of your ul
.
import { animateScroll } from "react-scroll"; scrollToBottom() { animateScroll.scrollToBottom({ containerId: "options-holder" }); }
You can call scrollToBottom
on setState callback.
For example
this.setState({ items: newItems}, this.scrollToBottom);
Or by using setTimeout.
Or you can even set Element
from react-scroll
and scroll to a certain li
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With