滚动时如何保持 <li> 元素固定在 <ul> 元素的顶部和底部

Posted

技术标签:

【中文标题】滚动时如何保持 <li> 元素固定在 <ul> 元素的顶部和底部【英文标题】:How to keep <li> elements fixed top and bottom of <ul> element when scrolling 【发布时间】:2016-03-26 22:57:59 【问题描述】:

我有一个固定高度的ul,如果滚动条出现太多,它包含动态数量的li 元素。您可以通过单击选择li元素。

我想要的是li元素,如果在其上方滚动,则活动固定在顶部,如果在其下方滚动,则固定在底部,因此始终显示活动的li元素,而另一个@987654327 @ 元素只是滚动过去的活动元素。

我做了一个plunker。我正在使用 Angular,我不知道这是否可以仅使用 CSS 来解决,或者我是否需要一个指令等。

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;

提前致谢!

【问题讨论】:

这不能仅通过 CSS 实现。逻辑非常简单,真的:在父滚动检查活动元素的位置并确定它是否在视图中。如果不是,请将其位置更改为固定(顶部或底部)并(最终)在父级上设置顶部/底部填充。您希望我们为您编码吗?如果是,请说明理由。最好是一个好的。 【参考方案1】:

使用纯 CSS 的考虑:最好的解决方案之一就是这样,因为那些可能想要使元素在 滚动时保持固定的人上下!

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>

【讨论】:

【参考方案2】:

我使用一些 CSS 并制定了指令来管理它。

做了一个傻瓜here。

我做了一个指令,每个li 元素都得到了。然后在指令中使用 jquery,我得到了必要的元素,例如具有滚动条的 div、当前的 li 元素等。

两个布尔值用于检查li 是固定在顶部还是底部。然后只需检查当前的 scrollPosition(scrollTop) 是高于还是低于当前的 li 元素。它还会检查li 元素是否也附加了活动布尔值。

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);
                

            )



        
    ;

【讨论】:

【参考方案3】:

如果我理解正确,您喜欢顶部的活动 div。

用css解决这个问题

在父元素上使用position:relative,在子元素上使用position:absolutetop:0

【讨论】:

这样做会使活动的 li 始终出现在顶部。 Gustav Olsson 只希望它在溢出时位于顶部/底部

以上是关于滚动时如何保持 <li> 元素固定在 <ul> 元素的顶部和底部的主要内容,如果未能解决你的问题,请参考以下文章

元素上下左右滚动插件,固定dom结构。基于jQuery,2009年

如何使固定元素保持相对于当前顶部滚动位置?

滚动时固定/浮动的div元素

滚动期间表头需要保持固定[重复]

通过滚动保持 select2 元素的固定大小?

使用 mCustomScrollbar 一次滚动一个元素