Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Prevent a wide table from stretching the flexbox item and container, make this table scrollable instead

My top-level layout is n columns, all of which are of fixed width (sidebars) except for the central one (mainbar) that should automatically fill up the remaining space.

So, I have this tricky wide table in the mainbar. It has a wrapper with overflow-x: auto, however instead of triggering the scrolling on the wrapper, it prefers to stretch everything up to the top-level flex container. This can be solved by adding width: calc(100% - {sum of widths of other columns}px) to the mainbar, but I'm looking for a more flexible solution that would allow adding more columns and resizing the existing ones without touching this calc rule.

Any ideas? Is there any way to say to a flex item: fill up the remaining space, but don't allow your content to stretch you?

UPD: Managed to do it by wrapping the content of the mainbar in a table with table-layout: fixed (the code is here), but I feel bad about it. Does anyone know of a more flexboxy solution? Or is this one okay?

// this JS generates placeholder text, ignore it
for (const el of document.querySelectorAll(".lorem")) {
    el.innerHTML = Array(Number(el.getAttribute("p")) || 1)
        .fill()
        .map(() => `<p>${chance.paragraph()}</p>`)
        .join("");
}
body {
    margin: 0;
}

.outer {
    display: flex;
}

.sidebar {
    flex: 0 0 300px;
    background: #eef;
}

.mainbar {
    background: #ffe;
    /* width: calc(100% - 500px); */
}

.rightbar {
    flex: 0 0 200px;
    background: #fef;
}

.table-wrapper {
    width: 100%;
    overflow-x: auto;
    background: pink;
}

.table-wrapper td {
    min-width: 400px;
}
<script src="https://unpkg.com/[email protected]/chance.js"></script>
<div class="outer">
    <div class="sidebar">
        <div class="lorem" p="4"></div>
    </div>
    <div class="mainbar">
        <div class="table-wrapper">
            <table>
                <tr>
                    <td class="lorem"></td>
                    <td class="lorem"></td>
                    <td class="lorem"></td>
                    <td class="lorem"></td>
                </tr>
            </table>
        </div>
        <div class="lorem" p="10"></div>
    </div>
    <div class="rightbar">
        <div class="lorem" p="3"></div>
    </div>
</div>
like image 716
thorn0 Avatar asked Mar 06 '23 19:03

thorn0


1 Answers

If I understand you correct, add flex: 1; min-width: 0; to your .mainbar rule and it should behave.

The flex: 1 will make it take available space and min-width: 0 will allow a flex item to be smaller than its content, which you can read more about here:

  • Why don't flex items shrink past content size?

Stack snippet

// this JS generates placeholder text, ignore it
for (const el of document.querySelectorAll(".lorem")) {
    el.innerHTML = Array(Number(el.getAttribute("p")) || 1)
        .fill()
        .map(() => `<p>${chance.paragraph()}</p>`)
        .join("");
}
body {
    margin: 0;
}

.outer {
    display: flex;
}

.sidebar {
    flex: 0 0 300px;
    background: #eef;
}

.mainbar {
    background: #ffe;
    flex: 1;
    min-width: 0;
    /* width: calc(100% - 500px); */
}

.rightbar {
    flex: 0 0 200px;
    background: #fef;
}

.table-wrapper {
    width: 100%;
    overflow-x: auto;
    background: pink;
}

.table-wrapper td {
    min-width: 400px;
}
<script src="https://unpkg.com/[email protected]/chance.js"></script>
<div class="outer">
    <div class="sidebar">
        <div class="lorem" p="4"></div>
    </div>
    <div class="mainbar">
        <div class="table-wrapper">
            <table>
                <tr>
                    <td class="lorem"></td>
                    <td class="lorem"></td>
                    <td class="lorem"></td>
                    <td class="lorem"></td>
                </tr>
            </table>
        </div>
        <div class="lorem" p="10"></div>
    </div>
    <div class="rightbar">
        <div class="lorem" p="3"></div>
    </div>
</div>
like image 129
Asons Avatar answered Apr 25 '23 16:04

Asons