Streamlit-float: Fix vertical position of Streamlit containers

Hey everyone,

A few months ago, I made a post asking if anyone would be interested in a module or component that adds the ability to “float” containers to keep them visible as you scroll down pages of content. Since then, the idea has gotten some interest and feedback but I have not gotten the chance to work on it until very recently.

Check out the project here:

GitHub

GitHub - bouzidanas/streamlit-float: A simple module for fixing the vertical…

One thing I would like to improve is remove the need for initialization so if anyone has an idea on how to accomplish that let me know or make a pull request.

If you find this interesting or useful, please give it a try!

floating-example

6 Likes

Thanks for sharing, as also mentioned in another post, this is a helpful component, thanks for creating it!

1 Like

Hey everyone,

Thanks to discussions here and contributions from members (like @lkdd-ao) who are finding more and more use cases for this module, streamlit-float has significantly improved. I am happy to announce the first release version: Version 0.2.6!

New features:

Target floating containers with your own CSS!

You can now add your own CSS to any container you float by providing a string containing the CSS!

Example:

import streamlit as st
from streamlit_float import *

# Float feature initialization
float_init()

# Create footer container and add content
footer_container = st.container()
with footer_container:
    st.markdown("Copyright © 2023 Your Name - All Rights Reserved.")

# Float the footer container and provide CSS to target it with
footer_container.float("bottom: 0;background-color: white;")

Currently, both float and float_parent take a string containing CSS as their only (optional) argument.

CSS helper function

The streamlit_float module now contains a CSS helper function that makes it easier to generate CSS for floating containers programmatically.

Example:

import streamlit as st
from streamlit_float import *

# Float feature initialization
float_init()

# Create footer container and add content
footer_container = st.container()
with footer_container:
    st.markdown("Copyright © 2023 Your Name - All Rights Reserved.")

# Get custom theme background color if set, otherwise default to white
bg_color = st.get_option('theme.backgroundColor')
if bg_color is None:
    bg_color = "white"

# Generate CSS to target the floating footer container
css = float_css_helper(bottom="0", background=bg_color)

# Float the footer container and provide CSS to target it with
footer_container.float(css)

NEW Float Box container

The newly added float_box function takes the markdown you provide and puts it in a newly created floating div container. This function also provides direct access (via its arguments) to several CSS parameters/attributes allowing you to easily adjust size, position, background, and border as well as add box-shadows and transitions.

Example:

import streamlit as st
from streamlit_float import *

float_init()

if "show" not in st.session_state:
    st.session_state.show = True

