Home > Mobile >  Background filter for dropdown
Background filter for dropdown

Time:01-10

The dropdown opens when elements of navbar are hovered. I want the background picture in hero div as well as rest of the body below navbar to be blurred. I tried using backdrop filter but its working. I included backdrop filter in sub-menu class but it has no effect on the image below it. I tried overlay but not exactly sure how to use it.

nav {
  display: inline-flex;
  width: 100%;
}

.nav-list {
  display: flex;
  width: 100%;
  margin-top: .7rem;
  padding-left: 1.1rem;
}

.nav-list li {
  position: relative;
}

.nav-list>li>a {
  color: black;
  display: block;
  font-size: 1rem;
  padding: 1.3rem 1rem;
  text-transform: uppercase;
  transition: color 300ms;
}

.nav-list>li>a::after {
  content: "";
  position: absolute;
  background-color: #ff2a00;
  height: 3.6px;
  width: 0;
  left: 0;
  bottom: 0px;
  transition: 0.1s;
}

.nav-list>li>a:hover:after {
  width: 100%;
}

.sub-menu {
  display: flex;
  position: fixed;
  box-sizing: border-box;
  background-color: black;
  visibility: hidden;
  top: 6.5rem;
  left: 3rem;
  width: 82.5rem;
  height: 35rem;
}

.sub-menu a {
  position: relative;
  top: 2rem;
  color: white;
  font-size: 1.1rem;
  font-weight: 200;
  backdrop-filter: blur(5px);
  padding: 0 40px 0 40px;
}

.nav-list li:hover>.sub-menu {
  top: 6.5rem;
  visibility: visible;
  opacity: 1;
}

.hero>img {
  position: relative;
  top: 6.3rem;
  z-index:-1;
  left: 4.5rem;
}
<nav>
  <ul >
    <li>
      <a href="">Test 1</a>
      <ul >
        <li><a href="#">shirts</a> </li>
        <li><a href="#">Shorts</a></li>
      </ul>
    </li>
    <li>
      <a href="%">Test 2</a>
      <ul >
        <li><a href="#">shirts</a> </li>
      </ul>
    </li>
  </ul>
</nav>

<div >
  <img src="https://picsum.photos/200/300" alt="" style="height: 690px;width: 1300px;">
</div>

CodePudding user response:

Using javascript, you can delegate an event handler to body. Then add a blur class to the BODY if its a link under nav-list.

Then in CSS, just dictate what you want to blur like this:

.blur .hero{}

let _body = document.body;

_body.addEventListener("mouseover", (e) => {
  let el = e.target;
  if (el.closest(".nav-list")) {
    _body.classList.add("blur")
  } else {
    _body.classList.remove("blur")
  }
});
nav {
  display: inline-flex;
  width: 100%;
}

.nav-list {
  display: flex;
  width: 100%;
  margin-top: .7rem;
  padding-left: 1.1rem;
}

.nav-list li {
  position: relative;
}

.nav-list>li>a {
  color: black;
  display: block;
  font-size: 1rem;
  padding: 1.3rem 1rem;
  text-transform: uppercase;
  transition: color 300ms;
}

.nav-list>li>a::after {
  content: "";
  position: absolute;
  background-color: #ff2a00;
  height: 3.6px;
  width: 0;
  left: 0;
  bottom: 0px;
  transition: 0.1s;
}

.nav-list>li>a:hover:after {
  width: 100%;
}

.sub-menu {
  display: flex;
  position: fixed;
  box-sizing: border-box;
  background-color: black;
  visibility: hidden;
  top: 6.5rem;
  left: 3rem;
  width: 82.5rem;
  height: 35rem;
}

.sub-menu a {
  position: relative;
  top: 2rem;
  color: white;
  font-size: 1.1rem;
  font-weight: 200;
  backdrop-filter: blur(5px);
  padding: 0 40px 0 40px;
}

.nav-list li:hover>.sub-menu {
  top: 6.5rem;
  visibility: visible;
  opacity: 1;
}

.hero>img {
  position: relative;
  top: 6.3rem;
  z-index: -1;
  left: 4.5rem;
}

