"Позиция: липкая;" не работает CSS и HTML

Я хочу, чтобы панель навигации прилипала к вершине, как только я ее прокручиваю, но она не работает, и я понятия не имею, почему. Если вы можете помочь, вот мой HTML и CSS код:

.nav-selections {
        text-transform: uppercase;
        letter-spacing: 5px;
        font: 18px "lato",sans-serif;
        display: inline-block;
        text-decoration: none;
        color: white;
        padding: 18px;
        float: right;
        margin-left: 50px;
        transition: 1.5s;
    }

        .nav-selections:hover{
            transition: 1.5s;
            color: black;
        }

    ul {
        background-color: #B79b58;
        overflow: auto;
    }

    li {
        list-style-type: none;
    }
<nav style="position: sticky; position: -webkit-sticky;">
        <ul align="left">
            <li><a href="#/contact" class="nav-selections" style="margin-right:35px;">Contact</a></li>
            <li><a href="#/about" class="nav-selections">About</a></li>
            <li><a href="#/products" class="nav-selections">Products</a></li>
            <li><a href="#" class="nav-selections">Home</a></li>
        </ul>
    </nav>

37 ответов

Решение

Липкое позиционирование - это гибрид относительного и фиксированного позиционирования. Элемент обрабатывается как относительное положение до тех пор, пока он не пересекает заданный порог, после чего он рассматривается как фиксированное положение.
...
Вы должны указать порог хотя бы с одним из top, right, bottom, или же left для липкого позиционирования, чтобы вести себя как ожидалось. В противном случае он будет неотличим от относительного позиционирования. [ источник: MDN ]

Так что в вашем примере вы должны определить позицию, в которой он должен держаться в конце, используя top имущество.

html, body {
  height: 200%;
}

nav {
  position: sticky;
  position: -webkit-sticky;
  top: 0; /* required */
}

.nav-selections {
  text-transform: uppercase;
  letter-spacing: 5px;
  font: 18px "lato", sans-serif;
  display: inline-block;
  text-decoration: none;
  color: white;
  padding: 18px;
  float: right;
  margin-left: 50px;
  transition: 1.5s;
}

.nav-selections:hover {
  transition: 1.5s;
  color: black;
}

ul {
  background-color: #B79b58;
  overflow: auto;
}

li {
  list-style-type: none;
}
<nav>
  <ul align="left">
    <li><a href="#/contact" class="nav-selections" style="margin-right:35px;">Contact</a></li>
    <li><a href="#/about" class="nav-selections">About</a></li>
    <li><a href="#/products" class="nav-selections">Products</a></li>
    <li><a href="#" class="nav-selections">Home</a></li>
  </ul>
</nav>

Проверьте, установлен ли переполнение для элемента-предка (например, overflow:hidden); попробуйте переключить это. Возможно, вам придется подняться на дерево DOM выше, чем вы ожидаете =).

Это может повлиять на ваш position:sticky на элементе-потомке.

У меня та же проблема, и я нашел ответ здесь.

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

В частности, ищите любое свойство переполнения, установленное на родительском объекте. Вы не можете использовать: overflow: hidden, overflow: scroll или же overflow: auto на родителя position: sticky элемент.

Если вы столкнулись с этим, и ваш стикер не работает - попробуйте настроить родителя на:

display: unset

Работал на меня

Еще несколько вещей, с которыми я столкнулся:

Когда ваш липкий элемент является компонентом (угловым и т. Д.)

  • Если сам "липкий" элемент является компонентом с пользовательским селектором элемента, таким как угловой компонент с именем <app-menu-bar> вам нужно будет добавить следующее в css компонента:

    :host { display: block; }   
    

    или же

    app-menu-bar  { display: block; }   // (in the containing component's css)
    

    Safari на iOS, в частности, кажется, требует display:block даже на корневой элемент app-root углового приложения или он не будет придерживаться.

  • Если вы создаете компонент и определяете CSS внутри компонента (теневой DOM / инкапсулированные стили), убедитесь, что position: sticky применяется к "внешнему" селектору (например, app-menu-bar в devtools должны показывать липкую позицию) а не верхний уровень div внутри компонента. С Angular это может быть достигнуто с помощью :host Селектор в CSS для вашего компонента.

    :host
    {
        position: sticky;
        display: block;   // this is the same as shown above
        top: 0;
        background: red;    
    }
    

