blur() всё кроме элемента

317
20 апреля 2022, 00:40

Есть к примеру готовый шаблон сайта с кнопками, ссылками, текстом, скажем такой c css.

Можно ли методами ванильного css, js, jquery при наведении на центральную кнопку заблюрить всё, кроме неё?

Все мои попытки блюрят задние div и из-за этого идёт блюр на кнопку по цепочке. Как вариант вынести кнопку в отдельный div вне всего сайта, но её положение должно зависеть от div`ов сайта.

Примерно нашёл как делать через scss, но я им не умею ещё пользоваться, и менять стиль всего css, ради одного эффекта мне кажется не эффективным. То есть цель: Наложить blur на весь сайт, кроме выбранного элемента при наведении на него. Спасибо.

Как пробовал блюрить через jquery:

$('.container__body_middle_middle').on('mouseover', function() {
  $(this).parents('div').not(this).css({
    "filter": "blur(10px)"
  });
}).on('mouseleave', function() {
  $(this).parents('div').css({
    "filter": "blur(0px)"
  });
});
* {
  margin: 0px;
  padding: 0px;
}
body {
  background-color: #FFDEE9;
  background-image: linear-gradient(0deg, #FFDEE9 0%, #B5FFFC 100%);
}
.container {
  width: 100%;
  height: 100vh;
  display: grid;
  grid-template-columns: auto 1fr auto;
  grid-template-rows: auto 1fr auto;
  grid-template-areas: "header   header   header" "left     middle     right" "footer   footer   footer";
  grid-gap: 2px 10px;
}
.container>* {
  display: flex;
  flex-direction: column;
  align-items: center;
}
.container__header {
  grid-area: header;
}
.container__footer {
  grid-area: footer;
}
.container__body_left {
  min-width: 100px;
  grid-area: left;
}
.container__body_right {
  min-width: 100px;
  grid-area: right;
}
.container__body_middle {
  grid-area: middle;
  display: grid;
  grid-template-columns: 1fr;
  grid-template-rows: auto 1fr auto;
  grid-row-gap: 10px;
}
.container__body_middle>* {
  display: flex;
  flex-direction: column;
  align-items: center;
}
.btn_middle {
  width: 200px;
  height: 200px;
  outline: none;
}
.surprise {
  position: absolute;
  top: 30%;
  padding-left: 30px;
}
<pre>
  <body>
    <div class="container">
      <div class="container__header border border-secondary rounded">
        <h1>header</h1>
      </div>
      <div class="container__body_middle border border-secondary rounded">
        <div class="surprise">
          <p>SECRET</p>
        </div>
        <div class="container__body_middle_header">
          <h1>НАЖМИ КНОПКУ</h1>
        </div>
        <div class="container__body_middle_middle">
          <button type="button" name="button"class="btn_middle btn btn-danger">кнопка</button>
        </div>
        <div class="container__body_middle_footer">
          <h1>просто текст</h1>
        </div>
      </div>
      <div class="container__body_left border border-secondary rounded">
        <!-- <h1>left</h1> -->
      </div>
      <div class="container__body_right border border-secondary rounded">
        <!-- <h1>right</h1> -->
      </div>
      <div class="container__footer border border-secondary rounded">
        <h1>footer</h1>
      </div>
    </div>
    <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js" integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN" crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js" integrity="sha384-B4gt1jrGC7Jh4AgTPSdUtOBvfO8shuf57BaghqFfPlYxofvL8/KUEfYiJOMMV+rV" crossorigin="anonymous"></script>
    <script src="/js/hover_blur.js"></script>  
  </body>
</pre>

Answer 1

Так, если родитель получает filter, все его вложенные элементы получают такой же. Нужно научиться как-то временно выносить кнопку за пределы его родителей, а оставшимся элементам дать blur. Но добавлять filter абсолютно всем элементам на странице - такая себе идея.

Добавить в CSS:

body.blur-all > * {
  /* Все элементы непосредственно внутри body.blur-all
     (1-го уровня вложенности, но не глубже) получат этот стиль */
  filter: blur(10px);
}
body.blur-all > .no-blur {
  /* Кроме элемента .no-blur — класс заранее будет добавлен на кнопку */
  filter: blur(0);
  position: absolute;
  z-index: 9999;
}

При наведении, временно перенести кнопку прямо под body, а body дать класс blur-all.

var $parent = $('.container__body_middle_middle');
            // Надо помнить, куда возвращать кнопку
var $btn = $parent.find("button");
var $clone = $btn.clone().hide();
$parent.append( $clone );
// Добавляется такая же, но скрытая копия.
// Чтобы забирая оттуда кнопку к body, временно показать копию - на всякий случай,
// чтобы остальные элементы не съехали.
$btn.addClass("no-blur");
$btn.on('mouseover', function() {
  var $this = $(this);
  $this.css({
    left: $this.position().left + "px",
    top: $this.position().top + "px",
  });
  $clone.show();
  $("body").addClass("blur-all").append($this);
  // Кнопка переносится в body
});
$btn.on('mouseleave', function() {
  var $this = $(this);
  $this.css({ left: "", top: "" });
  $clone.hide();
  $parent.append($this); // Кнопка возвращается на место.
  $("body").removeClass("blur-all");
});
/***/
$btn.on("click", function _test() {
  console.clear(); console.log("Та же самая кнопка, обработчики остались");
});
body.blur-all > * {
  filter: blur(10px);
}
body.blur-all .no-blur {
  filter: blur(0);
  position: absolute;
  z-index: 9999;
}

/****/
* {
  margin: 0px;
  padding: 0px;
}
body {
  background-color: #FFDEE9;
  background-image: linear-gradient(0deg, #FFDEE9 0%, #B5FFFC 100%);
}
.container {
  width: 100%;
  height: 100vh;
  display: grid;
  grid-template-columns: auto 1fr auto;
  grid-template-rows: auto 1fr auto;
  grid-template-areas: "header   header   header" "left     middle     right" "footer   footer   footer";
  grid-gap: 2px 10px;
}
.container>* {
  display: flex;
  flex-direction: column;
  align-items: center;
}
.container__header {
  grid-area: header;
}
.container__footer {
  grid-area: footer;
}
.container__body_left {
  min-width: 100px;
  grid-area: left;
}
.container__body_right {
  min-width: 100px;
  grid-area: right;
}
.container__body_middle {
  grid-area: middle;
  display: grid;
  grid-template-columns: 1fr;
  grid-template-rows: auto 1fr auto;
  grid-row-gap: 10px;
}
.container__body_middle>* {
  display: flex;
  flex-direction: column;
  align-items: center;
}
.btn_middle {
  width: 200px;
  height: 200px;
  outline: none;
}
.surprise {
  position: absolute;
  top: 30%;
  padding-left: 30px;
}
<body>
  <div class="container">
    <div class="container__header border border-secondary rounded">
      <h1>header</h1>
    </div>
    <div class="container__body_middle border border-secondary rounded">
      <div class="surprise">
        <p>SECRET</p>
      </div>
      <div class="container__body_middle_header">
        <h1>НАЖМИ КНОПКУ</h1>
      </div>
      <div class="container__body_middle_middle">
        <button type="button" name="button" class="btn_middle btn btn-danger">кнопка</button>
      </div>
      <div class="container__body_middle_footer">
        <h1>просто текст</h1>
      </div>
    </div>
    <div class="container__body_left border border-secondary rounded">
      <!-- <h1>left</h1> -->
    </div>
    <div class="container__body_right border border-secondary rounded">
      <!-- <h1>right</h1> -->
    </div>
    <div class="container__footer border border-secondary rounded">
      <h1>footer</h1>
    </div>
  </div>
  <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
  <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js" integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN" crossorigin="anonymous"></script>
  <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js" integrity="sha384-B4gt1jrGC7Jh4AgTPSdUtOBvfO8shuf57BaghqFfPlYxofvL8/KUEfYiJOMMV+rV" crossorigin="anonymous"></script>
  <script src="/js/hover_blur.js"></script>
</body>

Предполагается, что такая кнопка одна (для нескольких - надо вычислять и клонировать всё в цикле), и у неё изначально нет своих top / left, иначе нужно будет их дополнительно запоминать во внешних переменных.

$this.position().left — это дело можно вычислять один раз, вне обработчика и сохранить в переменной. Но на всякий случай поставлен внутри - мало-ли, какие изменения будут происходить у кнопки.

Если это не кнопка, а какой-то сложный элемент со вложенностью, есть смысл вместо клонирования посчитать его высоту, ширину и позиционирование, и создать такой же, но пустой блок.

Answer 2

Оставлю для истории, может кому поможет. Спасибо Оптимусу за советы.

Добавил jquery код, который клонирует кнопку в body, даёт ей позицию оригинальной кнопки и просто show/hide в зависимости от наведения. Всем спасибо и успехов )

$(function () {
  var position = $(".btn_middle").offset();
  var clone = $('.btn_middle').clone().appendTo('body').offset({top: position.top, left: position.left}).hide();
  $('.btn_middle').on('mouseover',function() {
    $(clone).show();
    $(this).parents('div').css({'filter' : 'blur(10px)'});
    $(clone).on('mouseleave', function () {
      $('.btn_middle').parents('div').css({'filter' : 'blur(0px)'});
      $(clone).hide();
      });
  });
});
* {
  margin: 0px;
  padding: 0px;
}
body {
  background-color: #FFDEE9;
  background-image: linear-gradient(0deg, #FFDEE9 0%, #B5FFFC 100%);
}
.container {
  width: 100%;
  height: 100vh;
  display: grid;
  grid-template-columns: auto 1fr auto;
  grid-template-rows: auto 1fr auto;
  grid-template-areas: "header   header   header"
                       "left     middle     right"
                       "footer   footer   footer";
  grid-gap: 2px 10px;
}
.container > * {
  display: flex;
  flex-direction: column;
  align-items: center;
}
.container__header{
  grid-area: header;
}
.container__footer {
  grid-area: footer;
}
.container__body_left {
  min-width: 100px;
  grid-area: left;
}
.container__body_right {
  min-width: 100px;
  grid-area: right;
}
.container__body_middle {
  grid-area: middle;
  display: grid;
  grid-template-columns:1fr;
  grid-template-rows: auto 1fr auto;
  grid-row-gap: 10px;
}
.container__body_middle > * {
  display: flex;
  flex-direction: column;
  align-items: center;
}
.btn_middle{
  width: 200px;
  height: 200px;
  outline: none;
}
.surprise {
  position: absolute;
  top: 30%;
  padding-left: 30px;
}
.h1_flip{
 position: absolute;
 font-size: 90px;
}
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>ПРИДУМАТЬ</title>
    <link rel="stylesheet" href="css/style.css">
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z" crossorigin="anonymous">
    <title>Заголовок страницы</title>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
  </head>
  <body>
    <div class="container">
      <div class="container__header border border-secondary rounded">
        <h1>header</h1>
      </div>
      <div class="container__body_middle border border-secondary rounded">
        <div class="surprise">
          <p>SECRET</p>
        </div>
        <div class="container__body_middle_header">
          <div class="h1_flip h1_flip_1">
            <h1 class="">ЖМИ</h1>
          </div>
          <h1 class="h1_flip h1_flip_2">ЖМИ ЕЩЁ</h1>
          <!-- <h1 class="h1_flip h1_flip_1">НЕ ТРОГАЙ</h1> -->
        </div>
        <div class="container__body_middle_middle">
          <button type="button" name="button"class="btn_middle btn btn-danger">КНОПКА</button>
        </div>
        <div class="container__body_middle_footer">
          <h1>просто надпись</h1>
        </div>
      </div>
      <div class="container__body_left border border-secondary rounded">
        <!-- <h1>left</h1> -->
      </div>
      <div class="container__body_right border border-secondary rounded">
        <!-- <h1>right</h1> -->
      </div>
      <div class="container__footer border border-secondary rounded">
        <h1>footer</h1>
      </div>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js" integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN" crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js" integrity="sha384-B4gt1jrGC7Jh4AgTPSdUtOBvfO8shuf57BaghqFfPlYxofvL8/KUEfYiJOMMV+rV" crossorigin="anonymous"></script>
    <script src="/js/hover_blur.js"></script>
  </body>
</html>

READ ALSO
почему таймер не отключается предыдущий, когда включается новый? [дубликат]

почему таймер не отключается предыдущий, когда включается новый? [дубликат]

Таймер отключается только когда выходит время, а если нажать кнопку то запустится уже новый таймер, и предыдущий тоже будет работать

214