2

It is not entirely clear to me how CSS transforms affect the flow layout of the document and the positioning of an element. According to the documentation on MDN and W3C, CSS transforms do not interfere with the flow layout:

From MDN on CSS transforms (emphasis mine):

By modifying the coordinate space, CSS transforms change the shape and position of the affected content without disrupting the normal document flow.

Thus, if we translate an element, the original flow layout should remain intact and the result of the transformation should be purely visual. A trivial example of this is demonstrated below:

.container {
  background: white;
  margin: 0 auto;
  border: 1px solid grey;
}

.block {
  width: 100%;
  height: 100px;
}

.blue {
  background: blue;
}

.red {
  background: yellow;
}

.transform {
  transform: translateY(-200%);
}
<div class="container">
  <div class="block red transform"></div>
  <div class="block blue"></div>
</div>

In this example, there are two div elements and the upper element was translated vertically so that it is not visible anymore. However, the flow layout remains unchanged and there is no overflow in the document. That is, the result of the transformation is purely visual.

Now, consider a page layout with a wrapper of fixed width, such that the width of the child elements is bounded by the wrapper element. Now add a positioned element that is wider than the wrapper and add an offset (e.g. left). In "narrow enough" windows, the body overflows and we are able to scroll horizontally. However, if we translate the same element and re-center it, the overflow disappears, implying that the transformation is not purely visual.

A demonstration of this effect is shown in the example below. Initially, the offset element is not transformed. You may try resizing your window to see the overflow and then toggle the transformation with the button in the center.

document.getElementById('toggle').addEventListener('click', function(event) {
  const blocks = document.querySelectorAll('.block.wide');
  for(let i=0;i<blocks.length;i++) {
    const block = blocks[i];
      block.classList.toggle('transform');
    }
});
html, body {
  background: #ddd;
}

.container {
  background: white;
  max-width: 1152px;
  margin: 0 auto;
}

.content {
  border: 1px solid grey;
}

.block.wide {
  background: yellow;
  max-width: 1380px;
  width: 100vw;
  position: relative;
  left: 50%;
}

.block.wide.transform {
  transform: translateX(-50%);
}
<div class="container">
  <div class="content">
    <div class="block">
      <h1>Lorem ipsum dolor sit amet</h1>
      <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
      <p><strong>Click the button below to toggle the transform and see the overflow vanish</strong></p>
      <button id="toggle">Toggle Transform</button>
  </div>
    <div class="block wide">
      <h1>Lorem ipsum dolor sit amet</h1>
      <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
  </div>
</div>

Is this the intended behavior according to the specifications? How do offsets and transformations interact?

In all my test cases, the CSS transform achieves the desired result. However, I feel that I am relying on luck rather than a technical specification.

qsi
  • 683
  • 1
  • 7
  • 16

1 Answers1

2

There's several points to cover here.

From the CSS Transforms spec, Section 3. The Transform Rendering Model says:

For elements whose layout is governed by the CSS box model, the transform property does not affect the flow of the content surrounding the transformed element. However, the extent of the overflow area takes into account transformed elements. This behavior is similar to what happens when elements are offset via relative positioning. Therefore, if the value of the overflow property is scroll or auto, scrollbars will appear as needed to see content that is transformed outside the visible area. Specifically, transforms can extend (but do not shrink) the size of the overflow area, which is computed as the union of the bounds of the elements before and after the application of transforms.

Which means transforms are supposed to affect the overflow and scrolling. However, in your first example, the overflow is to a negative coordinate space, and that overflow is always clipped, so it doesn't generate any new scrollbars.

But your second example, on a direct reading, seems to be in contradiction to the specification, with the transform shrinking the overflow area. What I think is happening here is that position relative shifts, and transforms are, as acknowledged by the quote above, very similar operations, and the transform is undoing the effect of the relative positioning.

In other words, the overflow area is being computed as the union of the bounds of the elements before and after the application of relative positioning and transforms.

Alohci
  • 78,296
  • 16
  • 112
  • 156
  • Thank you for your contribution, @alohci. Your explanation sounds reasonable and I can imagine that this is indeed what is happening. I have only recently started questioning the appropriateness of my solution to include "wide content" as it is not clear from the technical specification whether I am relying on a specified and defined behavior. In order to achieve the desired result outlined in example two, would you rely on translating the content or do you believe I should consider alternative approaches? – qsi Mar 20 '21 at 15:17