Blur the edges of a backdrop-filter element with CSS

喜你入骨 提交于 2021-02-10 16:20:55

问题


document.querySelector( 'style' ).innerHTML += `
  div {
    width: 40rem;
    height: 1rem;
    background-color: #444;
  }
  .earth_orbit, .moon {
    width: 15rem;
    margin-left: 100%;
    background-color: #222;;
  }
  .earth_orbit::before {
    width: 5rem;
    height: 5rem;
    background-color: #08f;
  }
  .moon {
    width: 2.5rem;
    height: 2.5rem;
    background-color: #ddd;
  }
  section {
    right: 5%;
    width: 37.5%;
    height: 50%;
    font-size: 5rem;
    font-weight: bold;
    text-align: center;
    backdrop-filter: blur( 2rem );
    -webkit-backdrop-filter: blur( 2rem );
    /* filter: blur( 1rem ); */ /* Only blur inside element, ignoring the paremter */
  }
`;
*, * ::before, * ::after {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}
html, body, main {
  overflow: hidden;
  height: 100%;
  background-color: #111;
  color: #eee;
}
html {
  font-family: Arial;
  font-size: 1.5vmin;
}
main, div, section {
  display: flex;
  justify-content: center;
  align-items: center;
}
div, div::before, section {
  position: absolute;
  z-index: auto;
  width: 10rem;
  height: 10rem;
  background-color: #f90;
  border-radius: 5rem;
  content: '';
}
.moon::before {
  display: none;
}
<style>
  .sun_orbit, .earth_orbit, section {
    background-color: transparent;
  }
  span {
    color: #ccc;
    font-size: 4rem;
  }
  .rotate {
    animation-name: rotate;
    animation-duration: 4s;
    animation-timing-function: linear;
    animation-iteration-count: infinite;
  }
  @keyframes rotate {
    0% { transform: rotate( 0deg ); }
    100% { transform: rotate( 360deg ); }
  }
  .offset {
    animation-duration: 1s;
  }
</style>
<main>
  <div class='sun_orbit rotate'>
    <div class='earth_orbit rotate offset'>
      <div class='moon'></div>
    </div>
  </div>
  <section>
    <p>blurred overlay<br><span>( backdrop-filter )</span></p>
  </section>
</main>

Where the CSS property backdrop-filter is used there are always sharp edges along the elements border. However to blur the edges themselves along with all content underneath is the desired result. setting filter: blur( *value* ) on the target element doesn't seem to do the trick in any browser i've tested.

There's this question asked over a year ago with no answer and perhaps not as clear an example of what is trying to be accomplished here. Every time the 'planets' go behind the blurred div you can see a clear edge of where the div begins and ends - like crisp glass. I'd like to find a way to maintain all the effects here but blur that edge or border along the 'glass' or backdropped overlay.


回答1:


The only work-around I found was faking backdrop-filter blur by duplicating all elements to be affected then creating a "window" overlapping the background positioned to it's exact location with a regular filter: blur( n ) applied.

document.querySelector( 'style' ).innerHTML += `
  .earth_orbit, .moon {
    width: 15rem;
    margin-left: 100%;
    background-color: #222;;
  }
  .earth_orbit::before {
    width: 5rem;
    height: 5rem;
    background-color: #08f;
  }
  .moon::before {
    display: none;
  }
  .moon {
    width: 2.5rem;
    height: 2.5rem;
    background-color: #ddd;
  }
  .sun_orbit, .earth_orbit {
    background-color: transparent;
  }
  footer {
    right: 5%;
    width: 20rem;
    height: 20rem;
    background-color: transparent;
  }
  .rotate {
    animation-name: rotate; animation-duration: 4s;
    animation-timing-function: linear; animation-iteration-count: infinite;
  }    
`;
*, * ::before, * ::after {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}
html, body, main {
  overflow: hidden;
  height: 100%;
  background-color: #111;
  color: #eee;
}
html {
  font-family: Arial;
  font-size: 1.5vmin;
}
main, div, footer {
  display: flex;
  justify-content: center;
  align-items: center;
}
div, div::before, footer {
  position: absolute;
  z-index: auto;
  width: 10rem;
  height: 10rem;
  background-color: #f90;
  border-radius: 5rem;
  content: '';
}
div {
  width: 40rem; height: 1rem;
  background-color: #444;
}
<style>
  footer .sun_orbit { top: 9.5rem; left: -13.25vmax; }
  section { width: 70%; height: 70%; }
  p { 
    position: relative; z-index: 10; font-size: 2rem; left: 30vh;
  }
  footer {
    overflow: hidden; background-color: #111;
    z-index: 10; filter: blur( 1rem ); left: 54.5vmax;
  }  
  @keyframes rotate {
    0% { transform: rotate( 0deg ); } 
    100% { transform: rotate( 360deg ); }
  } 
  .offset { animation-duration: 1s; }  
</style>
<main>
  <div class='sun_orbit rotate'>
    <div class='earth_orbit rotate offset'>
      <div class='moon'></div>
    </div>
  </div>
  <footer>
    <section>
      <div class='sun_orbit rotate'>
        <div class='earth_orbit rotate offset'>
          <div class='moon'></div>
        </div>
      </div>
    </section>
  </footer>
  <p>backdrop overlay<br>with faded edges</p>
</main>

Added benefit is this whole effect now works in Firefox when at first it didn't. Also: This could be made responsive if so desired.



来源:https://stackoverflow.com/questions/65015751/blur-the-edges-of-a-backdrop-filter-element-with-css

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!