Search code examples
htmlcsstwitter-bootstrapflexboxweb-component

Two column layout with self-contained fixed-position sidebar


I need a two-column layout, where the left (sidebar) is fixed and the right (main content) is scrollable.

I've done so with bootstrap's flex grid/layout:

#left { width: 10rem; }
#right { margin-left: 10rem; }           /* <------------- PROBLEM */
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">

<div class="row g-0">
  <nav id="left" class="col vh-100 position-fixed bg-success">test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test</nav>
  <main id="right" class="col bg-warning">START test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test FINISH</main>
</div>

The problem is the right column knows about the left column's width. I tried bootstrap's col-auto but that doesn't help.

In reality, the left column is an imported sidebar component, which is self-contained. So the rest of my design (and the right column) should not have any knowledge of its dimensions. For example:

<div class="container">
  <sidebar />
  <main id="right"><!-- whatever --></main>
</div>

How can I change this layout so the sidebar's width is not needed by the rest of the design? Is that even possible?

Note:

  • It doesn't need to be in bootstrap (it can be plain css)
  • There's no JavaScript in my wasm SPA framework, so I can't use it (and regardless, it must be a self-contained component)

Solution

  • Here is an over simplified example with just plain CSS.

    It uses position: sticky instead of fixed on #left. This way, #left gets both its place in the flow, and get fixed as a result.

    This should allow #right to auto-fill the rest of space with flex: 1, without a hard coded width from #left.

    Hope it gets the desired result correctly.

    Example:

    /* Try any value 👇 */
    #left { width: 10rem }
    /* Auto-fill 👇 */
    #right { flex: 1 }
    
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }
    
    .container {
      display: flex;
    }
    
    nav {
      position: sticky;
      top: 0;
      height: 100vh;
      background-color: pink;
    }
    
    main {
      background-color: beige;
    }
    <div class="container">
    <nav id="left">test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test</nav>
    <main id="right">START test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test FINISH</main>
    </div>