Другой

  • Если элемент, следующий за вашим липким элементом, имеет сплошной фон, вы должны добавить следующее, чтобы он не скользил внизу:

    .sticky-element { z-index: 100; }
    .parent-of-sticky-element { position: relative; }
    
  • Ваш липкий элемент должен быть первым (перед вашим контентом), если вы используете top и после этого при использовании bottom,

  • Есть осложнения при использовании overflow: hidden на вашем элементе обертки - в общем, он убьет липкий элемент внутри. Лучше объяснил в этом вопросе

  • Убедитесь, что у вас есть:

    position: sticky;

    и не

    display: sticky;

Это продолжение ответов от MarsAndBack и Miftah Mizwar.

Их ответы верны. Тем не менее, трудно определить проблему предка (ей).

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

$('.your-sticky-element').parents().filter(function() {
    console.log($(this));
    console.log($(this).css('overflow'));
    return $(this).css('overflow') === 'hidden';
});

Там, где предка нет overflow: visible изменить его CSS, чтобы он сделал!

Также, как указано в другом месте, убедитесь, что ваш липкий элемент имеет это в CSS:

.your-sticky-element {
    position: sticky;
    top: 0;
}

Другой очень распространенный сценарий, когда position: sticky может не работать, если у его родителей display: flex или же display: grid.

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

Мне пришлось использовать следующий CSS, чтобы он заработал:

.parent {
    display: flex;
    justify-content: space-around;
    align-items: flex-start;
    overflow: visible;
}

.sticky {
    position: sticky;
    position: -webkit-sticky;
    top: 0;
}

Если вышеуказанная доза не сработает, тогда...

Пройдите через всех предков и убедитесь, что ни один из этих элементов не имеет overflow: hidden. Вы должны изменить это наoverflow: visible

Sticky Позиция не будет работать, если ваш родитель использует дисплей flex. Когда я читал это в одном решении

Поскольку элементы гибкого блока по умолчанию растягиваются, все элементы имеют одинаковую высоту, и их нельзя прокручивать.

Итак, если вы используете display: flex; на родительском элементе вам нужно будет добавить это в липкий элемент align-self: flex-start; а также установите высоту на авто height: auto;

Это класс липких элементов выглядит так

      .stick-ontop {
  position: -webkit-sticky !important; // for safari
  position: sticky !important;
  top: 0;
  align-self: flex-start;
  height: auto;
}

Атакуйте этот Q с другого направления.

Представьте, что это игра Find the nearest scrolling ancestor.

Похоже, что панель навигации, которую нужно прикрепить, не должна быть внутри какого-либо раздела или раздела с другим содержимым. Ни одно из решений не работало на меня, пока я не вынул панель навигации из div, который панель навигации совместно использовала с другой верхней панелью. У меня ранее были верхняя панель и панель навигации, обернутые общим div.

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

В overflow:hiddenответы покрывают 90% случаев. Это более или менее сценарий "липкой навигации".

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

Контейнер должен быть той высоты, в которой должен прокручиваться элемент. В моем сценарии с "правым столбцом" это высота левого столбца. Лучший способ добиться этого - использоватьdisplay:table-cellна колоннах. Если вы не можете и застряли сfloat:right и, как и я, вам нужно будет либо угадать высоту левого столбца, либо вычислить ее с помощью Javascript.

Просто чтобы добавить ко всем ответам на этой странице, если у вас возникли проблемы сposition: sticky не работает, то вы можете проверить следующее:

  1. Поддержка браузера
  2. Если порог указан — т.е.top,left,bottomилиright должно быть установлено значение, отличное отauto
  3. Префикс поставщика для Safari/iOS v13 и ниже — т.е.position: -webkit-sticky
  4. Родительский элемент с overflowсвойство должно иметь высоту
  5. Родительский элемент должен иметь указанную высоту (чтобы у липкого элемента была область для прокрутки внутри)
  6. Во флексбоксе измените align-selfзначение, если липкий имеет align-self: autoили align-self: stretchнабор

Написал сообщение в блоге для тех, кто хочет узнать больше.

Я знаю, что уже слишком поздно. Но я нашел решение, даже если вы используете overflow или display:flex в родительских элементах sticky будет работать.

