Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sticky position in Safari with Angular Components

So, position: sticky is awesome, right? And so is Angular, right? Using both in conjunction with Firefox and Chrome work great. The problem starts with Safari.

If you build an Angular component that has a position: sticky div within it as the first element in the template, Safari doesn't know how to handle it. Example:

AppComponent:

@Component({
  template: '<sticky-component></sticky-component>'
})
export class AppComponent {}

StickyComponent:

@Component({
  selector: 'sticky-component',
  template: '<div class="sticky">Should be sticky</div>',
  styles: [
    `
      .sticky {
        position: sticky;
        position: -webkit-sticky;
        top: 0;
      }
    `
  ]
})
export class StickyComponent {}

This will generate a DOM like:

...
<sticky-component>
  <div class="sticky"></div>
</sticky-component>
...

If you physically write out the HTML without the <sticky-component> it works great in Safari. But since the parent of the sticky element is the host element, this fails. Trying to add the sticky CSS to the host element doesn't seem like it works either. Has anyone run into this issue before or has any solution? I know I can implement this sticky functionality using event listeners within Angular, but position: sticky is sooo much easier.

StackBlitz example: https://stackblitz.com/edit/angular-jede8a (works in Chrome/Firefox but not in Safari)

like image 942
SpellChucker Avatar asked Nov 30 '18 20:11

SpellChucker


2 Answers

This is more of a workaround which might not suit your needs but I guess it deserves an answer since it does solve the problem (not necessarily in the way you'd like it).

If the issue with Safari is a custom element (with a dash) used in the DOM, you can get rid of that by specifying a different selector. Instead of

selector: 'sticky-component',

you could have

selector: 'div[sticky-component]',

and then use the component by adding an attribute.

<div sticky-component></div>

Although certainly not ideal in this use-case, this is a valid way to define components. In fact, it's often done with custom buttons -- for example, Material itself uses this pattern: <button mat-button>.

like image 122
Lazar Ljubenović Avatar answered Oct 13 '22 16:10

Lazar Ljubenović


Not sure about inline styling. But if you move style to an external file. Following should do the trick.

 :host {
    .sticky {
        position: sticky;
        position: -webkit-sticky;
        top: 0;
    }
 }
like image 39
peter he Avatar answered Oct 13 '22 17:10

peter he