Липкий элемент поверх других элементов, не выходя из контейнера

#html #css #sticky

#HTML #css #липкий

Вопрос:

У меня есть сайт, на котором мне нужно сделать так, чтобы при прокрутке страницы вниз телефон оставался на месте, в центре, а содержимое телефона менялось местами при прокрутке, пока вы не дойдете до определенной точки (например, нижнего колонтитула). Проблема, с которой я сталкиваюсь, заключается в том, что он остается в области прокрутки, поскольку единственный способ, которым я мог понять, как его наложить, — это position: absolute . Однако добавление этого означает, что он больше не «липкий» внутри контейнера. Он выскакивает.

Вот пример (вы можете запустить демонстрацию ниже): https://codepen.io/oscargodson/pen/OJXJGRL

Скриншоты:

Загрузка страницы

введите описание изображения здесь

Прокрутка вниз (обратите внимание, что он все еще центрируется и накладывается поверх всего остального)

введите описание изображения здесь

Зеленая граница — это контейнер / родительский элемент желтого квадрата (изображение телефона в реальной жизни). Обратите внимание, как это получается.

введите описание изображения здесь

Я бы действительно предпочел не использовать JS, если это вообще возможно, но если это единственный способ, все в порядке.

 .panel-wrapper {
  border: 5px solid chartreuse;
  position: relative;
}

.panel {
  height: 100vh;
}

.panel-1 { background: aqua; }
.panel-2 { background: blue; }
.panel-3 { background: darkblue; }

.sticky-wrapper {
  width: 100%;
  position: sticky;
  background: transparent;
  top: calc(100vh/2 - 613px/2);
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
  z-index: 3;
}

.sticky-element {
  width: 315px;
  height: 613px;
  background: yellow;
  position: absolute;
  top: 0;
}

footer {
  font-size: 100px;
  font-weight bold;
  text-align: center;
  padding: 250px 0;
  background: red;
}  
 <div class="outer-wrapper">
  <div class="panel-wrapper">
    <div class="sticky-wrapper">
      <div class="sticky-element"></div>
    </div>
    <div class="panel panel-1"></div>
    <div class="panel panel-2"></div>
    <div class="panel panel-3"></div>
  </div>
  <footer>
     Should not overlap here!
  </footer>
</div>  

Комментарии:

1. Если вы удалите position: absolute .sticky-element его, он не будет перекрываться. Если вы добавите a margin-bottom: calc(100vh/2 - 613px/2); к своему .sticky-wrapper , он может сделать то, что вы ожидаете.

2. @AmauryHanser из того, что я вижу, удаление absolute дает липкому элементу высоту, которая приводит к большой белой полосе вверху. Он сохраняет его внутри, но не накладывается на панели (afaik)

3. Положение использования: исправлено

4. @OscarGodson Я пропустил это, извините, тогда, может быть, вы можете сделать, как я сказал, но добавить float: left в .sticky-wrapper

5. @SteveTomlin позиция: исправлено будет работать именно так, как я не хочу, если я не понимаю? В основном он работает как position: исправлена проблема.

Ответ №1:

Удалите position:absolute и сделайте липкий контейнер float:left

 .panel-wrapper {
  border: 5px solid chartreuse;
  position: relative;
}

.panel {
  height: 100vh;
}

.panel-1 { background: aqua; }
.panel-2 { background: blue; }
.panel-3 { background: darkblue; }

.sticky-wrapper {
  width: 100%;
  position: sticky;
  background: transparent;
  top: calc(100vh/2 - 613px/2);
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
  z-index: 3;
  float:left; /* added */
}

.sticky-element {
  width: 315px;
  height: 613px;
  background: yellow;
  top: 0;
}

footer {
  font-size: 100px;
  font-weight bold;
  text-align: center;
  padding: 250px 0;
  background: red;
}  
 <div class="outer-wrapper">
  <div class="panel-wrapper">
    <div class="sticky-wrapper">
      <div class="sticky-element"></div>
    </div>
    <div class="panel panel-1"></div>
    <div class="panel panel-2"></div>
    <div class="panel panel-3"></div>
  </div>
  <footer>
     Should not overlap here!
  </footer>
