How to make an absolute positioned element end just before the other element while changing the width of the screen?

441 views Asked by At

Let's assume we have a 'parent' block which consists of plenty of element including a button. By pressing this button the user should see a 'slide' element that will cover the parent block not the full width but only till the button inself(blocks 1 and 2 as you will see on the pen). So the slide should forever ends just before the button. Even when the width of the screen is changed. How could it be implemented?

See on Code Pen

<div class='parent'>
 <div class='first'>1</div>
 <div class='second'>2</div>
 <div class='btn'>Button</div>
 <div class='third'>3</div>

   <div class='slide'>
       Hello 
   </div>
</div>

 .parent {
    display: flex; 
}

 .first, .second, .third {
    padding: 30px;
}

 .first {
   background-color: salmon;
   flex-basis: 120px;
}

 .second {
   background-color: yellow;
   flex-grow: 1
}

.third {
   background-color: #56D7F7;
   flex-grow: 1
}

.btn {
   background-color: red;
   cursor: pointer;
}

.slide {
  position: absolute;
  left: 0
}
1

There are 1 answers

0
Richard Hunter On

You can achieve this with a bit of Javascript applying CSS styles. To open the slide, you scale it up by a calculated amount; to close, you just scale it back to its original size.

You might not want to scale the slide element since if there's any content in it, that will appear skewed a bit, but there's not too much work to change this solution to use translations instead.

I don't think there's a pure CSS solution since you have to calculate the position of the button, but of course I could be wrong!

let open = false;

slide.style.setProperty('transform-origin', 'left top');
slide.style.setProperty('transition', 'linear .4s all');

button.addEventListener('click', (event) => { 
  if (open) {
    slide.style.setProperty('transform', `scaleX(1)`);
    open = false;

  } else {
    const first = slide.offsetWidth;
    const last = button.offsetLeft;
    const scale = last / first;
    
    slide.style.setProperty('transform', `scaleX(${scale})`);

    open = true;
  }
})
.parent {
  display: flex;
  position: relative;
}

.first,
.second,
.third {
  padding: 30px;
}

.first {
  background-color: salmon;
  flex-basis: 120px;
}

.second {
  background-color: yellow;
  flex-grow: 1
}

.third {
  background-color: #56D7F7;
  flex-grow: 1
}

.btn {
  background-color: red;
  cursor: pointer;
}

.slide {
  position: absolute;
  background-color: green;
  width: 40px;
  left: 0;
  top: 0;
  bottom: 0;
}
<div class='parent'>
  <div class='first'>1</div>
  <div class='second'>2</div>
  <div id="button" class='btn'>Button</div>
  <div class='third'>3</div>

  <div id="slide" class='slide'>
    <div class='hello'>
    </div>
  </div>
</div>