Подтвердить что ты не робот

Событие, когда позиция: нажата кнопка

Я использую новый position: sticky (info), чтобы создать список контента, подобный iOS.

Он работает хорошо и намного превосходит предыдущий вариант JavaScript (пример), однако, насколько я знаю, ни одно событие не запускается, когда оно срабатывает, что означает, что я могу" t делать что-либо, когда панель попадает в верхнюю часть страницы, в отличие от предыдущего решения.

Я хотел бы добавить класс (например, stuck), когда элемент с position: sticky попадает в верхнюю часть страницы. Есть ли способ слушать это с помощью JavaScript? Использование jQuery в порядке.

Ниже приведена демонстрация нового position: sticky здесь.

4b9b3361

Ответ 1

Если кто-то попадет сюда через Google, один из его собственных инженеров найдет решение с использованием IntersectionObserver, пользовательских событий и часовых:

https://developers.google.com/web/updates/2017/09/sticky-headers

Ответ 2

В настоящее время нет собственного решения. См. Позиция таргетинга: липкие элементы, которые в настоящее время находятся в состоянии "застряли" . Однако у меня есть решение CoffeeScript, которое работает как с родным position: sticky, так и с полиполками, которые реализуют липкое поведение.

Добавьте "липкий" класс к элементам, которые вы хотите быть липкими:

.sticky {
  position: -webkit-sticky;
  position: -moz-sticky;
  position: -ms-sticky;
  position: -o-sticky;
  position: sticky;
  top: 0px;
  z-index: 1;
}

CoffeeScript для контроля "липких" позиций элементов и добавления "застрявшего" класса, когда они находятся в "липком" состоянии:

$ -> new StickyMonitor

class StickyMonitor

  SCROLL_ACTION_DELAY: 50

  constructor: ->
    $(window).scroll @scroll_handler if $('.sticky').length > 0

  scroll_handler: =>
    @scroll_timer ||= setTimeout(@scroll_handler_throttled, @SCROLL_ACTION_DELAY)

  scroll_handler_throttled: =>
    @scroll_timer = null
    @toggle_stuck_state_for_sticky_elements()

  toggle_stuck_state_for_sticky_elements: =>
    $('.sticky').each ->
      $(this).toggleClass('stuck', this.getBoundingClientRect().top - parseInt($(this).css('top')) <= 1)

ПРИМЕЧАНИЕ. Этот код работает только для вертикального липкого положения.

Ответ 3

Демонстрация с IntersectionObserver (используйте хитрость):

// get the sticky element
const stickyElm = document.querySelector('header')

const observer = new IntersectionObserver( 
  ([e]) => e.target.classList.toggle('isSticky', e.intersectionRatio < 1),
  {threshold: [1]}
);

observer.observe(stickyElm)
body{ height: 200vh; font:20px Arial; }

section{
  background: lightblue;
  padding: 2em 1em;
}

header{
  position: sticky;
  top: -1px;                    /* <- the trick */

  padding: 1em;
  padding-top: calc(1em + 1px); /* <- compensate for the trick */

  background: salmon;
  transition: .1s;
}

/* styles for when the header is in sticky mode */
header.isSticky{
  font-size: .8em;
  opacity: .5;
}
<section>Space</section>
<header>Sticky Header</header>

Ответ 4

После добавления Chrome position: sticky было обнаружено, что недостаточно готов и отнесено на флаг --enable-experimental-webkit-features. Paul Irish сказал в феврале "функция находится в странном состоянии limbo atm".

Я использовал polyfill, пока не стал слишком много головной боли. Он работает красиво, но когда есть, но есть угловые случаи, такие как проблемы CORS, и это замедляет загрузку страниц, делая запросы XHR для всех ваших ссылок CSS и переписывая их для объявления "position: sticky", которое браузер игнорировал.

Теперь я использую ScrollToFixed, который мне нравится лучше StickyJS, потому что это не испортит мой макет с помощью обертки.

Ответ 5

Я придумал это решение, которое работает как шарм и довольно мало. :)

Никаких дополнительных элементов не требуется.

Он запускается при событии прокрутки окна, что является небольшим недостатком.

var _$stickies = [].slice.call(document.querySelectorAll('.sticky'));

_$stickies.forEach(function(_$sticky){
    if (CSS.supports && CSS.supports('position', 'sticky')) {
        apply_sticky_class(_$sticky);

        window.addEventListener('scroll', function(){
            apply_sticky_class(_$sticky);
        })
    }
})

function apply_sticky_class(_$sticky){
    var currentOffset = _$sticky.getBoundingClientRect().top;
    var stickyOffset = parseInt( getComputedStyle(_$sticky).top.replace('px','') );
    var isStuck = currentOffset <= stickyOffset;

    _$sticky.classList.toggle('js-is-sticky', isStuck);
}

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

Ответ 6

Я знаю, что прошло некоторое время с тех пор, как был задан вопрос, но я нашел хорошее решение для этого. Плагин stickybits использует position: sticky, где поддерживается, и применяет класс к элементу, когда он "застревает". Я использовал его недавно с хорошими результатами, и, в момент написания, это активное развитие (что для меня плюс):)