Dataframe fullscreen-like view and resize into container

Hi, I’m on the first experience with Streamlit and there is possibile I miss some config or option.
The starting point of my app is to show database info selected from a tree showed into sidebar.
I solved the tree using streamlit_antd_components,
but the dataframe and other components will use only a very small part of the available space.
The ‘Fullscreen’ mode, clicking the button, uses all the available space and resizes as expected with the browser window,
but hides all the rest.

There is a way to show and resize the dataframe into the container like in ‘Fullscreen’ mode?

This is an axample code.

import streamlit as st
import pandas as pd

item_count = 100
column_count = 100
row_count = 1000

columns = []
for col in range(column_count):
    columns.append(f'column_{col:04d}')
df = pd.DataFrame(columns=columns)
for row in range(row_count):
    cells = []
    for col in range(column_count):
        cells.append(f'cell_{row:04d}_{col:04d}')
    df.loc[row] = cells

with st.sidebar:
    st.write("sidebar")
    for i in range(item_count):
        st.write(f"item_{i:04d}")

with st.container():
    st.write("header")
    st.dataframe(df, use_container_width=False)
    st.write("footer")

Take a look at the width and height parameters to st.dataframe.

Thanks Goyo for the reply.
The options width and height allow to set a fixed value, that is not the goal.
I tryed to remove the st.container() without any visible change.
I added border=True as st.container() option to see the used area.

What about the layout parameter to set_page_config?

Thanks for the suggestion: much better but not enough.
Horizontal resize works well and the wasted space on the left and right of the container might be acceptable, but no vertical space and resize management like ‘Fullscreen’ mode does.

As far as I know there is no way to make the height responsive. You’ll have to settle for a fixed height.

I have seen people trying to use JS to dynamically change the height, without much success IIRC. You can try that too.

‘Fullscreen’ mode does it very well, fills the browser window, resizes the table accordingly the browser window and always shows both the scrollbars around the table; why it is not possible to do the same into a container?

I gave this a try and was able to display a data frame that resizes their width (if the content is wider, it allows scrolling left/right):

You can see the demo here.

A few comments:

  • this will get the width on the first load, resizing the window won’t trigger a resize
  • it’s a read-only data frame
import streamlit as st
import streamlit.components.v1 as components
import jinja2
import pandas as pd
import numpy as np
from streamlit_js_eval import streamlit_js_eval

st.set_page_config(layout="wide")
st.title("Full screen data frame")

# Generate fake data
n_cols = 10
df = pd.DataFrame(np.random.randn(100, n_cols),
                  columns=("col %d" % i for i in range(n_cols)))


# get width
page_width = streamlit_js_eval(js_expressions='window.innerWidth', key='WIDTH',  want_output = True)
st.write(f"Width: {page_width}")

# Define maximum width as a variable
width = page_width
height = 600 


# Generate HTML table using Jinja2
template = jinja2.Template("""
<link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">

<div style="width: {{width}}px; height: {{height}}px; overflow-y: auto; overflow-x: auto;" class="mx-auto p-4 border border-gray-300 rounded-lg shadow-lg">
    <table class="min-w-full border-collapse">
        <thead>
            <tr class="bg-gray-200">
                {% for column in columns %}
                    <th class="p-2 border border-gray-300 text-left">{{ column }}</th>
                {% endfor %}
            </tr>
        </thead>
        <tbody>
            {% for row in rows %}
                <tr class="hover:bg-gray-100">
                    {% for value in row %}
                        <td class="p-2 border border-gray-300">{{ value }}</td>
                    {% endfor %}
                </tr>
            {% endfor %}
        </tbody>
    </table>
</div>
""")


html_table = template.render(columns=df.columns, rows=df.values.tolist(), width=width, height=height)
components.html(html_table, height=height, width=width)

Thanks for the reply but the code do not what i’m trying to do.
If you want to see what i mean, run my code and click the ‘Fullscreen’ button that appear in the upper right corner of dataframe.
The needed code is already implemented into Streamlit and used for the ‘Fullscreen’ mode.

This code

  1. do not fill the space
  2. do not resize the data vertically nor horizontally
  3. both the scollbars scroll the browser window, not the data


