最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to keep <li> elements fixed top and bottom of <ul> element when scrolling - Stack O

programmeradmin2浏览0评论

I have a ul with fixed height, which contian dynamic number of li elements, if too many a scrollbar appaers. You can select a lielement by clicking on it.

What I want is the lielement that is active to be fixed at the top if scrolling aboveit or fixed at the bottom if scrolling below it, so the active li element is always showing, and the other li elements just scrolls past the active one.

I have made a plunker. I am using Angular, and I dont know if this can be solved just using CSS or if I need a directive etc. for this.

Html:

div class="parent">
 <div class="child1">
   <input ng-model="vm.query" type="text" placeholder="Search" />
    <ul  >
        <li ng-repeat="todo in  todos" ng-class="{'active': todo.active}" ng-click="activeTodo($index)">
            <a>{{todo.name}}</a>
        </li>

    </ul>
 </div>

CSS:

.parent{
   display: flex;
}
.child1{

  background-color: #eeeeee;
  height: 500px;
  overflow:scroll;
}
.active{
 background-color: red;
 position:fixed;
}

Thanks in advance!

I have a ul with fixed height, which contian dynamic number of li elements, if too many a scrollbar appaers. You can select a lielement by clicking on it.

What I want is the lielement that is active to be fixed at the top if scrolling aboveit or fixed at the bottom if scrolling below it, so the active li element is always showing, and the other li elements just scrolls past the active one.

I have made a plunker. I am using Angular, and I dont know if this can be solved just using CSS or if I need a directive etc. for this.

Html:

div class="parent">
 <div class="child1">
   <input ng-model="vm.query" type="text" placeholder="Search" />
    <ul  >
        <li ng-repeat="todo in  todos" ng-class="{'active': todo.active}" ng-click="activeTodo($index)">
            <a>{{todo.name}}</a>
        </li>

    </ul>
 </div>

CSS:

.parent{
   display: flex;
}
.child1{

  background-color: #eeeeee;
  height: 500px;
  overflow:scroll;
}
.active{
 background-color: red;
 position:fixed;
}

Thanks in advance!

Share Improve this question edited Dec 22, 2015 at 7:46 Devl11 asked Dec 20, 2015 at 21:25 Devl11Devl11 2212 silver badges10 bronze badges 1
  • This is not achievable via CSS only. The logic is quite simple, really: on parent scroll check position of active element and determine if it's in view or not. If it's not, change its position to fixed (top or bottom) and (eventually) set a top/bottom padding on the parent. Would you like us to code it for you? If yes, please provide a reason. Preferably a good one. – tao Commented Dec 20, 2015 at 21:44
Add a ment  | 

3 Answers 3

Reset to default 2

I managed this using some CSS and making a directive.

Made a plunker here.

I made a directive which every li element got. Then with jquery in the directive I get the necessary elements like the div which have the scroll, the current li element etc.

Two booleans for checking if the li is fixed at the top or bottom. And then just check if the current scrollPosition(scrollTop) is higher or lower then the current li element. And it also check so the li element got the active boolean attached too it.

return {
        restrict: 'A',

        link: function($scope, element, attributes){

            var scrollDiv = $('#scrollDiv'),
                liElement = element,
                liElementTop = parseInt(liElement.offset().top),
                scrollDivTop = parseInt(scrollDiv.offset().top),
                isFixedTop = false,
                isFixedBottom = false;

            liElement.width(scrollDiv.width());


            scrollDiv.on('scroll', function(){
                var scrollTop = scrollDiv.scrollTop();

                if (!isFixedBottom && !isFixedTop && scrollTop <= liElementTop - (scrollDivTop+(scrollDiv.height()-liElement.height())) && liElement.hasClass("active")) {
                    isFixedBottom = true;
                    liElement.css({'position': 'fixed', 'top': scrollDivTop+(scrollDiv.height()-liElement.height()+1),'list-style-type':'none','z-index':'10'});
                } else if (isFixedBottom && !isFixedTop && scrollTop >= liElementTop - (scrollDivTop+(scrollDiv.height()-liElement.height()))) {
                    isFixedBottom = false;
                    liElement.css({'position': 'static', 'top': 0});
                }
                else if (!isFixedTop && !isFixedBottom && scrollTop >= liElementTop - scrollDivTop && liElement.hasClass("active")) {
                    isFixedTop = true;
                    liElement.css({'position': 'fixed', 'top': scrollDivTop,'list-style-type':'none','z-index':'10'});
                }
                else if (isFixedTop && !isFixedBottom && scrollTop <= liElementTop - scrollDivTop) {
                    isFixedTop = false;
                    liElement.css({'position': 'static', 'top': 0});
                }

            })



        }
    };

The consideration of using pure CSS: One of the best solution is this, because those who perhaps want to make an element remain fixed while it is scrolling up and down!

body {
  margin: 10px;
}

ul {
  display: block;
  width: 210px;
  max-height: 120px;
  overflow-y: auto;
  margin: 0;
  padding: 0;
}

li {
  padding: 8px 10px;
  display: block;
  font-size: 13px;
  cursor: pointer;
  background-color: #ddd;
}

li.fixed {
  position: -webkit-sticky;
  position: sticky;
  bottom: 0;
  background-color: #111;
  color: #f2f2f2;
}
<ul>
  <li>Item1</li>
  <li>Item2</li>
  <li>Item3</li>
  <li>Item4</li>
  <li>Item5</li>
  <li>Item6</li>
  <li>Item7</li>
  <li>Item8</li>
  <li>Item9</li>
  <li>Item10</li>
  <li>Item11</li>
  <li>Item12</li>
  <li>Item13</li>
  <li>Item14</li>
  <li>Item15</li>
  <li>Item16</li>
  <li>Item17</li>
  <li>Item18</li>
  <li>Item19</li>
  <li>Item20</li>
  <li>Item21</li>
  <li>Item22</li>
  <li>Item23</li>
  <li>Item24</li>
  <li>Item25</li>
  <li>Item26</li>
  <li>Item27</li>
  <li>Item28</li>
  <li>Item29</li>
  <li>Item30</li>
  <li>Item31</li>
  <li>Item32</li>
  <li>Item33</li>
  <li>Item34</li>
  <li>Item35</li>
  <li>Item36</li>
  <li>Item37</li>
  <li>Item38</li>
  <li>Item39</li>
  <li>Item40</li>
  <li>Item41</li>
  <li>Item42</li>
  <li>Item43</li>
  <li>Item44</li>
  <li>Item45</li>
  <li>Item46</li>
  <li>Item47</li>
  <li>Item48</li>
  <li>Item49</li>
  <li>Item50</li>
  <li class="fixed">HEADER</li>
</ul>

If I understood you correctly you like the active div on top.

to solve this in css

use position:relative on parent and position:absolute on the child element with top:0

发布评论

评论列表(0)

  1. 暂无评论