4

How can I apply filter: blur(20px) to a div with class todo, but not the div with class modal?

Is it possible, perhaps with the help of SCSS?

Code:

.todo {
  display: grid;
}

.modal {
  display: grid;
  position: fixed;
  width: 500px;
  height: 200px;
  top: 40%;
  left: 50%;
  transform: translate(-50%, -50%);
  background: #fafafa;
  box-shadow: 0 6px 30px rgba(0, 0, 0, 0.3);
  visibility: visible;
  opacity: 1;
}
<div class='todo'>
  <div class='todo__sidebar'>
    <ul>
      <li>item 1</li>
      <li>item 2</li>
    </ul>

    <div class='modal'>
      <span>12345</span>
    </div>
  </div>
</div>

Codepen

Daniel_Knights
  • 7,940
  • 4
  • 21
  • 49
brad_fresh
  • 129
  • 1
  • 11

3 Answers3

2

You could wrap the modal in a container and use backdrop-filter:

.todo {
  position: relative;
  display: grid;
}

.modal-container {
  display: flex;
  justify-content: center;
  align-items: center;
  position: fixed;
  top: 0;
  left: 0;
  backdrop-filter: blur(5px);
  height: 100vh;
  width: 100%;
}

.modal {
  display: grid;
  width: 500px;
  height: 200px;
  background: #fafafa;
  box-shadow: 0 6px 30px rgba(0, 0, 0, 0.3);
  visibility: visible;
  opacity: 1;
}
<div class='todo'>
  <div class='todo__sidebar'>
    <ul>
      <li>item 1</li>
      <li>item 2</li>
    </ul>

    <div class="modal-container">
      <div class='modal'>
        <span>12345</span>
      </div>
    </div>
  </div>
</div>

Though, the support is not great.


Another option is to use JS:

document.querySelector('ul').style.filter = 'blur(5px)';
.todo {
  display: grid;
}

.modal {
  display: grid;
  position: fixed;
  width: 500px;
  height: 200px;
  top: 40%;
  left: 50%;
  transform: translate(-50%, -50%);
  background: #fafafa;
  box-shadow: 0 6px 30px rgba(0, 0, 0, 0.3);
  visibility: visible;
  opacity: 1;
}
<div class='todo'>
  <div class='todo__sidebar'>
    <ul>
      <li>item 1</li>
      <li>item 2</li>
    </ul>
    <div class='modal'>
      <span>12345</span>
    </div>
  </div>
</div>

Or, you could swap them around in the HTML and use the sibling selector (~):

.todo {
  display: grid;
}

.modal {
  display: grid;
  position: fixed;
  width: 500px;
  height: 200px;
  top: 40%;
  left: 50%;
  transform: translate(-50%, -50%);
  background: #fafafa;
  box-shadow: 0 6px 30px rgba(0, 0, 0, 0.3);
  visibility: visible;
  opacity: 1;
  z-index: 1;
}

.modal ~ ul {
  filter: blur(5px);
}
<div class='todo'>
  <div class='todo__sidebar'>
    <div class='modal'>
      <span>12345</span>
    </div>

    <ul>
      <li>item 1</li>
      <li>item 2</li>
    </ul>
  </div>
</div>

None of these are ideal but just some options if you need them.

Daniel_Knights
  • 7,940
  • 4
  • 21
  • 49
0

You cannot "unblur" a child element of a blurred element.

Typically, rendering an element via CSS or SVG can conceptually be described as if the element, including its children, are drawn into a buffer (such as a raster image) and then that buffer is composited into the elements parent.

-- Filter Effect Module Level 1

* Emphasis mine.

You will need to apply filter only on the element you want blurred. Checkout anwsers in How to blur (css) div without blur child element and How to apply a CSS filter to a background image.

touchmarine
  • 1,548
  • 9
  • 11
0

You have to remove the div with class modal as a child of todo so that it is on top of that div. Here is the code that works:

.todo {
  display: grid;
  filter: blur(20px);
}
    
.modal {
  display: grid;
  z-index: 1000;
  position: fixed;
  width: 500px;
  height: 200px;
  top: 40%;
  left: 50%;
  transform: translate(-50%, -50%);
  background: #fafafa;
  box-shadow: 0 6px 30px rgba(0, 0, 0, 0.3);
  visibility: visible;
  opacity: 1;
}
<div class='todo'>
  <div class='todo__sidebar'>
    <ul>
      <li>item 1</li>
      <li>item 2</li>
    </ul>
  </div>
</div>
<div class='modal'>
     <span>12345</span>
</div>
Corné
  • 1,304
  • 3
  • 13
  • 32