Misaligned header when using scrollX and margin:auto
Misaligned header when using scrollX and margin:auto
Hi there,
I have recently added a "Streamlit" component to ITables, that let Python users render their DataFrames as interactive datatables in that context - see the demo here: https://itables.streamlit.app/
For the Streamlit component I've had to set scrollX=True
by default as the tables are rendered with an iframe that, unlike Jupyter Notebook outputs cells, don't have an horizontal scroll bar.
This mostly works, but when I try to center the table using margin:auto;table-layout:auto;width:auto;caption-side:bottom
for the style, I get a centered table but the header remains on the left, like in the screenshot below.
Do you see how to fix that? Thanks!
This question has an accepted answers - jump to answer
Answers
NB: to really get
margin:auto
in the app above, it's necessary to set it as the beginning or final condition (or to use a space), because the app currently replaces;margin:auto;
with;margin:0;
(that was an effort to no expose the users to this issue )A common problem is that Datatables needs
style="width:100%"
set on thetable
tag, as shown in this example to help calculate column sizes. Looks thewidth:auto;
sets the table width at 844px no matter the page width. Inspecting the table shows this:Not sure how to set this specifically on the
table
tag in your environment. Possibly setting ``width:100%;` will work.Kevin
Thank you Kevin!
I experimented with the table style set to
margin:auto;table-layout:auto;width:100%;caption-side:bottom
(through the "style" text input in the app) but I am afraid I still get the issue (I will try harder this week-end!)What you have highlighted is the
div
. Look at thetable
tag instead:Not sure if the test case you linked to is updated but it still shows a width of 844px.
Kevin
I looked at this more and realized this is a sample app from the developers of iTables. Looking at it further it seems that no matter what the width setting in the Style input is set to the
table
tag haswidth: 844px
set. For example:I would check with the iTables developers about the column width issue when using
scrollX
. Its unclear what exactly they are doing to setup the HTML and Datatables environment. Looks like you can ask about this here:https://github.com/mwouts/itables/issues
Kevin
Thanks Kevin! BTW I do maintain ITables and that's why I am trying to get this right
The style in the text box is passed verbatim to the table (well except for the replacement of
;margin:auto;
with;margin:0;
which I will remove when we solve this). It is set using table.setAttribute('style', style) and I can confirm that at the timestyle
is set, it haswidth:100%
if I pass that in the text box. So it must be changed to a fixed pixel width later on?Is it possible that calling
new DataTable
changes the style? When I log the style attribute I find, for instance:- (before)
margin:auto;table-layout:auto;width:100%;caption-side:bottom
- (after)
margin: auto; table-layout: auto; caption-side: bottom; width: 0px;
I also tried setting the style after calling
new DataTable
but then the caption was located between the table header and the rows. And if I set the style twice (before and afternew DataTable
) then I get a stretched table which is consistent withwidth:100%
but is not what I am looking for...I also tried
dt.columns.adjust()
as mentioned in https://datatables.net/forums/discussion/49564/scrolling-header-alignment but that had no effect, probably because my table is not 'visible' at that time.Maybe what I am after is more a behavior like
overflow-x:scroll;
as mentioned in that other thread, e.g. keep the table centered if there are not too many columns, and scroll only if it does not fit the container. Is that possible using only the standard DataTables arguments? (I have transitioned to thelayout
argument so I don't see myself adding a dedicated div in thedom
argument as in the other thread).Looking at this example the
table
tag hasstyle="width:100%"
the width of thetable
has a specific value. Note that Datatables clones the header, displays the cloned header and hides the original header withheight: 0;
. It looks like the clonedtable
has the defined width in px. I didn't realize that happened. Sorry for the misleading suggestion.Use
columns.adjust()
after the table becomes visible. See this example. I'm not sure how you are making the table visible. Maybe there is an event you can use or possibly a short setTimeout() to executecolumns.adjust()
.As a test maybe you can initialize Datatables with the table visible.
Kevin
Thanks Kevin! Sorry for taking that much of your time. I have tried
columns.adjust()
in a simpler context where I think that the table is initially visible, but that did not help.What I did precisely what to modify the html template in this way:
then I displayed a table with a style set to
margin:auto;width:auto
, andscrollX=true
:What I find strange (but I am afraid I know too little of html) is that the table gets a (fixed) width in pixels while
dt-scroll-body
anddt-scroll-foot
get a width of100%
It isn't clear to me that your
columns.adjust()
call there would happen after the table is made visible. It looks like it is just running immediately after the table is initialised, which wouldn't make any difference since the table initialisation already does column adjustment.As a hacky test, try resizing the window - if the table springs into the right size then you will need to discover whatever event it is, or code action that is making the table visible and trigger that. Perhaps it is in a tab, or there is a fade effect on the whole page or something?
Allan
Thank you Allan. Well even if I use
setTimeout
and check (visually) that the table is visible beforedt.columns.adjust()
is called, I still get the misaligned header. I have extracted below a short HTML file that shows the issue. Thank you for your help with this!Thanks for the extra code!
Here is that example running: https://live.datatables.net/zixucoyu/1/edit .
And with
width:auto
changed to bewidth:100%
it is fixed: https://live.datatables.net/zixucoyu/2/editYou can remove the
setTimeout
with that. The key is to setwidth:100%
.Allan
Thanks Allan! I agree than setting
width:100%
aligns the header and table body (and I don't think I needdt.columns.adjust()
in that case).Let me try to describe what I am trying to achieve:
1. I am looking for a default that would trigger an horizontal scroll bar for wide tables, but would work also for non-wide tables (and I don't know whether the table is wide or not, so I can't set scrollX dynamically)
2. I'd like to not stretch the table
3. I'd like to keep the table centered
If I use
-
scrollX=False
,margin:auto;width:auto
(the current default in Jupyter for ITables) then I get 2 and 3 (and Jupyter does provide an horizontal scroll so I almost get 1 - but I don't get that in the newer rendering context called "Streamlit")-
scrollX=True
,margin:auto;width:100%
then I get 1 and 3, but a stretched table like here: https://live.datatables.net/zixucoyu/4/edit-
scrollX=True
,margin:auto;width:auto;float:left
then I get 1 and 2, but a left sided table like here: https://live.datatables.net/zixucoyu/6/edit-
scrollX=True
,margin:auto;width:auto
then I get 1, 2 and 3 - except for the misaligned headerDo you see any other way to get 1+2+3 other than aligning the header with the table in the last configuration?
Thanks! I've got a bitter idea of what you want now, and given that you only want horizontal scrolling, not vertical, what I would do is set the table width to be
auto
as you originally did (and addmargin: 0
), but don't enablescrollX
. Instead, simply place the table in adiv
which hasoverflow: auto
.https://live.datatables.net/zixucoyu/8/edit
That way the table will be as narrow as it can be, but it has space that it can grow into and will overflow horizontally if needed.
The only downside is that the paging controls / filter would scroll out of sight at well, but that might not be an issue if you aren't using them (like in this example), or you could reposition them.
If this is what you are looking for, a perhaps better way of doing it, is to make the
div
that DataTables puts immediately around the table the scrolling element. That can be done with a little CSS.Allan
Thank you Allan (and Kevin) for your patience! Yes you're completely correct, the little CSS in your last link is what I was looking for!
I will now use, in the next PR,
rather than the
scrollX
option (except possibly in certain cases like the fixed columns...). This seems to work well in Jupyter, in Jupyter Book (= the documentation site) and in Streamlit too. Thank you again!Yeah, that workaround won't work with FixedColumns (or probably FixedHeader) unfortunately.
I had actually looked at using this method in DataTables 2 when vertical scrolling wasn't enabled. It solves a lot of issues, but introduces others...! You win some, you loose some. This one is a score draw
Allan