.blur .hero {
  filter: blur(10px)
}
<nav>
  <ul >
    <li>
      <a href="">Test 1</a>
      <ul >
        <li><a href="#">shirts</a> </li>
        <li><a href="#">Shorts</a></li>
      </ul>
    </li>
    <li>
      <a href="%">Test 2</a>
      <ul >
        <li><a href="#">shirts</a> </li>
      </ul>
    </li>
  </ul>
</nav>

<div >
  <img src="https://picsum.photos/200/300" alt="" style="height: 690px;width: 1300px;">
</div>

CodePudding user response:

The CSS way:

I think you are looking for a css ruleset like this:

nav:has(a:hover) ~ * {
  filter: blur(1.5rem);
}

Setting filter: blur(1.5rem); to the next siblings of the <nav> element when having an anchor on :hover.

But it's using :has() that is not still well supported (Firefox still missing).

https://developer.mozilla.org/en-US/docs/Web/CSS/:has

The functional :has() CSS pseudo-class represents an element if any of the relative selectors that are passed as an argument match at least one element when anchored against this element. This pseudo-class presents a way of selecting a parent element or a previous sibling element with respect to a reference element by taking a relative selector list as an argument.

The Javascript way:

Since via css there are some limits, you can decide to use js to listen for both the mouseover and the mouseleave events on each anchor in the .navbar that will toggle the blur class. Such class has a css rule like the one used before but with the .blur selector:

const toggleBlur = (event) => {
    document.querySelectorAll('nav ~ *')
    .forEach(el => el.classList.toggle('blur'));
};

const anchors = document.querySelectorAll('.nav-list li a');

anchors.forEach(anchor => anchor.addEventListener('mouseover', toggleBlur));
anchors.forEach(anchor => anchor.addEventListener('mouseleave', toggleBlur));

The demo:

Here the demo with your code and the addition explained above:

const toggleBlur = (event) => {
  document.querySelectorAll('nav ~ *')
    .forEach(el => el.classList.toggle('blur'));
};

const anchors = document.querySelectorAll('.nav-list li a');

anchors.forEach(anchor => anchor.addEventListener('mouseover', toggleBlur));
anchors.forEach(anchor => anchor.addEventListener('mouseleave', toggleBlur));
.blur,
ndav:has(a:hover) ~ * {
  filter: blur(1.5rem);
}

nav {
  display: inline-flex;
  width: 100%;
}

.nav-list {
  display: flex;
  width: 100%;
  margin-top: .7rem;
  padding-left: 1.1rem;
}

.nav-list li {
  position: relative;
}

.nav-list>li>a {
  color: black;
  display: block;
  font-size: 1rem;
  padding: 1.3rem 1rem;
  text-transform: uppercase;
  transition: color 300ms;
}

.nav-list>li>a::after {
  content: "";
  position: absolute;
  background-color: #ff2a00;
  height: 3.6px;
  width: 0;
  left: 0;
  bottom: 0px;
  transition: 0.1s;
}

.nav-list>li>a:hover:after {
  width: 100%;
}

.sub-menu {
  display: flex;
  position: fixed;
  box-sizing: border-box;
  background-color: black;
  visibility: hidden;
  top: 6.5rem;
  left: 3rem;
  width: 82.5rem;
  height: 35rem;
  z-index: 100;
}

.sub-menu a {
  position: relative;
  top: 2rem;
  color: white;
  font-size: 1.1rem;
  font-weight: 200;
  backdrop-filter: blur(5px);
  padding: 0 40px 0 40px;
}

.nav-list li:hover>.sub-menu {
  top: 6.5rem;
  visibility: visible;
  opacity: 1;
}

.hero>img {
  position: relative;
  top: 6.3rem;
  z-index:-1;
  left: 4.5rem;
}
<nav>
  <ul >
    <li>
      <a href="">Test 1</a>
      <ul >
        <li><a href="#">shirts</a> </li>
        <li><a href="#">Shorts</a></li>
      </ul>
    </li>
    <li>
      <a href="%">Test 2</a>
      <ul >
        <li><a href="#">shirts</a> </li>
      </ul>
    </li>
  </ul>
</nav>

<div >
  <img src="https://picsum.photos/200/300" alt="" style="height: 690px;width: 1300px;">
</div>



The demo:

I added a rule

  • Related