Exclude element with fixed positioning from justify-content in flex layout

<>

This question already has an answer here:

Answers


This is Firefox bug 874718. The spec says

The justify-content property aligns flex items along the main axis of the current line of the flex container.

Since an absolutely (including fixedly) positioned element is out-of-flow, is not a flex item (this is fully defined in Absolutely-Positioned Flex Children). So justify-content should ignore it.

But Firefox wraps it inside an anonymous flex item, according to an old spec:

Absolutely positioned children of a flex container are not themselves flex items, but they leave behind "placeholders" in their normal position in the box tree. These placeholders are anonymous inline boxes with a width, height, and line-height of ‘0’, and they interact normally with the flexbox layout algorithm. In particular, they'll trigger the creation of anonymous flex items, or join neighboring inline elements in their anonymous flex items.

To fix that, instead of using justify-content, I recommend aligning with auto margins:

.column > div:not(:first-child) {
  margin-top: auto;
}

That will distribute free space equally before the children of the flex container, except the first one. The effect should be like justify-content: space-between.

In the case of the fixed element, that auto margin will just compute to 0.

.column {
  display: flex;
  flex-flow: column nowrap;
  height: 300px;
  float: left;
  margin: 10px;
  border: 3px solid black;
}
.column > div:not(:first-child) {
  margin-top: auto;
}
.column > div,
#fixed {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 200px;
  height: 50px;
  background-color: red;
}
#fixed {
  position: fixed;
  top: 0;
  right: 0;
}
<div class="column">
  <div>Element 1</div>
  <div id="fixed">Element 2</div>
  <div>Element 3</div>
  <div>Element 4</div>
  <div>Element 5</div>
</div>

Update

Upon reviewing the OP once more, this is the objective:

When the screen width is at a certain size (I determined 720px+), #fixed(col2 ele2) is position: fixed, if it's at a smaller width, it will be position: static. When #fixed is "fixed" it is no longer in col2, therefore the spacing between col2's children increase. What is desired is a consistent spacing between all divs (ie col2 spacing must coincide with col1 spacing).

The OP did not provide a means to show both states: fixed and static; of which static needed to be established. I have added two media queries that will insure both static and fixed states of #fixed will be triggered at 720px.

@media screen and (min-width: 721px) {
  .spacer {
    display: none;
  }
  #fixed {
    position: fixed;
  }
  .column.column {
    justify-content: space-between !important;
  }
}

@media screen and (max-width: 720px) {
  .spacer.spacer {
    display: none !important;
  }
  #fixed {
    position: static;
  }
  .column.column {
    justify-content: space-between !important;
  }
}

For some reason, when applying just the properties display and position, the justify-content: space-between would break. So I included justify-content: space-between to both media queries, unfortunately that didn't work either. So then I added !important, and it still failed. So then I used my secret ninja technique and doubled the class selector .column.column and I was victorious! Doubling up on a selector will increase it's specitivity to trump anything.

Plunker in Full Screen Mode Resize the browser to see the magic.

Plunker in Preview Mode


I don't understand what you want to with #fixed. But I do understand the problem described in the demo:

The space between Element 1 and Element 3 in the second column should be the same height as the other spaces.

Since the second column cannot arbitrarily space it's content by a predetermined length due to the nature of justify-content: space-between, you'll need just as many divs as the first column in order to obtain the same spacing as the first column. As I understand it, you cannot hard code layout (HTML), so I wrote a little JS to create an invisible div and append it to the second column thereby making the space between element 1 and 3 the same as the spaces between the children of the first column.

Fiddle


Need Your Help

Gmail not showing inline images

python django email gmail mime

I have the following function (Django) to send out an invitation:

Show/Hide & Mouseover Javascript

javascript html css mouseover show-hide

I been researching on Show/Hide javascript and pushed it further with a mouseover effect to achieve what I want. I've set up a Fiddle for better accessibility. However, I now want to push it by hav...