3

I have a CSS animation effect that's difficult to implement due to layering problems. See the snippet below:

var toggle = document.getElementById('toggle');

function toggleF() {
  'use strict';
  document.querySelector('nav').classList.add('fuzzyState');
}

toggle.addEventListener('click', toggleF);
body {
  height: 90%;
  color: #222;
  text-align: center overflow:hidden;
}

button {
  outline: 0;
  cursor: pointer
}

#toggle {
  float: left;
  width: 38px;
  height: 38px;
  padding: 5px;
  margin: auto;
  background: #fff;
  color: #666;
  border: 0;
  font-size: 150%
}

#toggle:hover {
  background: #222;
  color: #eee;
  user-select: none;
  -webkit-user-select: none
}

#toggle:active {
  background: #022;
  color: #fff
}

nav ul:after {
  content"";
  display: block;
  clear: both
}

nav ul {
  height: 150px;
  margin: 0;
  padding: 0;
  font-size: 150%
}

nav li {
  width: 140px;
  height: 140px;
  margin: 5px;
  float: left;
  list-style: none;
  user-select: none;
  -webkit-user-select: none
}

nav button {
  display: block;
  position: relative;
  top: 50%;
  width: 100%;
  height: 100%;
  background: transparent;
  border: 0;
  text-transform: uppercase;
  transform: translateY(-50%)
}

nav button:hover {
  background: #022;
  color: #eee
}

nav button:active {
  background: #033;
  color: #fff
}

ul hr {
  position: relative;
  top: 50%;
  width: 1px;
  height: 90px;
  margin: 10px;
  background: #eee;
  border: 0;
  float: left;
  transform: translateY(-50%);
  z-index: 2
}

nav.fuzzyState #dos {
  transform: translateX(230px)
}

nav.fuzzyState #uno {
  transform: translateX(400px);
  -webkit-filter: blur(1px)
}

nav.fuzzyState #tres {
  /*transform:translateX(-230px)*/
}

nav #tres {
  position: relative;
  z-index: 1
}

#leftNavMask {
  background: #fff;
  position: absolute;
  top: 15%;
  right: 0;
  left: 356px;
  width: 200px;
  height: 190px;
  text-align: justify;
  transform: translateY(-50%);
}

#rightNavMask {
  background: #fff;
  position: absolute;
  top: 15%;
  right: 0;
  left: 156px;
  width: 200px;
  height: 190px;
  text-align: justify;
  transform: translateY(-50%);
  z-index: -1
}

#dos,
#tres {
  transition: transform 0.7s ease-in-out
}

#uno {
  transition: transform 1s ease-in-out, -webkit-filter 1s ease-in-out;
}
<button id="toggle">+</button>
<nav>
  <ul>
    <li id="uno"><button>uno</button></li>
    <li id="dos"><button>dos</button></li>
    <hr>
    <li id="tres"><button>tres</button></li>

    <div id="leftNavMask"></div>
    <div id="rightNavMask"></div>
  </ul>
</nav>

After the + button is clicked my goal is to make the tres button slide to the left while being masked just like the uno and dos buttons, except in the opposite direction. It seems impossible to pull off because whatever z-index I give any elements there's no way to have the left mask on top of the correct elements while simultaneously having the right mask do its job. Are there any simple ways to do this without jQuery? Thanks.

To clarify: The uno and dos buttons are currently going under a div that is colored to match the background. I need the tres button to slide left under a second div that is somehow on top of the tres button to mask it but also below the uno and dos buttons so they aren't blocked at the beginning.

ElChiniNet
  • 2,778
  • 2
  • 19
  • 27
Lynel Hudson
  • 2,335
  • 1
  • 18
  • 34
  • So 1 and 2 are acting correct, but you want 3 to slide to the left behind that line? – Leeish Apr 29 '16 at 20:25
  • 1
    @Leeish, Precisely. If you uncomment the code in my CSS for `nav.fuzzyState #tres` you'll be able to see what happens. #3 just over laps the other divs. – Lynel Hudson Apr 29 '16 at 20:26
  • I don't think it can be done but I'm up voting to see if someone can. The stacking order you want with z-index is impossible. You could probably do some crazy timing with javascript but I'll be interested in seeing if someone can pull it off without JS. – Leeish Apr 29 '16 at 20:28
  • 1
    @Leeish looks like we have a winner. – Lynel Hudson Apr 29 '16 at 22:54
  • Duh. I was stuck trying to use stacking like you. Overflow works fine. – Leeish May 02 '16 at 14:42

1 Answers1

0

Long time since this question was asked, therefore, most probably you have found a solution already. But just in case, here you have a possible approach to what you wanted to achieve.

Instead of using absolute positioned divs with the same color of the background to cover the animated li elements, why don't use an overflow hidden property in the ul container? If you do this, the ul will act as a "mask" and when the li elements get animated outside the ul, they will be automatically "hidden". Take a look at your snippet already modified using this approach (I have used two ul elements to animate the li elements separately):

I saw that you placed an hr (and two div) inside the ul element and a ul should only contain li elements. For this solution, I used a pseudo-element to mimic the vertical line.

var toggle = document.getElementById('toggle');

function toggleF() {
  document.querySelector('nav').classList.toggle('fuzzyState');
}

toggle.addEventListener('click', toggleF);
body {
  color: #222;
}

button {
  cursor: pointer;
  outline: 0;
}

#toggle {
  background: #fff;
  border: 0;
  color: #666;
  float: left;
  font-size: 150%;
  height: 38px;
  margin: auto;
  padding: 5px;
  width: 38px;
}

#toggle:hover {
  background: #222;
  color: #eee;
  user-select: none;
}

#toggle:active {
  background: #022;
  color: #fff
}

nav ul {
  display: inline-block;
  font-size: 150%;
  margin: 0;
  overflow: hidden;
  padding: 0;
  position: relative;
}

nav ul.left::after {
  content: "";
  display: block;
  border-right: 1px solid #eee;
  height: 90px;
  position: absolute;
  right: 0;
  top: 50%;
  transform: translateY(-50%);
}

nav li {
  display: inline-block;
  height: 140px;
  list-style: none;
  margin: 5px;
  user-select: none;
  transition: transform 0.7s ease-in-out;
  width: 140px;
}

nav button {
  background: transparent;
  border: 0;
  display: block;
  height: 100%;
  position: relative;
  text-transform: uppercase;
  top: 50%;
  transform: translateY(-50%);
  width: 100%;
}

nav button:hover {
  background: #022;
  color: #eee;
}

nav button:active {
  background: #033;
  color: #fff;
}

nav.fuzzyState ul > li {
  pointer-events: none;
}

nav.fuzzyState ul.left > li {
  transform: translateX(200%);
}

nav.fuzzyState ul.right > li {
  transform: translateX(-100%);
}
<button id="toggle">+</button>
<nav>
  <ul class="left">
    <li><button>uno</button></li>
    <li><button>dos</button></li>
  </ul>
  <ul class="right">
    <li><button>tres</button></li>
  </ul>
</nav>
ElChiniNet
  • 2,778
  • 2
  • 19
  • 27