How to programmatically scroll an HTML element?

14,542

Solution 1

Try something like this: http://jsfiddle.net/2yMWC/1/ (no jQuery)

The idea is that when an element is selected, you take note of that element's offsetTop property in JavaScript, and then update the <div> element's scrollTop to match. I added some CSS making the heights of the rows inconsistent just to check how robust the technique is.

Here's a more generic example where the user can select any row and jump/scroll there: http://jsfiddle.net/2yMWC/

The JavaScript

var divEl = document.getElementById("scroll-pane");
var selectedTrEl = undefined;

function select(index) {
    var trEl = divEl.getElementsByTagName("tr")[index];
    if(selectedTrEl) {
        selectedTrEl.className = "";
    }
    selectedTrEl = trEl;
    selectedTrEl.className = "selected";
    var scrollTo = selectedTrEl.offsetTop;
    divEl.scrollTop = scrollTo;
}

select(76);

(function forever() {
    var trEls = divEl.getElementsByTagName("tr");
    var itemNumber = trEls.length;
    var tdEl = document.createElement("td");
    tdEl.appendChild(document.createTextNode("item "+itemNumber));
    var trEl = document.createElement("tr");
    trEl.appendChild(tdEl);
    trEls[0].parentNode.appendChild(trEl);
    select(itemNumber);
    setTimeout(forever, 1000);
}());

The HTML

<div id="scroll-pane" style="width:250px; height:100px; overflow-y:scroll; overflow-x:hidden;">
  <table>
    <tr><td>item 0</td></tr>
    <tr><td>item 1</td></tr>
    <tr><td>item 2</td></tr>
    <tr><td>item 3</td></tr>
    <tr><td>item 4</td></tr>
    <tr><td>item 5</td></tr>
    <tr><td>item 6</td></tr>
    <tr><td>item 7</td></tr>
    <tr><td>item 8</td></tr>
    <tr><td>item 9</td></tr>
    <tr><td>item 10</td></tr>
    <tr><td>item 11</td></tr>
    <tr><td>item 12</td></tr>
    <tr><td>item 13</td></tr>
    <tr><td>item 14</td></tr>
    <tr><td>item 15</td></tr>
    <tr><td>item 16</td></tr>
    <tr><td>item 17</td></tr>
    <tr><td>item 18</td></tr>
    <tr><td>item 19</td></tr>
    <tr><td>item 20</td></tr>
    <tr><td>item 21</td></tr>
    <tr><td>item 22</td></tr>
    <tr><td>item 23</td></tr>
    <tr><td>item 24</td></tr>
    <tr><td>item 25</td></tr>
    <tr><td>item 26</td></tr>
    <tr><td>item 27</td></tr>
    <tr><td>item 28</td></tr>
    <tr><td>item 29</td></tr>
    <tr><td>item 30</td></tr>
    <tr><td>item 31</td></tr>
    <tr><td>item 32</td></tr>
    <tr><td>item 33</td></tr>
    <tr><td>item 34</td></tr>
    <tr><td>item 35</td></tr>
    <tr><td>item 36</td></tr>
    <tr><td>item 37</td></tr>
    <tr><td>item 38</td></tr>
    <tr><td>item 39</td></tr>
    <tr><td>item 40</td></tr>
    <tr><td>item 41</td></tr>
    <tr><td>item 42</td></tr>
    <tr><td>item 43</td></tr>
    <tr><td>item 44</td></tr>
    <tr><td>item 45</td></tr>
    <tr><td>item 46</td></tr>
    <tr><td>item 47</td></tr>
    <tr><td>item 48</td></tr>
    <tr><td>item 49</td></tr>
    <tr><td>item 50</td></tr>
    <tr><td>item 51</td></tr>
    <tr><td>item 52</td></tr>
    <tr><td>item 53</td></tr>
    <tr><td>item 54</td></tr>
    <tr><td>item 55</td></tr>
    <tr><td>item 56</td></tr>
    <tr><td>item 57</td></tr>
    <tr><td>item 58</td></tr>
    <tr><td>item 59</td></tr>
    <tr><td>item 60</td></tr>
    <tr><td>item 61</td></tr>
    <tr><td>item 62</td></tr>
    <tr><td>item 63</td></tr>
    <tr><td>item 64</td></tr>
    <tr><td>item 65</td></tr>
    <tr><td>item 66</td></tr>
    <tr><td>item 67</td></tr>
    <tr><td>item 68</td></tr>
    <tr><td>item 69</td></tr>
    <tr><td>item 70</td></tr>
    <tr><td>item 71</td></tr>
    <tr><td>item 72</td></tr>
    <tr><td>item 73</td></tr>
    <tr><td>item 74</td></tr>
    <tr><td>item 75</td></tr>
    <tr><td>item 76</td></tr>
    <tr><td>item 77</td></tr>
    <tr><td>item 78</td></tr>
    <tr><td>item 79</td></tr>
    <tr><td>item 80</td></tr>
    <tr><td>item 81</td></tr>
    <tr><td>item 82</td></tr>
    <tr><td>item 83</td></tr>
    <tr><td>item 84</td></tr>
    <tr><td>item 85</td></tr>
    <tr><td>item 86</td></tr>
    <tr><td>item 87</td></tr>
    <tr><td>item 88</td></tr>
    <tr><td>item 89</td></tr>
    <tr><td>item 90</td></tr>
    <tr><td>item 91</td></tr>
    <tr><td>item 92</td></tr>
    <tr><td>item 93</td></tr>
    <tr><td>item 94</td></tr>
    <tr><td>item 95</td></tr>
    <tr><td>item 96</td></tr>
    <tr><td>item 97</td></tr>
    <tr><td>item 98</td></tr>
    <tr><td>item 99</td></tr>
  </table>
