Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CSS Filter cancels element position [duplicate]

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

like image 704
vsync Avatar asked Feb 07 '23 17:02

vsync


2 Answers

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>
like image 142
Oriol Avatar answered Feb 09 '23 06:02

Oriol


body{ 
  -webkit-filter:blur(2px); 
  filter:blur(2px); 
  /* setting the viewport height on body */
  min-height: 100vh;
}

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

Setting the body to min-height of viewport seems to work.

like image 37
orangeh0g Avatar answered Feb 09 '23 06:02

orangeh0g