шаги:

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

  2. Добавьте к родительскому элементу следующие стили:

    {позиция: абсолютная; высота: 100vmax; }

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

Это оно! Теперь он должен работать. С уважением

1. Прилипание позиции, скорее всего, не будет работать, если для любого из родительских элементов элемента установлено значение «Скрыть», «Прокрутка» или «Авто».

2. Прилипание позиции может работать некорректно, если какой-либо родительский элемент имеет заданную высоту.

Я знаю, что это старый пост. Но если есть кто-то вроде меня, который только недавно начал возиться с позицией: прилипать, это может быть полезно.

В моем случае я использовал position: sticky как элемент сетки. Это не работало, и проблема была в переполнении х: скрыто на html элемент. Как только я удалил это свойство, оно работало нормально. Имея переполнение-х: скрыто на body Элемент, казалось, работал, но понятия не имею, почему.

Забавный момент, который не был очевиден для меня: по крайней мере, в Chrome 70 position: sticky не применяется, если вы установили его с помощью DevTools.

Из моего комментария:

nav {
  position: sticky;
  top: 0;
}

.nav-selections {
  text-transform: uppercase;
  letter-spacing: 5px;
  font: 18px "lato", sans-serif;
  display: inline-block;
  text-decoration: none;
  color: white;
  padding: 18px;
  float: right;
  margin-left: 50px;
  transition: 1.5s;
}

.nav-selections:hover {
  transition: 1.5s;
  color: black;
}

ul {
  background-color: #B79b58;
  overflow: auto;
}

li {
  list-style-type: none;
}

body {
  height: 200vh;
}
<nav>
  <ul align="left">
    <li><a href="#/contact" class="nav-selections" style="margin-right:35px;">Contact</a></li>
    <li><a href="#/about" class="nav-selections">About</a></li>
    <li><a href="#/products" class="nav-selections">Products</a></li>
    <li><a href="#" class="nav-selections">Home</a></li>
  </ul>
</nav>

Существует полифилл для использования в других браузерах, кроме FF и Chrome . Это экспериментальные правила, которые могут быть реализованы или нет в любое время через браузеры. Хром добавить его пару лет назад, а затем уронил, кажется, обратно... но как долго?

Ближайшей будет позиция: относительные + координаты обновляются при прокрутке, как только она достигнет "липкой точки", если вы хотите превратить это в сценарий javascript

Просто добавляю свои два цента после того, как столкнулся с этой проблемой: я добавлял прикрепленную позицию к боковой панели с помощью гибкой оболочки.

  1. добавлениеposition: stickyнедостаточно: необходимоtopилиbottomсо значением, отличным отautoработать
  2. было недостаточно, раньше у меня был родительский элемент (ну, родительский элемент родительского элемента моей боковой панели, если быть более точным)
  3. position: sticky; top: 0;и устранение проблемныхoverflow: hiddenбыло недостаточно: моему гибкому контейнеру требовалсяalign-items: flex-start. В контексте гибкости имеет смысл, что гибкий элемент, который не расположен в верхней части своего родителя, не должен вести себя как липкий элемент.

Это просто краткое изложение всех остальных ответов.

  1. Удалить overflow собственность от body тег

  2. задавать height: 100% к body чтобы решить проблему с overflow-y: auto

min-height: 100% не работает вместо height: 100%

Если у какого-либо родителя/предка липкого элемента установлено любое из следующих свойств переполнения, позиция: липкий не будет работать (если вы не укажете высоту в переполненном контейнере):

  • переполнение: скрыто
  • переполнение: прокрутка
  • переполнение: авто

Фрагмент для проверки родительских элементов с набором свойств переполнения:

      let parent = document.querySelector('.sticky').parentElement;

while (parent) {
    const hasOverflow = getComputedStyle(parent).overflow;
    if (hasOverflow !== 'visible') {
        console.log(hasOverflow, parent);
    }
    parent = parent.parentElement;
}

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

Источник цитаты: https://www.designcite.com/web/tutorial/how-to-fix-issues-with-css-position-sticky-not-working .

Я считаю, что эта статья много говорит о том, какsticky работает

Как на самом деле работает CSS Position Sticky! Прикрепление позиции CSS состоит из двух основных частей: прикрепленного элемента и липкого контейнера.