</div>

Some CSS

.selected {
    color:#00aa00
}
table tr:nth-child(2n) {
    font-size:200%;
}

Solution 2

You can just set the container element's scrollTop property to its scrollHeight property to get it to scroll to the bottom.

Alternatively, you can set it to the target element's offsetTop (and even subtract some from that to get it closer to the middle of the view).

Share:
14,542
Multimedia Mike
Author by

Multimedia Mike

I do multimedia stuff. Email at: mike -at- multimedia.cx.

Updated on July 25, 2022

Comments

  • Multimedia Mike
    Multimedia Mike almost 2 years

    I am trying to create a web page that has a table of elements that the user can select from. The number of elements could be as small as a single element but also grow as large as about 120. I don't want the table to stretch down the page, so I'm stuffing it into its own <div> tag with a defined height and a vertical scroll bar. A bare-bones example:

    <div style="width:100px; height:100px; overflow-y:scroll; overflow-x:hidden;">
      <table>
        <tr><td>item 1</td></tr>
        <tr><td>item 2</td></tr>
        <tr><td>item 3</td></tr>
        <tr><td>item 4</td></tr>
        <tr><td>item 5</td></tr>
        <tr><td>item 6</td></tr>
        <tr><td>item 7</td></tr>
        <tr><td>item 8</td></tr>
        <tr style="color:#00aa00"><td>item 9</td></tr>
      </table>
    </div>
    

    In this example, the table is in a vertically-scrolling area and the active item is the last one in the table. So far so good.

    My question is: When updating this table, how can I set it so that it automatically scrolls to the end? E.g., when the page is created, it's supposed to select element #9 automatically; the UI should already highlight that item in the list and that means automatically setting the scrollbar to the end.

    I don't see a way to do it with the <div> tag (though I may be missing something). Do I need to use an <iframe> tag some how? I figure that if each line of the table has an anchor tag, then the scroll position could be set that way. I'm not completely sure how to do that, though, so I thought I would ask.

    I know there are probably data table plugins I can use to do this (I was using YUI previously, and I never figured out if it could solve this particular problem). But this seems simple enough that I don't feel I should need to import any plugin that could easily be used as an entire in-browser spreadsheet.

  • Multimedia Mike
    Multimedia Mike about 11 years
    Thanks. I did a bit of searching-- is scrollTop a jQuery-ism? I haven't dealt with that yet (but am not averse to learning).
  • Niet the Dark Absol
    Niet the Dark Absol about 11 years
    No, it's plain JavaScript.
  • Multimedia Mike
    Multimedia Mike about 11 years
    But will this work for programatically iterating to the next item (or previous) in the list without reloading the page?
  • Multimedia Mike
    Multimedia Mike about 11 years
    Thanks for all of this. Your example works beautifully. This also gives me a good strategy for updating the highlighted cell. Unfortunately, I can't get scrollTop to "take" in my code. I console.log() divEl.scrollTop both before an after setting it and the value remains 0. Is there something I need to do in order to make the property writable?
  • Multimedia Mike
    Multimedia Mike about 11 years
    There must be something else going on here, because when I manually adjust the vertical scroll bar, scrollTop still remains 0.
  • Multimedia Mike
    Multimedia Mike about 11 years
    I discovered a slightly different solution that does the right thing that I need: "selectedTrEl.scrollIntoView(false);". Thanks for pointing me in the right direction.
  • Richard JP Le Guen
    Richard JP Le Guen about 11 years
    Interesting. Which browser are you using?
  • Multimedia Mike
    Multimedia Mike about 11 years
    Google Chrome, latest version, on Windows 7. Your jsfiddle example worked fine. I suspect there's something in my spaghetti JavaScript that is causing a conflict somehow. But that scrollIntoView() method seems to be a good way to accomplish this goal.