2

I believe this goes exactly against the way the display: flex property is supposed to work, but I wonder if it's possible, or if there's a hack for it.

Is it possible to have a child of a flex container not behave as a flex item? Example:

http://jsbin.com/jusehedumi/edit?html,css,output

Is there any way in which child three could be made behave as a normal display block? Without it automatically aligning due to the justicity-content: center of the parent flex container?

A purely css solution would be awesome. Thinking about it, adding some extra HTML would probably make this issue easier to fix/solvable.

.flex{
  display: flex;
  justify-content: center;
  width: 400px;
  height: 400px;
  background: #ccc;
}

.child{
  width: 100px;
  height: 100px;
  background: red;
  margin: 20px;
}

.child.three{
  background: blue;
  display: block;
}
  Is there any way to make child three not behave as a flex child?
  <div class="flex">
    <div class="child one"></div>
    <div class="child two"></div>
    <div class="child three"></div>
  </div>

Edit: I know a child can be taken out of the flex container by using position: absolute or the likes. What I'm looking for is a way of making one of the children behave as a block element (or inline for that matter) while remaining a child of the flex container.

Obed Parlapiano
  • 3,226
  • 3
  • 21
  • 39
  • 1
    What do you want to do to that block? Can you override the flex behavior with position: absolute ? – Axnyff Jan 09 '18 at 16:37
  • This is mostly a curiosity question. I had an actual use case but figured it's easier to change the HTML a bit and how I approached the styling rather than break how flex is supposed to work. Still, could be a useful question to other people! – Obed Parlapiano Jan 10 '18 at 08:21
  • @ObedMarquezParlapiano Updated my answer. As you can see, there is more than one way to make a flex item behave as a block or inline, though the way to do it depends on what one want to achieve. – Asons Jan 10 '18 at 09:30

2 Answers2

8

Updated based on a question edit

No, there is no property that can be set, to make a flex container child stop being a flex item.

What can be done though, is to not use any flex properties on one, and by that make it behave as a block or inline-block element.

E.g., combined with flex-wrap: wrap enabling items to wrap, giving the third item flex: none will make it behave as an inline block, giving it width: 100% it will behave as a block (as shown below).

When it comes to flex container properties, some can be overridden on the item, like align-items / align-self, some cannot, like justify-content.

To mimic justify-content in your given code sample, auto margins could be used, and with that, together with a trick using the order property and a pseudo element, one could make the third behave like an inline block:

.flex{
  display: flex;
  flex-wrap: wrap;
  align-content: flex-start;
  width: 400px;
  height: 400px;
  background: #ccc;
}

.child{
  width: 100px;
  height: 100px;
  background: red;
  margin: 20px;
}

.child.one{
  margin-left: auto;
}
.child.two{
  margin-right: auto;
}

.flex::after{
  content: '';
  width: 100%;
  order: 1;
}
.child.three{
  background: blue;
  order: 2;
}
Is there any way to make child three not behave as a flex child?
  <div class="flex">
    <div class="child one"></div>
    <div class="child two"></div>
    <div class="child three"></div>
  </div>

As a note, here is a good answer that describes the flex item's display type:


Initial answer

Is it possible to have a child of a flex container not behave as a flex item?

There is no good, cross browser solution to make a flex container child not behave as a flex item.

One can use absolute positioning, though as it will take the element out of flow, it won't behave like a block element when it comes to content flow.

Is there any way in which child three could be made behave as a normal display block?

Based on the fact that a normal block element take a row of its own, filling its parent's width, you can, by adding flex-wrap: wrap to the container and give the third item a width of 100%, make it behave like one.

Note, I also added align-content: flex-start; so the items won't stretch/spread along the parent's height, instead align at its top.

.flex{
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-content: flex-start;
  width: 400px;
  height: 400px;
  background: #ccc;
}

.child{
  width: 100px;
  height: 100px;
  background: red;
  margin: 20px;
}

.child.three{
  background: blue;
  width: 100%;
}
Is there any way to make child three not behave as a flex child?
  <div class="flex">
    <div class="child one"></div>
    <div class="child two"></div>
    <div class="child three"></div>
  </div>

If you want the third item to keep the same width as the first two, a wrapper could help you.

.flex{
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-content: flex-start;
  width: 400px;
  height: 400px;
  background: #ccc;
}

.child{
  width: 100px;
  height: 100px;
  background: red;
  margin: 20px;
}

.child.three{
  background: blue;
}

.wrapper{
  width: 100%;
}
Is there any way to make child three not behave as a flex child?
  <div class="flex">
    <div class="child one"></div>
    <div class="child two"></div>
    <div class="wrapper">
      <div class="child three"></div>
    </div>
  </div>

If a wrapper can't be used, you could use a right margin, though since percent based margin might render different on different browsers, you need to test it properly, or use another unit, e.g. viewport units, like vw.

.flex{
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-content: flex-start;
  width: 400px;
  height: 400px;
  background: #ccc;
}

.child{
  width: 100px;
  height: 100px;
  background: red;
  margin: 20px;
}

.child.three{
  background: blue;
  margin-right: calc(100% - 120px);
}
Is there any way to make child three not behave as a flex child?
  <div class="flex">
    <div class="child one"></div>
    <div class="child two"></div>
    <div class="child three"></div>
  </div>

If neither of the above solutions is an option, the same layout can be achieved using block and inline block elements.

.flex{
  /*  removed the Flexbox properties
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  */
  text-align: center;               /* added  */
  width: 400px;
  height: 400px;
  background: #ccc;
}

.child{
  display: inline-block;            /*  added  */
  width: 100px;
  height: 100px;
  background: red;
  margin: 20px;
}

.child.three{
  background: blue;
  display: block;
}
<strike>Is there any way to make child three not behave as a flex child?</strike>
  <div class="flex">
    <div class="child one"></div>
    <div class="child two"></div>
    <div class="child three"></div>
  </div>
Asons
  • 84,923
  • 12
  • 110
  • 165
5

Only elements that are in-flow children of a flex container are flex items.

Therefore, elements that are absolutely-positioned children or descendants beyond the children of a flex container are not flex items and ignore flex properties.

See my answer here for more details:

Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
  • Right! I knew that, should have made my answer more clear. I meant making a child *behave* as a `block` element even while being inside a flex container. – Obed Parlapiano Jan 10 '18 at 08:17
  • Technically, flex items *are* block-level elements, except they exist in a flex formatting context. You should take a step back and explain the primary objective, not what you feel is the path to the solution. Try to avoid the [**XY Problem**](https://meta.stackexchange.com/q/66377/300177). – Michael Benjamin Jan 10 '18 at 18:02