Как сделать так, чтобы элемент с абсолютным расположением заканчивался непосредственно перед другим элементом при изменении ширины экрана?

#css #flexbox #position #styling #shrink

#css #flexbox #положение #стиль #сжать

Вопрос:

Давайте предположим, что у нас есть «родительский» блок, который состоит из большого количества элементов, включая кнопку. Нажав эту кнопку, пользователь должен увидеть элемент «слайд», который будет закрывать родительский блок не на всю ширину, а только до самой кнопки (блоки 1 и 2, как вы увидите на ручке). Таким образом, слайд должен всегда заканчиваться непосредственно перед кнопкой. Даже при изменении ширины экрана. Как это можно реализовать?

Смотрите на 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. Поскольку вы хотите, чтобы ваш div покрывал 2 других div, и один из них имел динамическую ширину с помощью flex, я бы рекомендовал решение с помощью JS. Будет ли это проблемой?

Ответ №1:

Вы можете добиться этого с помощью немного Javascript, применяя стили CSS. Чтобы открыть слайд, вы увеличиваете его на вычисленную величину; чтобы закрыть, вы просто уменьшаете его до исходного размера.

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

Я не думаю, что существует чистое CSS-решение, поскольку вам нужно вычислить положение кнопки, но, конечно, я могу ошибаться!

 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>