# Page content
st.markdown('''# Large Language Models

Large language models, such as GPT-3 and BERT, have revolutionized natural language processing. These models are trained on massive amounts of text data and can generate human-like text, answer questions, and perform various language-related tasks. They have been used in a wide range of applications, including chatbots, language translation, and content generation. The advancements in large language models have opened up new possibilities for improving communication and understanding between humans and machines.

## The beginning

The beginning of large language models can be traced back to the development of the Transformer model by Vaswani et al. in 2017. This model introduced the concept of self-attention, which allows the model to capture long-range dependencies in text and greatly improves its ability to understand and generate coherent sentences. Since then, researchers and engineers have built upon this foundation to create even larger and more powerful language models like GPT-3 and BERT.

One of the key challenges in developing large language models is the computational resources required for training and inference. Training these models often involves using thousands of GPUs and weeks or even months of compute time. Additionally, the size of these models can make them difficult to deploy and run on resource-constrained devices. However, advancements in hardware and distributed computing have made it possible to train and use these models at scale, opening up new opportunities for natural language processing.

## Enter the big players

The big players in AI, such as Microsoft, Google, and Facebook, have played a crucial role in bringing the resources needed to accelerate progress in large language models (LLMs). These companies have invested heavily in research and development, as well as in building the necessary infrastructure to train and deploy these models.

Microsoft, for example, has made significant contributions to the field of natural language processing through projects like Microsoft Research NLP and the development of the Turing NLG language model. They have also developed Azure Machine Learning, a cloud-based platform that provides the computational resources and tools needed to train and deploy large language models at scale.

Google, on the other hand, has been at the forefront of LLM research with projects like Google Brain and Google Research. They have developed models like BERT and T5, which have achieved state-of-the-art performance on a wide range of natural language processing tasks. Google's cloud platform, Google Cloud, provides the infrastructure and tools necessary for training and deploying large language models.

Meta has also made significant contributions to the field of natural language processing through projects like PyTorch and the development of models like RoBERTa. They have also invested in building powerful computing infrastructure, such as the FAIR (Facebook AI Research) cluster, which enables researchers to train and experiment with large language models.

These companies have not only brought the necessary computational resources to the table but have also contributed to the research and development of novel techniques and architectures for improving the performance and efficiency of large language models. Their contributions have helped to push the boundaries of what is possible in natural language processing and have accelerated progress in the field.

## Llama 2: Partnership between Microsoft and Meta

Llama 2 is a collection of open-source large language models (LLMs) developed by Meta AI. The models range in size from 7 billion to 70 billion parameters and are designed to perform well on various language processing tasks. Llama 2 is available for free for research and commercial use. 
Llama 2 is the result of a partnership between Meta and Microsoft. The models are optimized for dialogue use cases and can be used to create a ChatGPT-like chatbot. 

Llama 2 is considered a game-changer for the adoption and commercialization of LLMs because of its comparable performance with much larger models and its permissive open-source license. The license allows the use and distribution of Llama 2 in commercial applications. 

Meta has also introduced Code Llama, a large language model that can generate code from text prompts.
            
## Getting started with Llama 2

To get started with Llama 2, you need to fill out the access form on Meta's website and wait for a confirmation email. Once access is granted, you can:

- Visit llama2.ai to interact with the chatbot demo.
- Download the Llama 2 code.
- Access Llama 2 through Microsoft Azure or Amazon SageMaker JumpStart.
- Try a variant at llama.perplexity.ai.

You can also run Llama 2 locally. To do this, you can: 

- Download the Llama 2 model in GGML format from Hugging Face.
- Install the latest version of Python.
- Prepare the Python environment.
- Interact with the Llama 2 large language model.

Facebook researchers say that Llama 2 models perform better than existing open-source models. They also say that Llama 2 models are close behind closed-source models like ChatGPT.\n
''')
st.warning("**DISCLAIMER!** The majority of this psuedo-article was generated by AI. Information may be inaccurate or misleading. Tools such as [Markdown Composer](https://markdown-composer.streamlit.app/) and Google's [Generative AI search](https://blog.google/products/search/generative-ai-search/) were used to create this article.")

# Container with expand/collapse button
button_container = st.container()
with button_container:
    if st.session_state.show:
        if st.button("⭳", type="primary"):
            st.session_state.show = False
            st.experimental_rerun()
    else:
        if st.button("⭱", type="secondary"):
            st.session_state.show = True
            st.experimental_rerun()
    
# Alter CSS based on expand/collapse state
if st.session_state.show:
    vid_y_pos = "2rem"
    button_b_pos = "21rem"
else:
    vid_y_pos = "-19.5rem"
    button_b_pos = "1rem"

button_css = float_css_helper(width="2.2rem", right="2rem", bottom=button_b_pos, transition=0)

button_container.float(button_css)
float_box('<iframe width="100%" height="100%" src="https://www.youtube.com/embed/J8TgKxomS2g?si=Ir_bq_E5e9jHAEFw" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>',width="29rem", right="2rem", bottom=vid_y_pos, transition=0, shadow=12, css="padding: 0;")

Demo: Component Demo

streamlit-float-demo4

3 Likes

:grinning: Great, better than I thought. Based on streamlit_float, I can achieve more functions. Thank you again.

2 Likes

Great component! Love it. Quick question, the css variable in the float_css_helper() function, how would one go about using it? I though it was a dictionary where we could input out own css variables not included in the available options. Could you perhaps give an example?

Thanks.

To answer your question, the css variable in the helper function takes a css string and appends it to the end of the return string. Its currently a placeholder for a planned feature where you can give it a dictionary containing css and it will construct and append this css to the end of the returned steing.

I though it was a dictionary where we could input out own css variables not included in the available options.

This is basically the planned feature i mentioned that is not yet implemented. Currently, its is to allow you to construct CSS for the available options (that are really only currently available directly in the Float Box function). Most other functions like the float function only take pure CSS strings in their optional arguments. The helper function creates this string provided specific options that are deemed most important. For other options you have to provide in a css string.

I will get back to you with more examples a bit later and maybe if I have time, see if I can get the feature implemention finished.

1 Like

Cool thanks for getting back to me. Look forward to it!

1 Like

