Hi, I 've seen default scroll responses to specific areas of the code, but I still having a doubt. Iām building an app that sends messages to the screen and I want to know if there is any way to make the page does scroll to the bottom when the size of the messages are bigger than the size of the screen by default.
I also want to know this. I have tried almost all methods that cannot achieve automatic scrolling to the bottom. The only way to scroll to the bottom is to set an anchor point at the bottom, and then click the link to jump to scroll the page to the bottom, but this is not automatic
Here is a related response about scrolling to the bottom of a text area:
If you want to scroll to the bottom the page, hereās a modification of my previous answer:
import streamlit as st
if 'chat' not in st.session_state:
st.session_state.chat = "A: Hello"
def submit():
st.session_state.chat += f' \nB: {st.session_state.B}'
st.session_state.chat += ' \nA: Some response.'
# Clear the text input widget for convenience
st.session_state.B = ''
st.write(st.session_state.chat)
st.text_input('B\'s Response', key='B', on_change=submit)
# Define the scroll operation as a function and pass in something unique for each
# page load that it needs to re-evaluate where "bottom" is
js = f"""
<script>
function scroll(dummy_var_to_force_repeat_execution){{
var textAreas = parent.document.querySelectorAll('section.main');
for (let index = 0; index < textAreas.length; index++) {{
textAreas[index].style.color = 'red'
textAreas[index].scrollTop = textAreas[index].scrollHeight;
}}
}}
scroll({len(st.session_state.chat)})
</script>
"""
st.components.v1.html(js)
āI was unable to achieve the effect of automatic scrolling in the py file, but I observed the front-end code and found that the height of the pageāsā body 'was always 0. In fact, the container you are currently using needs scrolling.ā. I tried using st. components. v1. html () to execute JavaScript code, but this is not feasible. Because this method embeds an html under the iframe tag, the JavaScript code will be executed in this html without affecting the home page. Finally, I can only add the effect of automatic scrolling by modifying the local default āindex. htmlā front-end page, which requires modifying the files in the streamlit package. If you donāt mind later version iterations, you can use this method. Generally, the default āindex. htmlā file is located in your local folder, streamlint /static, where you can make the following modifications:
<script>
document.addEventListener('DOMContentLoaded', function() {
// Write the code that needs to be executed after the document is loaded here
// Here, priority is given to locating the completed div tags that can be loaded by opening the page
const targetDiv = document.querySelector('#root > div:nth-child(1) > div.withScreencast > div > div');
const observer = new MutationObserver(function(mutations) {
// Execute the corresponding code when detecting a change in the div element
// Locate the div tag that requires automatic scrolling here
const parentDiv = document.querySelector("#root > div:nth-child(1) > div.withScreencast > div > div > div > section.main.css-k1vhr4.egzxvld5");
// Locate your content div tag here. We need to scroll through the height of this content
const targetDiv = document.querySelector(".block-container.css-k1ih3n.egzxvld4 > div:nth-child(1) > div");
const height = targetDiv.getBoundingClientRect().height;
// Enable scrolling
parentDiv.scrollTop = height;
});
// Options for configuring a MutationObserver instance
const config = { attributes: true, childList: true, subtree: true };
// Start the MutationObserver instance
if (targetDiv) {
observer.observe(targetDiv, config);
};
});
</script>
Note: Thistag needs to be placed below thetag to ensure that the component is loaded before testing
Iām trying to achieve the same for a markdown (chat) container, specifically Iām developing a chatbot application that uses OpenAIās GPT-4 model for conversation. In this application, the chat history is displayed in a predefined div with class āchat-containerā. New messages are appended to this div, and the most recent message should be displayed automatically by scrolling to the bottom of the div.
Iāve tried several JavaScript-based solutions to auto-scroll the div to the bottom, but so far none of them have worked. Hereās a sample of the JavaScript that I tried implementing:
<script>
// Select the node that will be observed for mutations
const chatContainer = document.querySelector('.chat-container');
// Create a new instance of 'MutationObserver' named 'observer',
// passing it a callback function
const observer = new MutationObserver(function() {
chatContainer.scrollTop = chatContainer.scrollHeight;
});
// Start observing the target node for configured mutations
observer.observe(chatContainer, { childList: true });
</script>
The main issue is that this script doesnāt seem to trigger when a new message is added, and the scroll position remains at the current message instead of moving to the most recent message.
Iām interested in hearing if anyone has experienced a similar issue and if there are any known solutions or workarounds. Specifically, is there a way to auto-scroll to the most recent message in the chat history in Streamlit?
Javascript will not keep re-executing automatically. You have to either remove it and rewrite, or throw in a dummy variable like an integer that you increment thereby changing the script with each page load so it reruns.
Thanks a lot for the swift reply and the suggestion regarding the re-execution of Javascript in Streamlit. I implemented the recommended approach of using a dummy variable to force a change and hence a re-run of the script. The dummy variable increments properly, so there is a change on each page load. However, the desired effect - auto-scrolling to the bottom of a chat - isnāt happening.
Here is the JavaScript code snippet Iām using:
st.markdown(
"""
<script>
var element = document.getElementById("end-of-chat");
element.scrollIntoView({behavior: "smooth"});
</script>
""",
unsafe_allow_html=True,
)
And hereās how I increment the dummy variable in Python:
st.session_state['dummy_counter'] += 1
I insert a unique <div id="end-of-chat"></div> after each chat message and intend to use this as an anchor to scroll down to. The dummy variable change is triggering the rerun correctly, but it seems the Javascript isnāt executing or having an effect each time.
Despite these measures, after a certain number of messages, new messages arenāt scrolled into view and are instead off-screen.
Is there something in the way Streamlit handles Javascript that could be preventing the desired scrolling behavior?