How can I have a position: fixed; behaviour for a flexbox sized element?

CssFlexbox

Css Problem Overview


I have a div called .side-el which I would like to have in a position: fixed; behavior, but as soon as I apply position fixed the width alternates from the right one. The right width would be the one set by flexbox. How can I achieve this goal?

.container {
  -webkit-align-content: flex-start;
  align-content: flex-start;
  -webkit-align-items: flex-start;
  align-items: flex-start;
  display: -webkit-flex;
  display: flex;
  -webkit-flex-direction: row;
  flex-direction: row;
  -webkit-flex-wrap: wrap;
  flex-wrap: wrap;
  -webkit-justify-content: flex-start;
  justify-content: flex-start;
  
  * {
    box-sizing: border-box;
    -webkit-flex-grow: 1;
    flex-grow: 1;
    -webkit-flex-shrink: 0;
    flex-shrink: 0;
  }
}


.main-el {
  box-sizing: border-box;
  padding:0 2em;
  width: 70%;
}

.side-el {
  box-sizing: border-box;
  width: 30%;
}

<div class="container" style="background-color: blue; height: 100px;">
  <div class="main-el">
    <div  style="background-color: red; height: 1000px;">content</div>
  </div>
  <div class="side-el" >
    <div style="background-color: red; height: 100px;">content</div>
  </div>
</div>

Css Solutions


Solution 1 - Css

Here's a way to do this inspired by bootstrap:

.fixed-top {
  display: flex;
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
}

This gives your flex-box room to breathe and do it's flex-box thing. If your flex-direction is column, you could use top, left, bottom instead.

This works because when you give an element a fixed position and a left and right of 0 or a top and bottom of 0, the element is stretched to fill the space from left to right, or top to bottom. That in turn allows a flex-box to use the amount of space you would expect without position fixed.

Solution 2 - Css

You can't.

As explained by the CSS2.1 spec:

> Absolutely positioned boxes are taken out of the normal flow.

And the Flexible Box Layout spec confirms that:

> An absolutely-positioned child of a flex container does not > participate in flex layout. However, it does participate in the > reordering step (see order), which has an effect in their > painting order.

(Emphasis mine)

Solution 3 - Css

@Daniel , I know this is very late but ... while the accepted answer is correct, I don't feel it's very helpful. I had the same question (which is how I came across this post), and the solution I think I'll go with is to wrap the position fixed element within the flex element. Here's a (very ugly) example

Relevant Markup

  <aside class="Layout-aside" ng-class="{'isCollapsed': collapsed}" ng-controller="AsideCtrl">
    <div class="Layout-aside-inner">
      <button ng-click="collapsed = !collapsed">
        <span ng-show="collapsed">&gt;</span>
        <span ng-hide="collapsed">&lt;</span>
      </button>
      <ul class="Layout-aside-content">
        <li ng-repeat="i in items">{{i}}</li>
      </ul>
    </div>
  </aside>

Relevant CSS

.Layout-aside {
  order: 0;
  min-width: 140px;
  width: 140px;
  background-color: rgba(0, 255, 0, .4);
  transition: width .4s, min-width .4s; 
}
.Layout-aside.isCollapsed {
  min-width: 25px;
  width: 25px;
}

.Layout-aside-inner {
  position: fixed;
}

.Layout-aside.isCollapsed .Layout-aside-inner {
  width: 25px;
}

.Layout-aside.isCollapsed .Layout-aside-content {
  opacity: 0;
}

Solution 4 - Css

You can achieve it with a css alternative position: sticky

It acts great but the only problem is browser support (June 2018): https://caniuse.com/#feat=css-sticky

Hope it gets better soon.

Solution 5 - Css

position:sticky was mentioned by Juozas Rastenis above but without code example. Here's a minimalist example:

* {
  box-sizing: border-box;
}

body {
 display: flex;
 margin: 0;
}

nav {
 width: 20%;
 height: 100vh;
 top: 0; /* this is required for "sticky" to work */
 position: sticky;
 background: lightblue;
 padding: 1rem;
}

main {
 height: 3000px; /* cause scroll */
 background: lightpink;
 flex-grow: 1;
 padding: 1rem;
}

<body>
 <nav>
  sidebar here
 </nav>

 <main>
  content here
 </main>
</body>

Solution 6 - Css

A far simpler solution would be to use overflow-y:scroll and height: 100vh on the main-el container. This will give the appearance of fixed position to the side-el container without resorting to position: fixed.

Solution 7 - Css

I had the same issue, I actually just found a way to have flex-box, a width for the nav bar, and center it while in a fixed position.

nav {
	display: flex;
	height: 50px;
	width: 90%;
	left: 5%;
	position: fixed;
}

I wanted to be able to have a flex-box nav bar in a fixed position but centered. So what I did was do the left 5% since that's equal to half of the 10% width left over. Try it out, it might help you! :)

Solution 8 - Css

You are saying you want position:fixed;-like behavior that plays together with flexbox. As mentioned in the accepted answer, applying this property to an element drops it out of the normal flow, so this isn't really possible.

If what you want is to have a fixed sidebar .side-el and a scrollable content box .main-el as the items of a flex container, here's how you might do this:

  1. Disable scrolling in the flex container's parent; let's assume it's <body>, as you don't provide div.container's parent. Also, hard-set it's height to viewport-height (100vh) so that no part of the body's box remains outside view (imagine the body's box normally extending beyond your screen to contain the entire document; you don't want that, if you are to disable the ability to move the viewport via scrolling).
  2. Set the flex container's (.container) height to that of it's parent.
  3. Selectively re-enable scrolling for the content box (.main-el).

In CSS:

body{
  overflow: hidden;
  height: 100vh;
}
.container {
  display: flex;
  height: 100%;
}
.main-el {
  overflow-y: auto;
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionDaniel SchmidtView Question on Stackoverflow
Solution 1 - CssWylliam JuddView Answer on Stackoverflow
Solution 2 - CssOriolView Answer on Stackoverflow
Solution 3 - Csso4ohelView Answer on Stackoverflow
Solution 4 - CssJuozas RastenisView Answer on Stackoverflow
Solution 5 - CssRomanView Answer on Stackoverflow
Solution 6 - CssGreg BeaverView Answer on Stackoverflow
Solution 7 - CssAdrian D.View Answer on Stackoverflow
Solution 8 - CssodnesView Answer on Stackoverflow