最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

reactjs - How do i use overflow-x: auto and position: sticky at a same time in my typescript and scss code - Stack Overflow

programmeradmin2浏览0评论

I'm working on a React table where both the header and body exist within the same div. I need the table header to be position: sticky without setting a fixed height while ensuring that overflow-x: auto is applied to enable horizontal scrolling.

However, I'm unable to make the sticky header work correctly when scrolling horizontally. The header either doesn't stick or gets misaligned.

Here's my component:

<div className={styles.tableContainer}>
    <Table
        data={tableData}
        maxRows={50}
        columns={columns}
        renderDataItem={renderDataItem}
        className={styles.table}
        headerClassName={styles.tableHeader}
        headerItemClassName={styles.headerItem}
        bodyRowClassName={styles.tableBodyRow}
        dataClassName={styles.tableData}
        loading={loading}
        controlled
    />
</div>

scss

.table-container {
    overflow-x: auto;
    position: relative;
}

.table {
    border-collapse: separate;
    border-spacing: 0;
    border-width: 0;

    .table-header {
        background-color: var(--color-bg-secondary);
        border: none;
        position: sticky;
        top: 0;
        z-index: 100;
    }
}

Issue In a React table where both the header and body exist within the same container, you need:

The header to remain sticky at the top. The table to allow horizontal scrolling (overflow-x: auto). No fixed height for the header.

A common issue is that the header either doesn’t stick properly or becomes misaligned when scrolling horizontally.

And yesss!!, I finally got a way to solve this!! Solution The trick is to use two separate elements for the table container and the table header. Then, sync the horizontal scroll (scrollLeft) of the header with the main container using a scroll event listener.

const StickyTable = ({ data, columns, renderDataItem, loading }) => {
    const tableContainerRef = useRef<HTMLDivElement>(null);
    const tableHeaderRef = useRef<HTMLDivElement>(null);

    useEffect(() => {
        const tableContainer = tableContainerRef.current;
        const tableHeader = tableHeaderRef.current;

        if (!tableContainer || !tableHeader) return;

        const handleScroll = () => {
            tableHeader.scrollLeft = tableContainer.scrollLeft;
        };

        tableContainer.addEventListener("scroll", handleScroll);
        return () => tableContainer.removeEventListener("scroll", handleScroll);
    }, []);

    return (
        <div className="table-container" ref={tableContainerRef}>
            <div className="table-header" ref={tableHeaderRef}>
                {/* Render Table Header */}
            </div>
            <table className="table">
                <tbody>
                    {data.map((item, index) => renderDataItem(item, index))}
                </tbody>
            </table>
        </div>
    );
};

export default StickyTable;

Hope this helpss you too.

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论