# Is it possible to handle scroll events in Elm without the use of ports?

**URL:** <https://discourse.elm-lang.org/t/is-it-possible-to-handle-scroll-events-in-elm-without-the-use-of-ports/3396>\
**Category:** Learn\
**Created:** [March 26, 2019, 10:59am UTC](https://discourse.elm-lang.org/t/is-it-possible-to-handle-scroll-events-in-elm-without-the-use-of-ports/3396 "2019-03-26T10:59:20Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![pdamoc](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/pdamoc/32/36_2.png) [@pdamoc](https://discourse.elm-lang.org/u/pdamoc)\
**Post date:** [March 26, 2019, 10:59am UTC](https://discourse.elm-lang.org/t/is-it-possible-to-handle-scroll-events-in-elm-without-the-use-of-ports/3396/1 "2019-03-26T10:59:20Z")

</div>

I have this [Ellie example](https://ellie-app.com/55HbSQ9mD6Na1) where I implemented a sticky menu. Is it possible to modify this example to not use ports?  
Is there a simpler way to do it (one that doesn’t involve two messages)?

---

<div class="post-metadata">

**Author:** ![joakin](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/joakin/32/171_2.png) [@joakin](https://discourse.elm-lang.org/u/joakin)\
**Post date:** [March 26, 2019, 12:28pm UTC](https://discourse.elm-lang.org/t/is-it-possible-to-handle-scroll-events-in-elm-without-the-use-of-ports/3396/3 "2019-03-26T12:28:32Z")

</div>

Maybe just position sticky in CSS could do? (If you can live with the browser support, which is not bad) it also degrades gracefully to non-stickiness if it is not supported.

See [https://developer.mozilla.org/en-US/docs/Web/CSS/position#Sticky\_positioning](https://developer.mozilla.org/en-US/docs/Web/CSS/position#Sticky_positioning) and the example there.

---

<div class="post-metadata">

**Author:** ![pdamoc](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/pdamoc/32/36_2.png) [@pdamoc](https://discourse.elm-lang.org/u/pdamoc)\
**Post date:** [March 26, 2019, 12:37pm UTC](https://discourse.elm-lang.org/t/is-it-possible-to-handle-scroll-events-in-elm-without-the-use-of-ports/3396/4 "2019-03-26T12:37:46Z")

</div>

> [@joakin](#):
>
> Maybe just position sticky in CSS could do?

For this particular usecase, that would work for a nav that doesn’t change but, how would you change the background color once the nav reaches top?

---

<div class="post-metadata">

**Author:** ![joakin](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/joakin/32/171_2.png) [@joakin](https://discourse.elm-lang.org/u/joakin)\
**Post date:** [March 26, 2019, 1:08pm UTC](https://discourse.elm-lang.org/t/is-it-possible-to-handle-scroll-events-in-elm-without-the-use-of-ports/3396/5 "2019-03-26T13:08:49Z")

</div>

Then you definitely need to use ports with scroll events right now like you were doing, unfortunately. Until we have a onScroll subscription parallel to onResize.

I would set it up in JS with async throttling for better perf (see [example](https://developer.mozilla.org/en-US/docs/Web/Events/scroll#Example)), to avoid potential performance issues. Scroll and resize events can trigger rather quickly.

Very similar to what you are already doing.

---

<div class="post-metadata">

**Author:** ![joakin](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/joakin/32/171_2.png) [@joakin](https://discourse.elm-lang.org/u/joakin)\
**Post date:** [March 26, 2019, 1:14pm UTC](https://discourse.elm-lang.org/t/is-it-possible-to-handle-scroll-events-in-elm-without-the-use-of-ports/3396/6 "2019-03-26T13:14:26Z")

</div>

I have a couple of helpers in a gist here:

> <https://gist.github.com/joakin/0890e13047d63361032fc6c27839f352>

I believe (hope) they should work well.

---

<div class="post-metadata">

**Author:** ![jreusch](https://avatars.discourse-cdn.com/v4/letter/j/b5e925/32.png) [@jreusch](https://discourse.elm-lang.org/u/jreusch)\
**Post date:** [March 26, 2019, 2:36pm UTC](https://discourse.elm-lang.org/t/is-it-possible-to-handle-scroll-events-in-elm-without-the-use-of-ports/3396/7 "2019-03-26T14:36:41Z")

</div>

If you don’t necessarily need your scroll to happen on `<body>`, you can maybe create a wrapper `<div>` and attach a scroll event to that:

CSS:

```css
#app {
      margin: 0;
      padding: 0;
      width: 100vw;
      height: 100vh;
      overflow: auto;
}

```

ELM:

```elm
onScroll : msg -> Attribute msg
onScroll msg = on "scroll" (Json.succeed msg)

wrapView : Html Msg -> Html Msg
wrapView actualContents =
    div [id "app", onScroll SyncViewport] [actualContents]

updateViewport : Viewport -> Cmd Msg
updateViewport previous =
    Browser.Dom.getViewportOf "app"
        |> Task.onError (\_ -> Task.succeed previous)
        |> Task.perform UpdateViewport

```

---

<div class="post-metadata">

**Author:** ![pdamoc](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/pdamoc/32/36_2.png) [@pdamoc](https://discourse.elm-lang.org/u/pdamoc)\
**Post date:** [March 26, 2019, 2:44pm UTC](https://discourse.elm-lang.org/t/is-it-possible-to-handle-scroll-events-in-elm-without-the-use-of-ports/3396/8 "2019-03-26T14:44:30Z")

</div>

Thank you!

[I have updated the example to use this solution.](https://ellie-app.com/55LNyTg8f3ka1)

---

<div class="post-metadata">

**Author:** ![joakin](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/joakin/32/171_2.png) [@joakin](https://discourse.elm-lang.org/u/joakin)\
**Post date:** [March 26, 2019, 9:00pm UTC](https://discourse.elm-lang.org/t/is-it-possible-to-handle-scroll-events-in-elm-without-the-use-of-ports/3396/9 "2019-03-26T21:00:12Z")

</div>

Oh very nice! I missed that on the MDN docs, it is a nice workaround.

I tried the Ellie on an iOS device and with two or three flicks I generated 200 messages and the corresponding 200 getViewportOf calls too. It was pretty janky scrolling, probably letting css with position sticky handle the position, using debounced scroll events for toggling the menu style, and HTML.Lazy to avoid renders would give the best UX.

---

<div class="post-metadata">

**Author:** ![system](https://canada1.discourse-cdn.com/flex035/uploads/elm_lang/original/1X/50a05e53677a2c3b47776d7abd0f113eb50193a1.png) [@system](https://discourse.elm-lang.org/u/system)\
**Post date:** [April 5, 2019, 9:00pm UTC](https://discourse.elm-lang.org/t/is-it-possible-to-handle-scroll-events-in-elm-without-the-use-of-ports/3396/10 "2019-04-05T21:00:15Z")

</div>

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.
