Работа с Angular

Для интеграции Stickybits в проект на Angular необходимо сначала установить пакет через npm:

npm install stickybits --save

После установки библиотеку можно импортировать в компонент или сервис:

import stickybits from 'stickybits';

Рекомендуется инициализировать Stickybits внутри жизненного цикла компонента ngAfterViewInit, чтобы гарантировать наличие DOM-элементов, к которым будет применяться «липкое» поведение.

import { Component, AfterViewInit } from '@angular/core';
import stickybits from 'stickybits';

@Component({
  selector: 'app-sticky-demo',
  templateUrl: './sticky-demo.component.html',
  styleUrls: ['./sticky-demo.component.scss']
})
export class StickyDemoComponent implements AfterViewInit {

  ngAfterViewInit(): void {
    stickybits('.sticky-element', {
      stickyBitStickyOffset: 0,
      useStickyClasses: true,
      verticalPosition: 'top'
    });
  }
}

Основные параметры Stickybits

  • stickyBitStickyOffset — задаёт смещение от верхнего края окна для фиксированного элемента. Позволяет учитывать, например, высоту шапки сайта.
  • useStickyClasses — при значении true Stickybits добавляет CSS-классы (.is-sticky, .is-stuck), что упрощает стилизацию через SCSS или CSS.
  • verticalPosition — определяет вертикальную позицию фиксации элемента ('top' или 'bottom').
  • parentClass — класс родителя для ограничения области действия «липкого» элемента. Если не указан, элемент будет фиксироваться относительно окна.

Пример с использованием кастомного смещения и ограничением родителем:

stickybits('.sticky-element', {
  stickyBitStickyOffset: 60,
  useStickyClasses: true,
  verticalPosition: 'top',
  parentClass: 'sticky-container'
});

Работа с динамическим контентом

В Angular часто используется динамическая подгрузка контента через *ngIf или *ngFor. В таких случаях Stickybits необходимо инициализировать после того, как элемент появился в DOM. Для этого удобно использовать ViewChild или AfterViewInit.

import { ViewChild, ElementRef } from '@angular/core';

@ViewChild('dynamicSticky') dynamicSticky!: ElementRef;

ngAfterViewInit(): void {
  if (this.dynamicSticky) {
    stickybits(this.dynamicSticky.nativeElement, {
      stickyBitStickyOffset: 50
    });
  }
}

Если элементы могут появляться и исчезать динамически, рекомендуется использовать MutationObserver или Angular ngAfterViewChecked, чтобы повторно инициализировать Stickybits при изменении DOM.

Использование классов для кастомизации стилей

Stickybits добавляет следующие CSS-классы к элементу:

  • .js-is-sticky — элемент в состоянии «липкости»
  • .js-is-stuck — элемент достиг границы родителя
  • .js-is-bottom — элемент закреплён у нижней границы родителя (для verticalPosition 'bottom')

Пример SCSS для визуального эффекта:

.sticky-element {
  transition: all 0.3s ease;
  
  &.js-is-sticky {
    background-color: rgba(255, 255, 255, 0.95);
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
  }
  
  &.js-is-stuck {
    background-color: rgba(240, 240, 240, 0.95);
  }
}

Удаление и повторная инициализация

Для корректного управления памятью и предотвращения конфликтов при переходе между компонентами рекомендуется очищать Stickybits перед уничтожением компонента:

import { OnDestroy } from '@angular/core';

export class StickyDemoComponent implements AfterViewInit, OnDestroy {
  private stickyInstance: any;

  ngAfterViewInit(): void {
    this.stickyInstance = stickybits('.sticky-element', { useStickyClasses: true });
  }

  ngOnDestroy(): void {
    if (this.stickyInstance) {
      this.stickyInstance.cleanup();
    }
  }
}

Интеграция с Angular Material и Flex Layout

При использовании Angular Material и Flex Layout важно учитывать, что Stickybits применяет фиксированное позиционирование. Для корректной работы:

  • Родительский контейнер должен иметь относительное позиционирование (position: relative)
  • Если используется mat-toolbar или фиксированные шапки, задавать stickyBitStickyOffset равным их высоте
  • При использовании fxLayout проверять, что элементы не скрываются или не смещаются динамически без уведомления Stickybits

Адаптивное поведение

Stickybits корректно работает с responsive-дизайном, но при изменении ширины экрана может понадобиться пересчитать позиции. Для этого удобно подписаться на событие window.resize и вызывать повторную инициализацию:

window.addEventListener('resize', () => {
  if (this.stickyInstance) {
    this.stickyInstance.cleanup();
    this.stickyInstance.update();
  }
});

Комбинирование с Angular анимациями

Stickybits можно комбинировать с Angular анимациями для плавного появления «липкого» элемента. При этом CSS-классы .js-is-sticky удобно использовать как триггеры:

animations: [
  trigger('stickyFade', [
    state('inactive', style({ opacity: 0 })),
    state('active', style({ opacity: 1 })),
    transition('inactive => active', animate('300ms ease-in')),
    transition('active => inactive', animate('200ms ease-out'))
  ])
]
<div [@stickyFade]="isSticky ? 'active' : 'inactive'" class="sticky-element">
  Контент
</div>

Особенности производительности

Stickybits использует минимальное количество слушателей событий и оптимизирован для быстрого рендера. Тем не менее при большом количестве «липких» элементов рекомендуется:

  • Ограничивать использование в пределах видимой области
  • Использовать useStickyClasses: true для стилизации через классы вместо ручного JS-манипулирования стилями
  • Для динамических списков с множеством элементов применять ленивую инициализацию или виртуальный скролл

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