2. and 3.

Thanks everyone for your replies.
Using the suggestions I was able to assemble this code; it is tricky, not fluid (needs some forced rerun) and requires user intervention, but does what I want. The st.dataframe width is well managed using layout=“wide” as st.set_page_config option. The rest is about the st.dataframe height.

import streamlit as st
from   streamlit_js_eval import streamlit_js_eval
import pandas as pd
import time

st.set_page_config(page_title='title', layout="wide")

if "run_count" not in st.session_state:
    st.session_state.run_count = 0

st.session_state.run_count += 1

if "height" not in st.session_state:
    st.session_state.height = None

if "skip_streamlit_js_eval" not in st.session_state:
    st.session_state.skip_streamlit_js_eval = False

# get window height using streamlit_js_eval
# streamlit_js_eval work-arounds:
# 1. returns None without sleep and retry
# 2. use some empty space into the container
#print(f"Run count before check: {st.session_state.run_count:4d} --- Window Height: {str(st.session_state.height):4s} --- Skip skip_streamlit_js_eval: {st.session_state.skip_streamlit_js_eval}")
if not st.session_state.skip_streamlit_js_eval:
    time.sleep(0.2) # neverending loop without sleep
    height = streamlit_js_eval(js_expressions='window.outerHeight', key = 'window.outerHeight')
    if height is not None:
        st.session_state.skip_streamlit_js_eval = st.session_state.height == height
    st.session_state.height = height
#    print(f"Run count before rerun: {st.session_state.run_count:4d} --- Window Height: {str(st.session_state.height):4s} --- Skip skip_streamlit_js_eval: {st.session_state.skip_streamlit_js_eval}")
    st.rerun()
st.session_state.skip_streamlit_js_eval = False
#print(f"Run count after check:  {st.session_state.run_count:4d} --- Window Height: {str(st.session_state.height):4s} --- Skip skip_streamlit_js_eval: {st.session_state.skip_streamlit_js_eval}")

# get other (non dataframe) components height
# value found trying and trying ...
other_components_height = 317

# compute dataframe height
dataframe_height        = max(0, int(st.session_state.height - other_components_height))

# Remove whitespace from the top of the page and sidebar
# https://discuss.streamlit.io/t/reduce-white-space-top-of-the-page/21737
st.markdown("""
        <style>
               .block-container {
                    padding-top: 3rem;
                    padding-bottom: 2rem;
                    padding-left: 2rem;
                    padding-right: 2rem;
                }
        </style>
        """, unsafe_allow_html=True)

item_count = 30
column_count = 30
row_count = 50

columns = []
for col in range(column_count):
    columns.append(f'column_{col:04d}')
df = pd.DataFrame(columns=columns)
for row in range(row_count):
    cells = []
    for col in range(column_count):
        cells.append(f'cell_{row:04d}_{col:04d}')
    df.loc[row] = cells

with st.sidebar:
    st.write("sidebar")
    for i in range(item_count):
        st.write(f"item_{i:04d}")

with st.container(border = True):
    st.write(f"header --- Run count: {st.session_state.run_count} --- Window Height: {st.session_state.height} --- Dataframe Height: {dataframe_height}")
    if dataframe_height:
        st.dataframe(df, height=dataframe_height)
    st.write("footer")
  1. At start the st.dataframe fills the height of the window
  2. At window resize the st.dataframe remain unchanged, the script do not rerun automatically
  3. At user rerun (pressing R or click Rerun in the 3-dot menu in the top right corner) the st.dataframe fills the height of the window

    To compute the required dataframe height I must know the window height and the height of the other Streamlit components, found a value good for maximized window (for my monitor resolution).

The call to streamlit_js_eval returns the window height but:

  • must be executed multiple times with a delay between the calls to get the value instead of None
  • used some space (height) like an empty st.write

So the script must call st.rerun until streamlit_js_eval call returns not None value, save the value and then rerun without the streamlit_js_eval call.
As result the page will be drawn an redrawn with different layouts.

This code is enough for a demo but not for production.

I submitted the Feature request
add an option to dataframe and data_editor to use the available window heigth