5

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>
Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
Hampus
  • 2,769
  • 1
  • 22
  • 38
  • If you want more context to the contrived example, please see: https://stackoverflow.com/questions/44323258/dynamically-create-angular-animations – Hampus Jun 02 '17 at 12:01
  • Question seems a bit unclear.... are you trying to get the green square to be visible within the parent? e.g. butted up against the right side of the red square? – chazsolo Jun 02 '17 at 12:02
  • Exactly. I'll clarify. – Hampus Jun 02 '17 at 12:02
  • 1
    Translate only affects the element it pertains to - the element itself is still within the document flow and is only _visually_ transformed. If you want the others to move, you will have to translate all of them together. – chazsolo Jun 02 '17 at 12:03
  • @chazsolo Understood, and I am looking for a way around that. Is there something similar that does affect all? – Hampus Jun 02 '17 at 12:07
  • Assuming you'd be applying this style inline and not as a CSS rule, you'd have to select all the children and apply the same transformation. I can move this to an answer if you believe it's justified. – chazsolo Jun 02 '17 at 12:08
  • Well. It does "solve" the contrived example but not my real issue. I however found that using margin-left: -100% works – Hampus Jun 02 '17 at 12:14
  • But I can live with awarding you the answer since you did verify my suspicion that translate only affects visual appearance – Hampus Jun 02 '17 at 12:20
  • Just be aware of performance difference between animations on transforms and other properties that *do* affect document flow; you'll get better performance using transforms. Also note that one can only help solve a contrived example if that's all you provide; if there's more to the real issue, you could have posted some follow up explanation. – chazsolo Jun 02 '17 at 12:20
  • 1
    I am perfectly happy with the comments and answer you've given. I had to break the real issue down to a contrived example and to be fair, I did provide more context in the very first comment I made (for which I now have a solution for thanks to this discussion). The performance degradation is unfortunately noticeable though. – Hampus Jun 02 '17 at 13:53

1 Answers1

8

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>
chazsolo
  • 7,873
  • 1
  • 20
  • 44