Как закрепить блок при прокрутке страницы

Закрепляем блоки при прокрутке страницы в пределах родительского блока

'1'

Пример на Codepen



Прежде чем начать, хотел бы обратить внимание, что у блога есть телеграм канал https://t.me/frontips, где можно узнавать о выходе новых статей и со временем будет появляться больше интересной и полезной информации.

Поддержите развитие блога и канала подпиской!

А теперь перейдём к теме статьи ;) Приятного чтения!



HTML-разметка примера

<div class="header">
  <div class="header__logo">Sticky</div>
</div>
<div class="sections">
  <div class="sticky">
    <div class="sticky__flex">
      <div class="sticky__half sticky__half_image">
        <div class="sticky__img"><img src="https://picsum.photos/1920/1080" alt=""/></div>
      </div>
      <div class="sticky__half">
        <div class="sticky__body">
          <div class="sticky__title">Lorem ipsum dolor sit amet, consectetur.</div>
          <div class="sticky__text">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Consequatur quos veritatis distinctio est ipsam repudiandae vel totam asperiores quas! Debitis quam voluptate fuga iure ut deleniti, illum laborum quaerat aut.</div>
        </div>
      </div>
    </div>
  </div>
  <div class="sticky">
    <div class="sticky__flex">
      <div class="sticky__half">
        <div class="sticky__body">
          <div class="sticky__title">Lorem ipsum dolor sit amet, consectetur.</div>
          <div class="sticky__text">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Consequatur quos veritatis distinctio est ipsam repudiandae vel totam asperiores quas! Debitis quam voluptate fuga iure ut deleniti, illum laborum quaerat aut. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Consequatur quos veritatis distinctio est ipsam repudiandae vel totam asperiores quas! Debitis quam voluptate fuga iure ut deleniti, illum laborum quaerat aut.</div>
        </div>
      </div>
      <div class="sticky__half sticky__half_image">
        <div class="sticky__img"><img src="https://picsum.photos/1920/1081" alt=""/></div>
      </div>
    </div>
  </div>
  <div class="sticky">
    <div class="sticky__flex">
      <div class="sticky__half sticky__half_image">
        <div class="sticky__img"><img src="https://picsum.photos/1920/1082" alt=""/></div>
      </div>
      <div class="sticky__half">
        <div class="sticky__body">
          <div class="sticky__title">Lorem ipsum dolor sit amet, consectetur.</div>
          <div class="sticky__text">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Consequatur quos veritatis distinctio est ipsam repudiandae vel totam asperiores quas! Debitis quam voluptate fuga iure ut deleniti, illum laborum quaerat aut.</div>
        </div>
      </div>
    </div>
  </div>
  <div class="sticky">
    <div class="sticky__flex">
      <div class="sticky__half">
        <div class="sticky__body">
          <div class="sticky__title">Lorem ipsum dolor sit amet, consectetur.</div>
          <div class="sticky__text">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Consequatur quos veritatis distinctio est ipsam repudiandae vel totam asperiores quas! Debitis quam voluptate fuga iure ut deleniti, illum laborum quaerat aut. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Consequatur quos veritatis distinctio est ipsam repudiandae vel totam asperiores quas! Debitis quam voluptate fuga iure ut deleniti, illum laborum quaerat aut. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Consequatur quos veritatis distinctio est ipsam repudiandae vel totam asperiores quas! Debitis quam voluptate fuga iure ut deleniti, illum laborum quaerat aut.</div>
        </div>
      </div>
      <div class="sticky__half sticky__half_image">
        <div class="sticky__img"><img src="https://picsum.photos/1920/1083" alt=""/></div>
      </div>
    </div>
  </div>
  <div class="sticky">
    <div class="sticky__flex">
      <div class="sticky__half">
        <div class="sticky__img sticky__half_image"><img src="https://picsum.photos/1920/1084" alt=""/></div>
      </div>
      <div class="sticky__half">
        <div class="sticky__body">
          <div class="sticky__title">Lorem ipsum dolor sit amet, consectetur.</div>
          <div class="sticky__text">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Consequatur quos veritatis distinctio est ipsam repudiandae vel totam asperiores quas! Debitis quam voluptate fuga iure ut deleniti, illum laborum quaerat aut.</div>
        </div>
      </div>
    </div>
  </div>
  <div class="sticky">
    <div class="sticky__flex">
      <div class="sticky__half">
        <div class="sticky__body">
          <div class="sticky__title">Lorem ipsum dolor sit amet, consectetur.</div>
          <div class="sticky__text">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Consequatur quos veritatis distinctio est ipsam repudiandae vel totam asperiores quas! Debitis quam voluptate fuga iure ut deleniti, illum laborum quaerat aut.</div>
        </div>
      </div>
      <div class="sticky__half sticky__half_image">
        <div class="sticky__img"><img src="https://picsum.photos/1920/1085" alt=""/></div>
      </div>
    </div>
  </div>
</div>

CSS стили примера