Hey @Rushmore,
I have added the feature you asked about to the helper function. You can now give the css argument a dictionary instead of a string if you want:

test_css = float_css_helper(css='color: red;font-size: 2rem;background-image: url("https://c.pxhere.com/photos/ed/91/purple_skin_leather_texture_leather_texture_background_bright_leatherette_decorative-1372721.jpg!d")')
container.float(test_css)

or …

test_css = float_css_helper(css={"color": "red", "font-size": "2rem", "background-image": 'url("https://c.pxhere.com/photos/ed/91/purple_skin_leather_texture_leather_texture_background_bright_leatherette_decorative-1372721.jpg!d")'})
container.float(test_css)

Any additional options/arguments you give the helper function will also be added to the returned CSS:

test_css = float_css_helper(color="red", font_size="2rem", background_image='url("https://c.pxhere.com/photos/ed/91/purple_skin_leather_texture_leather_texture_background_bright_leatherette_decorative-1372721.jpg!d")')
container.float(test_css)

Make sure to use underscores instead of dashes for the css property names when given as separate arguments to the function.

You can also mix the last method with the css options (one of the first two ways shown here):

test_css = float_css_helper(css={"color": "red", "font-size":"2rem"}, background_image='url("https://c.pxhere.com/photos/ed/91/purple_skin_leather_texture_leather_texture_background_bright_leatherette_decorative-1372721.jpg!d")')
container.float(test_css)

Of course, you need to make sure you update to version 2.10 or later

NIce! Looks good thanks will update and use :+1:

Hey, just tested your component on firefox browser and it seems only the float_box method works. I though perhaps it was just my implementation though when I went to the component’s example web app via streamlit cloud in firefox it was pretty much the same.

Is there a way around this? If you don’t have the time its not a problem. Just want to know before I seek alternative measures for firefox in particular.

Hey,

This is the weak point of the method used to float Streamlit containers. Because Streamlit has no way of adding id and classes to its containers (a requested feature that has yet to be add to Streamlit), I have to use the CSS :has function to target the containers. Unfortunately, Firefox does not allow or recognize this CSS function by default. You have to change the browser settings to turn it on.

Other solutions that I thought of are more messy and frustrating to use. So I dont see this getting fixed until Streamlit adds the ability to target its containers somehow (add our own class or id to them) or Firefox adds the :has function. The latter might happen this year! They are apparently working out the bugs right now

If you can come up with a solution or a better way, let me know!

Note that the Float Box doesnt have this issue because its essentially a html div element (not a Streamlit container) and I can easily add a class to that!

1 Like

Ahh okay. I built something fairly similar to the capability of adding custom id/classnames to existing elements here. It uses streamlit’s components.html component where javascript is used to inject it.

Something like this:

js = '''

<script>
     sidebar_nav_container = parent.document.querySelectorAll('[data-testid="stSidebarNav"] ul');
     sidebar_nav_container[0].classList.add('sidebar-nav-list-container-streamlit')
     
     sidebar_nav_parent_el = parent.document.querySelectorAll('[data-testid="stSidebarNav"] ul li');
     sidebar_nav_parent_el.forEach((el) => {{
                        el.classList.add('sidebar-individual-page-container-streamlit')
                    }})
</script>

'''

st.components.v1.html(js)

The only downfall was it create a massive whitespace but I was able to use st.empty() to add and then remove it because it was appended but it had to be initialised at the start of the app so that it was always there when the app loaded and during sessions.

I thought st.components.v1.html(js) put the JavaScript in an <iframe> and thus doesnt have access to containers outside the iframe? If this is not the case, then I think we have a possible solution!

Yeah but see this for more on this.

1 Like

Oh I see, I didnt know you could access the window.parent.document from inside the iframe. Thats extremely convenient for a lot of things!

I am working on something else at the moment so I cant implement this solution right now.

It would be very helpful if you can open up an issue in the github repository with enhancement tag. A short description of the limitation (float functions do not work in Firefox) and the reason (not being able to target containers with css - Firefox doesnt support :has) and provide your suggestion for how to get around the limitation using Javascript.

This way we can keep track of this and I can post updates for everyone there as well! I will implement a solution based on this work around when I get the chance!

Thank you for making me aware of this trick! I think it could come in handy in the future.

2 Likes

No problem. Will do so later in the day. Its 3am here in london so gotta get some snoozes. Will let you know when its done. :smile:

2 Likes