Search code examples
cssfirefoxposition

CSS Filter cancels element position


Demo page

body {
  -webkit-filter: blur(2px);
  filter: blur(2px);
}

div {
  background: blue;
  margin: auto;
  position: absolute;
  right: 0;
  top: 50%;  /*  <---- ignored */
  left: 0;
  height: 200px;
  width: 200px;
  transform: translateY(-50%);
}
<div></div>

Giving filter:blur(1px) (or any other filter) to a parent of a positioned element makes the browser ignore the child's position.

Has anyone encountered that and know a way to fix this annoyance?


Tested on FF48 beta / win7


Solution

  • That's because absolutely positioned elements are positioned relatively to their containing block, which is established by their nearest positioned ancestor, or the initial containing block if there is no such ancestor.

    Then, if you don't use filter, the containing block will be the initial one, which has the same dimensions as the viewport.

    However, if you use filter on body, that will establish a containing block, even for absolutely positioned descendants. It will be like if you used position: relative.

    body {
      position: relative;
    }
    div {
      background: blue;
      margin: auto;
      position: absolute;
      right: 0;
      top: 50%;
      left: 0;
      height: 200px;
      width: 200px;
      transform: translateY(-50%);
    }
    <div></div>

    Instead, I recommend setting the filter on html, and use height: 100% to make it as tall as the viewport.

    html {
      height: 100%;
      -webkit-filter: blur(2px);
      filter: blur(2px);
    }
    div {
      background: blue;
      margin: auto;
      position: absolute;
      right: 0;
      top: 50%;
      left: 0;
      height: 200px;
      width: 200px;
      transform: translateY(-50%);
    }
    <div></div>