</div>  

Если у вас будет контент, рассмотрите shape-outisde хитрость, чтобы вы также могли перекрывать текст:

 .panel-wrapper {
  border: 5px solid chartreuse;
  position: relative;
}

.panel {
  height: 100vh;
  font-size:10vh;
  color:#fff;
}

.panel-1 { background: aqua; }
.panel-2 { background: blue; }
.panel-3 { background: darkblue; }

.sticky-wrapper {
  width: 100%;
  position: sticky;
  background: transparent;
  top: calc(100vh/2 - 613px/2);
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
  z-index: 3;
  float:left; /* added */
  shape-outside:linear-gradient(transparent,transparent);
}

.sticky-element {
  width: 315px;
  height: 613px;
  background: yellow;
  top: 0;
}

footer {
  font-size: 100px;
  font-weight bold;
  text-align: center;
  padding: 250px 0;
  background: red;
}  
 <div class="outer-wrapper">
  <div class="panel-wrapper">
    <div class="sticky-wrapper">
      <div class="sticky-element"></div>
    </div>
    <div class="panel panel-1">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras in dignissim magna. Nulla magna lorem, mattis et ultricies euismod, posuere condimentum nulla. Pellentesque mollis, mauris quis elementum porttitor, arcu mauris aliquet metus, sed maximus sapien diam varius est. Aliquam erat volutpat.</div>
    <div class="panel panel-2">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras in dignissim magna. Nulla magna lorem, mattis et ultricies euismod, posuere condimentum nulla. Pellentesque mollis, mauris quis elementum porttitor, arcu mauris aliquet metus, sed maximus sapien diam varius est. Aliquam erat volutpat.</div>
    <div class="panel panel-3">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras in dignissim magna. Nulla magna lorem, mattis et ultricies euismod, posuere condimentum nulla. Pellentesque mollis, mauris quis elementum porttitor, arcu mauris aliquet metus, sed maximus sapien diam varius est. Aliquam erat volutpat.</div>
  </div>
  <footer>
     Should not overlap here!
  </footer>
</div>  

Комментарии:

1. это интересно, можете ли вы объяснить, как это работает? Я понимаю, почему абсолютная позиция создает проблемы, но то, как значение float влияет на подобное поведение, выходит за рамки моего понимания

2. @Warden330 float:left удалит элемент из потока, чтобы он мог перекрывать блочные элементы и не занимал места

3. Очень круто. Я не знал об этом. Это очень полезно во многих сценариях, спасибо 🙂

4. Он не работал в моем реальном случае использования, вернулся, и вы вставили форму-снаружи и бум, который работает! Опять же, то, что я раньше не слышал и не использовал. еще раз спасибо!!

5. @TemaniAfif похоже, это не работает в Chrome. Firefox и Safari это работает. Однако в Chrome содержимое фактически перемещается. Например, липкая оболочка перемещается влево, но занимает 100% ширины, и если я прокручиваю вправо, я вижу содержимое, которое должно быть ниже.

Ответ №2:

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

 footer {
  position: relative;
  z-index: 20; /* above z-index of sticky element*/
}
  

Или вы можете добавить немного javascript для определения положения прокрутки и, когда оно будет равно x снизу, т.Е. Высоте нижнего колонтитула, измените css на абсолютную позицию.

Комментарии:

1. Не будет ли тогда отключен желтый ящик / телефон? Не очень липкий и остается в контейнере?

2. @OscarGodson Да, вы правы, это отключит его. Вот почему решение javascript выше, возможно, лучше подходит для ваших нужд. Еще лучше, используйте javascript, чтобы просто добавить атрибут класса или данных к липкому элементу, как только он достигнет позиции прокрутки. Таким образом, вы сохраняете большую часть логики в css.