*,
*::before,
*::after {
  box-sizing: border-box;
}
body {
  margin: 0;
  padding: 0;
  font-family: 'Open Sans', sans-serif;
}
.header {
  position: -webkit-sticky;
  position: sticky;
  background: #fff;
  height: 100px;
  display: flex;
  text-transform: uppercase;
  align-items: center;
  justify-content: center;
  text-align: center;
  z-index: 99;
  top: 0;
  background: linear-gradient(90deg, #4facfe, #00f2fe);
}
.header__logo {
  letter-spacing: 15px;
  font-size: 48px;
  font-weight: 800;
  color: #fff;
}
.sticky {
  position: relative;
  z-index: 1;
}
.sticky:not(:last-child) .sticky__half {
  border-bottom: 0;
}
.sticky__flex {
  display: flex;
}
.sticky__half {
  width: 50%;
  min-height: 800px;
  border: 10px solid #000;
}
.sticky__half:nth-child(1) {
  border-right: 5px solid #000;
}
.sticky__half:nth-child(2) {
  border-left: 5px solid #000;
}
.sticky__img {
  width: 100%;
  height: 100%;
}
.sticky__img img {
  width: 100%;
  height: 100%;
  -o-object-fit: cover;
  object-fit: cover;
  display: block;
}
.sticky__body {
  padding: 60px;
  position: -webkit-sticky;
  position: sticky;
  top: 100px;
  border: 10px solid #00f2fe;
}
.sticky__title {
  font-weight: 800;
  font-size: 36px;
  margin-bottom: 30px;
  background: -webkit-linear-gradient(0deg, #4facfe, #00f2fe);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
}
.sticky__text {
  font-size: 18px;
}

@media (max-width: 767.98px) {
  .sticky__flex {
    flex-direction: column;
  }
  .sticky__half {
    min-height: auto;
    width: 100%;
  }
  .sticky__half_image {
    order: -1;
  }
}

Как работает position: sticky;

Блок со свойством position: sticky; при прокрутке страницы закрепляется относительно окна браузера опираясь на заданные значения top и/или left, при этом взаимодействует с другими элементами и закрепляется только тогда, когда родительский блок находится в отображаемом окне браузера и закрепленному элементу достаточно места в родительском блоке

Важно понять что для элемента с position: sticky; необходим родительский элемент, у которого будет свободное пространство для закрепленного элемента, если этого пространства нет, то блок со свойством position: sticky; будет вести себя как при position: static; установленном по-умолчанию для всех элементов

Еще раз для наглядности:

'1'

<div class="sticky">
  <div class="sticky__flex">
    <div class="sticky__half sticky__half_image">
      <div class="sticky__img"><img src="https://picsum.photos/1920/1080" alt=""/></div>
    </div>
    <div class="sticky__half">
      <div class="sticky__body">
        <div class="sticky__title">Lorem ipsum dolor sit amet, consectetur.</div>
        <div class="sticky__text">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Consequatur quos veritatis distinctio est ipsam repudiandae vel totam asperiores quas! Debitis quam voluptate fuga iure ut deleniti, illum laborum quaerat aut.</div>
      </div>
    </div>
  </div>
</div>
.sticky__half {
  width: 50%;
  min-height: 800px;
  border: 10px solid #000;
}
.sticky__body {
  padding: 60px;
  position: -webkit-sticky;
  position: sticky;
  top: 100px;
  border: 10px solid #00f2fe;
}
  1. Блоку <div class="sticky__body"> заданы свойства position: sticky; и top: 100px;
  2. Блок <div class="sticky__body"> находится в родительском блоке <div class="sticky__half">
  3. Высота блока <div class="sticky__body"> меньше высоты родительского блока <div class="sticky__half">

В итоге, при прокрутке страницы, как только блок <div class="sticky__body"> достигает расстояние 100px от верха окна браузера, закрепляется. Пока родительский блок <div class="sticky__half"> находится в пределах отображаемого окна браузера и блоку <div class="sticky__body"> достаточно места, он будет закреплен, как только места становится недостаточно, то блок открепляется от указанных 100px от верха окна браузера и прокручивается выше вместе с родительским блоком

Отличие от position: fixed;

При position: fixed; элемент никак не взаимодействует с другими элементами, он позиционируется относительно окна браузера отдельно от остальных элементов

Свойство position: fixed; полезно если элемент всегда должен находится в пределах окна браузера и не должен взаимодействовать с другими элементами, например, при верстке кнопки “Наверх” для возврата к началу страницы, которую обычно располагают справа внизу относительно окна браузера - она всегда видна и не затрагивает остальные элементы

Как закрепить шапку сайта

<body>
  <div class="header">
    <div class="header__logo">Sticky</div>
  </div>
</body>
.header {
  position: -webkit-sticky;
  position: sticky /* Закрепляем элемент */;
  top: 0 /* Указывем на каком расстоянии от верха браузера будет крепиться шапка сайта */;
}

Блоку <div class="header"> добавляем свойство position: sticky; и top: 0;. Родительским элемент для блока <div class="header"> является <body>, поэтому при прокрутке страницы блок <div class="header"> закрепляется к самому верху окна браузера, пока body будет оставаться в пределах отображаемого окна браузера, а так как <body> основной родительский элемент для всей страницы, то блок <div class="header"> будет всегда закреплен к верху окна браузера

Если будем закрелять шапку сайта свойством position: fixed;, то шапка сайта не будет взаимодействовать с другими элементами и следующие за шапкой элементы будут перекрыты шапкой или шапка будет перекрыта следующими элементами в зависимости от z-index.



Свойство position: sticky; поддерживается во всех браузерах, кроме Internet Explorer. В Internet Explorer верстка не ломается, просто элементы остаются по умолчанию position: static; и будут прокручиваться не закрепляясь, поэтому можно использовать данный прием в проектах.

Ссылка на документацию по position - MDN web docs



Изображения - https://picsum.photos/



Друзья, стараюсь для вас, поддержите проект!

Подписывайтесь, впереди много всего интересного и полезного ;)

Telegram - https://t.me/frontips

VK - https://vk.com/frontips