Sticky Item  - это элемент, который мы определили с помощью стилей position: sticky. Элемент будет плавать, когда позиция области просмотра совпадает с определением позиции, например:top: 0px.

Прикрепленный контейнер - это HTML-элемент, который обертывает прикрепленный элемент. Это максимальная площадь, в которой может плавать липкий предмет.

Когда вы определяете элемент с помощью position: sticky, вы автоматически определяете родительский элемент как липкий контейнер!

Реальное поведение липкого элемента:

  • Сначала это относительно какое-то время
  • затем фиксируется на время
  • наконец, он исчезает из поля зрения

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

Элемент позиционируется в соответствии с обычным потоком документа, а затем смещается относительно его ближайшего предка с прокруткой и содержащего блока (ближайшего предка на уровне блока), включая элементы, связанные с таблицей, на основе значений top, right,bottom, и влево. Смещение не влияет на положение других элементов.

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

Этот пример поможет вам понять:

code https://codepen.io/darylljann/pen/PpjwPM

Используя стратегию из этого блога (https://www.designcise.com/web/tutorial/how-to-fix-issues-with-css-position-sticky-not-working), я придумал вариант для тех, кто не может контролировать все компоненты на странице

Я использую Angular и в методе ngOnInit запускаю этот код, чтобы изменить видимые свойства родителей на видимые.

/**
 * position: sticky
 * only works if all parent components are visibile
 */
let parent = document.querySelector('.sticky').parentElement;
while (parent) {
  const hasOverflow = getComputedStyle(parent).overflow;
  if (hasOverflow !== 'visible') {
    parent.style.overflow = 'visible';
    // console.log(hasOverflow, parent);
  }
  parent = parent.parentElement;
}

z-indexтоже очень важно. Иногда это сработает, но вы этого просто не увидите. На всякий случай попробуйте установить очень большое число. Также не всегда ставьтеtop: 0 но попробуйте что-нибудь повыше, если оно где-то спрятано (под панелью инструментов).

Watch out for empty grid areas!

In my case I had something like this:

      .cart-areas {
    grid-template-columns: 2fr 0.2fr 1.5fr;
    grid-template-areas:
      'order . summary'
      'order . .'
      'order . .';
}

I wanted that summary grid item to be sticky when the user completes the checkout form. It didn't work because of those empty grid items (marked with .).

The solution was to delete those empty items like so:

      .cart-areas {
    grid-template-columns: 2fr 0.2fr 1.5fr;
    grid-template-areas:
      'order . summary'
      'order . summary'
      'order . summary';
}

Вот что меня сбивало с толку... мой липкий div находился внутри другого div, так что родительскому div требовалось дополнительное содержимое ПОСЛЕ липкого div, чтобы родительский div был "достаточно высоким", чтобы липкий div мог "скользить" по другому содержимому, как вы прокручиваете вниз.

Поэтому в моем случае сразу после липкого div мне пришлось добавить:

    %div{style:"height:600px;"} 
      &nbsp;

(В моем приложении есть два расположенных бок о бок div с "высоким" изображением слева и короткой формой ввода данных справа, и я хотел, чтобы форма ввода данных перемещалась рядом с изображением при прокрутке вниз, так что форма всегда на экране. Это не сработает, пока я не добавлю вышеупомянутый "дополнительный контент", чтобы у липкого div было что "скользить"

У меня такая же проблема. Для меня проблема заключалась в отображении: «нет» на больших экранах (медиа-запрос) и отображении: «начальный» на смартфонах. Если я удалил свойство display css и добавил события непрозрачности и указателя none на рабочем столе, все сработало.

Если исправление danday74 не работает, проверьте, что родительский элемент имеет высоту.

В моем случае у меня было два ребенка, один плавающий влево и один плавающий вправо. Я хотел, чтобы правильный плавающий стал липким, но должен был добавить <div style="clear: both;"></div> в конце родителя, чтобы дать ему высоту.

Представьте, что вы хотите сохранитьoverflow: hiddenдля вашего предка и получить все вкусности от , то используйтеcontainвзаменoverflow:

      contain: paint;

Иposition: stickyдолжен по-прежнему работать, как ожидалось

Другие вопросы по тегам