6

I'm having troubles with fixed positioning, css transformed container and Safari. I'm trying to display a dropdown list when I click an item, inside a modal. The modal bears a css transform. To make sure the dropdown list is always displayed over the modal, I position it as fixed (I calculate the left and top values using JS).

It works as expected in Chrome, Firefox and Opera, but Safari shows a strange behaviour. According to the W3C:

Any computed value other than none for the transform results in the creation of both a stacking context and a containing block. The object acts as a containing block for fixed positioned descendants.

So a fixed element inside a CSS transformed container should be positioned relatively to this container, instead of the viewport. But it seems that Safari does not behave like this. See this example :

$(document).ready(function() {
  $(".show-liste").click(function() {
    $(".liste").show();
  });
});
.modale {
  height: 50px;
  overflow-y: scroll;
  transform: translate(100px);
}

ul {
  position: fixed;
  left: 0px;
  top: 0px;
}



/* --- Purely style related stuff ---- */

body {
  font-size: 80%;
}
.modale {
  position: absolute;
  top: 50px;
  padding: 60px;
  background-color: white;
  border: 1px solid #ccc;
  box-shadow: 2px 2px 2px #ddd;
}
button {
  width: 200px;
}
ul {
  list-style-type: none;
  margin-top: 0;
  padding-left: 0;
  width: 200px;
  display: none;
  box-shadow: 2px 2px 2px #ddd;
}
li {
  background: white;
  padding: 10px 20px;
  border: 1px solid #eee;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div class="modale">
  <div class="row">
    <div>
      <button class="show-liste">Open dropdown</button>
      <ul class="liste">
        <li>Choice 1</li>
        <li>Choice 2</li>
        <li>Choice 3</li>
        <li>Choice 4</li>
        <li>Choice 5</li>
      </ul>
    </div>
  </div>
</div>

Do you have any idea how to fix this ? Any polyfill, any way to get round this issue ? USing absolute positionning is the solution I'd like to avoid, as it would imply moving the list at the document's body level, and then handling it's creation / destruction, attached model (I'm using AngularJS), events, etc. That's really my last resort.

Pierre-Adrien
  • 2,836
  • 29
  • 30
  • Something weird is happening with your code snippet. [Here's a jsFiddle of the same code](http://jsfiddle.net/mblase75/Loap9oc0/). – Blazemonger Dec 15 '14 at 15:59
  • It appears, [according to W3C](http://www.w3.org/wiki/CSS_absolute_and_fixed_positioning#Fixed_positioning), that `position:fixed` is supposed to always be relative to the browser viewport, not a containing element like `absolute` is. Firefox and Chrome are therefore deviating from the official spec, and Safari considers its behavior to be "correct." – Blazemonger Dec 15 '14 at 22:11
  • Well it was the case before CSS transform module indeed. Now CSS3 transformed items become the "containing block for fixed positioned descendants" (http://www.w3.org/TR/css3-transforms/#transform-property). – Pierre-Adrien Dec 16 '14 at 07:58
  • 1
    The CSS3 transforms are still a working draft, which might explain the inconsistency. Found [this answer](http://stackoverflow.com/a/15885486) that might help. – Blazemonger Dec 16 '14 at 14:00
  • Have you thought about using an iframe to get around this issue in Safari? – Blazemonger Dec 16 '14 at 14:06

1 Answers1

3

I believe you can get the desired cross-browser behavior by using position:absolute instead of position:fixed.

Blazemonger
  • 90,923
  • 26
  • 142
  • 180
  • Indeed I could. I was looking for other solutions, as the project I'm working on would imply much more work to use ``position: absolute`` to position the item (would need to copy the DOM node at the root level, taking care of its lifecycle, events, etc., which would led me to other issues). I totally forgot to mention that, I'll update my question. – Pierre-Adrien Dec 15 '14 at 20:52
  • You don't need to move the DOM node at all. Changing `fixed` to `absolute` positions the `.liste` absolutely *within the `.modale`* just like you wanted it to. – Blazemonger Dec 15 '14 at 21:13
  • I'm pretty sorry, my snippet was not accurate. I forgot to mention my modale window has a fixed height + ``overflow:scroll`` (which is why I need to use fixed or move the ``.liste`` to the document root if I want to position it using ``absolute``. I fixed my initial question once more. Sorry for this again ! – Pierre-Adrien Dec 15 '14 at 21:41