Freeze first column in html table

i have a css and javascript to freeze first column in a html table, and it is tested in [codepen] (https://codepen.io/zh1611/pen/bjaEKJ) but when i move it to my dash app, it is not working as expected.

below is code i am using:

app.css.append_css({“external_url”: ‘https://codepen.io/zh1611/pen/bjaEKJ.css’})
app.scripts.append_script({“external_url”: [‘https://code.jquery.com/jquery-3.2.1.min.js’,
https://codepen.io/zh1611/pen/bjaEKJ.js’]})

html.Table([
html.Thead([html.Tr([html.Th(col, style={‘textAlign’:‘center’, ‘fontSize’:‘16px’, **table_colors[‘header’]}) for col in df1.columns])]),
html.Tbody(rows)
], className=‘main-table’)

This is the output of the html code.

This is what i get when i scroll the table horizontally where the entire tbody whole shifted to the left while header remain static.
image

you should be able to do this directly with css. i recommend checking out https://stackoverflow.com/questions/1312236/how-do-i-create-an-html-table-with-fixed-frozen-left-column-and-scrollable-body

1 Like

i will consider change my dash-app code using this approach. but i am still scratching my head why the css/js combination work in codepen but not in my app. the html structure look-alike.

the answer from stackoverflow, this could be due to the table was dynamically created, that’s why the js script cannot find the object hence no effect.

after spent some time googling and stackoverflowing i finally found a solution…it seems simple problem in the first glance but ends up i bumped into some new terms: event bubbling, event delegation …etc. let me know if you have better solution.

ref: javascript - Attach scroll event to div with body on() binding fails - Stack Overflow
ref: javascript - Event binding on dynamically created elements? - Stack Overflow

dash:

return  html.Table([
    html.Thead([
        html.Tr(
            [html.Th(col, style={'textAlign':'center', 'fontSize':'16px', **table_colors['header']}) for col in df1.columns]
        )
    ]), 
    html.Tbody(rows)
], className='mtable')

js:

(document).on('mouseover', '.mtable tbody', function(){ // alert('scrolling'); (‘.mtable tbody’).on(‘scroll’, function() {
('.mtable thead').css("left", -(“.mtable tbody”).scrollLeft());
('.mtable thead tr th:first-child').css("left", (“.mtable tbody”).scrollLeft()-2);
('.mtable tbody tr td:first-child').css("left", (“.mtable tbody”).scrollLeft()-2);
});
});

For all of the folks finding this on Google, this is now a built-in feature of the DataTable called fixed_columns, see https://dash.plotly.com/datatable for examples.