8

So far I haven't found a solid way to create a sticky header on AMP pages. I know there are CSS workaround/hacks, but nothing I can use in a production environment. A simple "position:fixed;" unfortunately won't work in my case.

Out of all the components, I thought there would be one that toggles a body class on scroll, but I haven't found anything yet. Also don't think "amp-position-observer" will be of any use.

Am I missing something? Ideally I'd like to be able to toggle an element's class name after a scroll of X amount of pixels. Is this possible in AMP?

TylerH
  • 19,065
  • 49
  • 65
  • 86
Joseph Wer
  • 351
  • 1
  • 5
  • 15
  • 1
    Why doesn't `position: fixed` work? There's an official example of just that: https://github.com/ampproject/amphtml/blob/master/examples/article-fixed-header.amp.html – ceejayoz Jun 13 '18 at 00:14
  • have you tried position:sticky? (here's a good blog on it https://gedd.ski/post/position-sticky/) – Rachel Gallen Jun 13 '18 at 00:20
  • @ceejayoz due to the nature of the header, I can't keep the same layout on scroll. There are some sub items that need to disappear, background color needs to change etc. Might have to go that route and deal with the design sacrifice. No biggie. – Joseph Wer Jun 13 '18 at 02:19
  • @RachelGallen I'm thinking it will be the same issue as above. If there was some sort of pseudo selector, I could do it. .header:sticky {background-color:red} Unfortunately, no dice. – Joseph Wer Jun 13 '18 at 02:23
  • @JosephWer is there a reason why you are looking for css attributes? You could easily use the scrollTop position in a js function to update a classname after a certain amount of pixels.. – Rachel Gallen Jun 13 '18 at 02:33
  • @RachelGallen this is a Google AMP project, so unfortunately no custom javascript is allowed :( – Joseph Wer Jun 13 '18 at 19:57

2 Answers2

6

Toggling an element's classname after a scroll of X amount of pixels is currently not supported as amp-position-observer does not allow changing amp-state.

You can combine amp-position-observer to change parts of the header using amp-animation. However, it's application is limited as the supported CSS properties are limited. Nevertheless, with a little bit of creativity this approach can be quite flexible. One possible pattern is to duplicate elements in your header which are then shown/hidden based on your scrolling position.

Here is a sample highlighting the header based on the currently focused section.

fstanis
  • 4,719
  • 1
  • 17
  • 37
Sebastian Benz
  • 4,055
  • 1
  • 18
  • 17
1

I built a working solution of a sticky header within an amp-list. The pitfall is that amp elements add display: block and position: absolute on many elements.

To use position: sticky you need to use display: inline and position: relative on all subelements on your header. Make sure these are actually applied and not overwritten, use id to get a higher specificity over the amp css classes.

Here's an example using an amp list css:

  • All divs need display: inline
  • The amp-list gets an id (not class) to apply css to itself and the generated child div
  • Divs can be nested as long as they use display: inline

.sticky {
  position: sticky;
  z-index: 1;
  display: inline-block;
  box-sizing: border-box;
  width: 100%;
  background-color:white;
  top: 40px;
}

.inline {
  display: inline;
}

#list-wrapper, #list-wrapper>div {
  display: inline;
  position: relative;
}
<div>
    <amp-list [src]="..." items="." single-item layout="flex-item" id="list-wrapper">
        <template type="amp-mustache">
            <div class="inline">
                <span class="sticky">
                    <span>Sticky header</span>
                </span>
            </div>
        </template>
    </amp-list>
    <div>Your content</div>
<div>
lisa p.
  • 1,958
  • 19
  • 29