Home > Enterprise >  How do I make a scrollable element scroll farther when a fixed bottom positioned element is shown?
How do I make a scrollable element scroll farther when a fixed bottom positioned element is shown?

Time:02-26

I have a list of song entries that I want to be scrollable. When I click on an entry it queues the song and the media controls slide up from the bottom and are positioned fixed.

Here is the problem, the media controls are going right above the list so they are blocking some items, and I can not scroll any farther to see the other song entries. Having them above the entries in general is what I want so that the controls are always accessible.

I know plenty of apps that have lists or other scrollable content with some sort of pop up or element at the bottom and they made it possible to scroll further when that is there so I am asking how do I implement that?

Here is a minimum example I wrote up. You can see that 15 entries should be visible and indeed when the media controls aren't present, 15 are visible. However once they show up one can scroll to the bottom and some entries are blocked.

So I guess my Svelte code is being formatted really weird in StackOverflow. It's been separated into three blocks, one with script, one with styles, and one with markup.

const entries = 15
const arbitraryArr = [...Array(entries).keys()]

let mediaControls = false

const showMediaControls = () => mediaControls = true
.list {
  list-style: none;
  padding: 0;
}

.entry {
  cursor: pointer;
}

.media-controls {
  position: fixed;
  left: 0;
  right: 0;
  bottom: -100%;
  height: 25%;
  background: #fff;
  transition: bottom 250ms;
}

.media-controls.shown {
  bottom: 0;
}
<main>
  <h1>{entries} entries should be visible</h1>

  <ul class='list'>
    {#each arbitraryArr as whatever (whatever)}
    <li class='entry' on:click={showMediaControls}>
      <h3>This is entry {whatever   1}</h3>

      <p>Some body text</p>
    </li>
    {/each}
  </ul>

  <div class='media-controls' class:shown={mediaControls}>
    <h2>Media controls</h2>
  </div>
</main>

CodePudding user response:

So what I understand from the question is that the media player is coming on top of the last x list items.

There are two solutions that come to mind:

When the media player shows up from below, insert padding to the list item container at the bottom and remove the padding when the media player is hidden. For good UI, you may add transitions.

Another option:

When the media player is shown, render a div at the bottom with the height of the media player and all the list elements will be pushed up. Since the tech stack used is not mentioned, I have implemented something with React. Please take a look: JS Fiddle

class MusicApp extends React.Component {
    constructor(props) {
      super(props)
      this.state = {
        // make this true to see how it works without the fix
        seeWithoutFix: false,
        // ------------

        playing: null,
        items: [{
            text: "God's Plan",
            liked: false
          },
          {
            text: "Family Ties",
            liked: false
          },
          {
            text: "DNA",
            liked: true
          },
          {
            text: "Paranoid",
            liked: true
          },
          {
            text: "Lovesick",
            liked: true
          },
        ]
      }

      this.handleSongClick = this.handleSongClick.bind(this);
    }

    handleSongClick(song) {
      this.setState({
        playing: song
      })
    }

    render() {
      return ( <
        div >
        <
        h2 > Your playlist: < /h2> <
        div > {
          this.state.items.map(item => ( <
            button key = {
              item.text
            }
            onClick = {
              () => this.handleSongClick(item)
            } >
            <
            span > {
              item.text
            } < /span> < /
            button >
          ))
        } {
          !this.state.seeWithoutFix && this.state.playing && < div className = "push-list-up" > < /div>} < /
            div > {
              this.state.playing && < div className = "music-bar" > {
                this.state.playing.text
              } <
              /div>
            } <
            /div>
        )
      }
    }

    ReactDOM.render( < MusicApp / > , document.querySelector("#app"))
body {
  background: #20262E;
  font-family: Helvetica;
}

#app {
  background: #fff;
  transition: all 0.2s;
  padding: 10px;
}

button {
  width: 100%;
  margin: 12px 0;
  padding: 12px;
  box-shadow: 4px 2px 4px rgba(0, 0, 0, 0.1);
}

h2 {
  font-weight: bold;
  margin-bottom: 15px;
}

.music-bar {
  position: fixed;
  text-align: center;
  bottom: 0;
  width: 100%;
  background: white;
  padding: 16px 0px;
}

.push-list-up {
  height: 40px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.0.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.0.0/umd/react-dom.production.min.js"></script>

<div id="app"></div>

  • Related