Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flex item does not "float" after translated sibling

I have a problem with a translated flex item still occupying its original space so that the following flex item does not immediately follow. Please see JSFiddle or snippet for more details. I want the green rectangle to follow immediately after the red so that is will be visible within the border. I can unfortunately not translate the parent, it will have overflow: hidden so that only the child within the border is visible.

Here is a JSFiddle https://jsfiddle.net/3wv9d9dm/

Or a snippet:

.parent {
  display: flex;
  width: 100px;
  margin-left: auto;
  margin-right: auto;
  border: 1px solid black;
}

.child {
  flex: 0 0 100%;
}
<div class="parent">
  <div class="child" style="background-color:red;transform:translateX(-100%);"><h1>1</h1></div>
  <div class="child" style="background-color:green;"><h1>2</h1></div>
  <div class="child" style="background-color:blue;"><h1>3</h1></div>
</div>
like image 291
Hampus Avatar asked Jun 02 '17 11:06

Hampus


People also ask

Does Flex work with float?

The float property is ignored in a flex container. A flex container establishes a new flex formatting context for its contents. This is the same as establishing a block formatting context, except that flex layout is used instead of block layout.

How do you make a flex item float right?

Use justify-content: space-between and the order property. Use justify-content: space-between and reverse the order of the divs.

How do I move my flex item to the next row?

If all 3 fit on the same row, they won't wrap. The solution is to force them by adding a collapsed row (height 0) which takes up the entire width of the container, making it occupy an entire row, thus pushing the 3rd item on the next row.

Does Flex affect grandchildren?

The display: flex directive only affects a box model and its direct children. It does not affect grandchildren nodes.


1 Answers

From MDN, emphasis mine:

The <transform-function> CSS data type denotes a function used to modify an element's appearance.

Transforming an element only modifies appearance, not position in the document flow. This means that even though the element appears to have moved its position in the DOM it continues to affect sibling/other elements because its physical dimensions remain in place prior to the transformation.

A way to get around this is to animate or modify properties that affect document flow such as margin.

.parent {
  display: flex;
  width: 100px;
  margin-left: auto;
  margin-right: auto;
  border: 1px solid black;
}

.child {
  flex: 0 0 100%;
}
<div class="parent">
  <div class="child" style="background-color:red;margin-left:-100%;">
    <h1>1</h1>
  </div>
  <div class="child" style="background-color:green;">
    <h1>2</h1>
  </div>
  <div class="child" style="background-color:blue;">
    <h1>3</h1>
  </div>
</div>

An alternate way is to transform all elements together. This method is more performant (as it skips the layout and paint steps of the browser rendering pipeline). Visit this article on Rendering Performance for a detailed explanation.

One possible way of doing this:

let children = document.querySelectorAll('.child');

[].forEach.call(children, (child) => {
  child.style.transform = 'translate(-100%)';
});
.parent {
  display: flex;
  width: 100px;
  margin-left: auto;
  margin-right: auto;
  border: 1px solid black;
}

.child {
  flex: 0 0 100%;
}
<div class="parent">
  <div class="child" style="background-color:red;">
    <h1>1</h1>
  </div>
  <div class="child" style="background-color:green;">
    <h1>2</h1>
  </div>
  <div class="child" style="background-color:blue;">
    <h1>3</h1>
  </div>
</div>
like image 196
chazsolo Avatar answered Nov 14 '22 21:11

chazsolo