Ways to ensure <li> elements remain anchored to the top and bottom of <ul> element while scrolling

I currently have a ul with a fixed height that contains a dynamic number of li elements. When there are too many elements, a scrollbar appears. By clicking on a li element, you can select it.

What I am aiming for is to have the active li element stay fixed at the top when scrolling above it and stay fixed at the bottom when scrolling below it. This way, the active li element is always visible, while the other elements scroll past it.

I have created a plunker to demonstrate the issue. I am using Angular, and I am unsure if this can be resolved using only CSS or if I need to use a directive.

Here is the HTML code:

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>

And the CSS code:

.parent{
   display: flex;
}
.child1{

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

Thank you in advance!

Answer №1

To achieve this functionality, I utilized CSS along with implementing a custom directive.

Check out the Plunker I created for a demo here.

The directive I developed is applied to each li element. Within the directive, I used jQuery to target specific elements such as the scrolling div and the current li element.

By incorporating two boolean variables to determine if the li is fixed at the top or bottom, I was able to compare the current scroll position (scrollTop) to the position of the li element. Additionally, I ensured that the li element has an 'active' boolean attached to 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});
                }

            })



        }
    };

Answer №2

The Advantages of Implementing Pure CSS: This method is ideal for individuals looking to keep an element stationary while 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>Item50</li>
  <li class="fixed">HEADER</li>
</ul>

Answer №3

It seems that you prefer having the active div at the top based on what you mentioned.

To address this using CSS

apply position:relative to the parent element and position:absolute to the child element while setting top:0

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Converting JSON object settings to a string causes an error as it is not a valid function

For my project, I have been provided with a JSON object that contains various settings, some being strings and others booleans. One thing I am struggling with is adding an animation name from the object that is stored in a variable. aniFx.move(inner, { ...

Why does the appearance of my PHP spreadsheet change when I attempt to print it?

After using a CSS stylesheet to position my textboxes correctly, I noticed that in Chrome everything appeared fine. However, when attempting to print the site (Ctrl+P), each sentence and textbox shifted. How can I ensure they remain in place? <!-- #cap ...

React - Updating state from an external component

I realize that the question I am about to ask may go against some basic principles of using React... however, with this example, I hope someone can assist me in finding a solution to the problem I am currently facing. While this code snippet is not from m ...

What's the deal with this error message saying val.slice isn't a function?

In the process of developing a web application using express with a three-tier architecture, I have chosen to use a mysql database to store blogposts as a resource. Here is an illustration of how the table is structured: CREATE TABLE IF NOT EXISTS blogpos ...

The initial item in a pagination/list is double-parsed on an AJAX website using Selenium 3.0.2, Firefox webdriver, and BeautifulSoup 4.5.1

For the past three days, I've been facing a frustrating issue with both Selenium and Bs4. While I suspect Selenium (or my code) to be the culprit. Like many others before me, I'm attempting to scrape data from this website: I'm moving from ...

What is the best way to set a div's size to a constant value?

I recently designed a webpage that includes a feature where clicking a button adjusts the font size within the div. Within the div, there is a ul containing the buttons. However, when the font size changes, the div expands and the nav buttons also shift a ...

Can the background color of HTML header text be altered using JavaScript in JQGRID?

Can the background color of HTML header text be modified using JavaScript? Updated: Oops, I forgot to mention that it is for the header text in jqGrid. My apologies for that oversight. ...

Guide on incorporating text input areas into specific positions within a string

Looking for a way to replace specific words in a string with input fields to enter actual values? For example... Dear Mr. [Father_name], your son/daughter [name] did not attend class today. This is what I want it to look like... Dear Mr. Shankar, your ...

How to properly declare an explicit injector when using the resolve parameter in $routeProvider?

$routeProvider resolve feature in AngularJS allows for injecting additional dependencies to the controller function. How can we combine this with explicit dependency injection declaration? Example: angular.module('myModule', []) .config(func ...

Insufficient width of images in the bootstrap carousel

Is there a different solution to this problem that hasn't been mentioned in the other posts? I've tried all the top solutions from those posts, but my issue still remains. In particular, the "example" code and "Stock" bootstrap carousel appear t ...

Advantages and disadvantages of distinct methods for looping through HTML elements

My JS code generates HTML elements that are structured like this: <div id="container"> <div id="block_1" class="blocks"></div> <div id="block_2" class="blocks"></div> <div id="block_3" class="blocks"></di ...

Ways to help parents disregard events initiated by their children

I have a situation where clicking on a child element should not trigger the parent element, but using event.stopPropagation() is not an option due to other event listeners waiting for the click event. Specifically, when clicking on the dropdown of parent1 ...

Modifying child text in React when hovering over a button

How can I update the text of a child function component when hovering over a button in the parent class component? I am struggling to access the prop in the child component and keep getting null. Any assistance would be greatly appreciated. Parent Compone ...

Tips for sending an email without using MAILTO in JavaScript or jQuery

Today is a great day for many, but unfortunately not for me. I've been struggling with this issue for over two weeks now and can't seem to find a solution anywhere on the internet. Stack Overflow always comes to my rescue when things get really t ...

Exploring properties of a directive in AngularJS

Take a look at this directive (function () { /** * Configuration */ var directiveName = 'customSearchFilters'; /** * Module */ angular.module(directiveName, []).directive('searchFilters', searchFiltersDir); function searchFilters ...

Utilizing data-ng-start and end conditions in AngularJs to bind table values

Whenever I try to use the data-ng-repeat-start and data-ng-repeat-end to bind data with row values in a table, the data does not display in the correct format. <table id="tbl"> <tbody> <tr data-ng-repeat="data in RDetails" data-n ...

Exploring Vue's data binding with both familiar and mysterious input values

How can I model an object in Vue that contains both known and unknown values? The quantity is unknown, but the type is known. I need to present user inputs for each type, where the user enters the quantity. How should I approach this? data() { retur ...

Tips for locating and interacting with a specific element using Selenium

I am delving into the realm of Python and honing my skills by creating practical applications for daily use. I recently embarked on automating a routine task, but hit a roadblock when attempting to utilize selenium to click on a specific element that dynam ...

The 'mat-table' component is triggering an error indicating that the 'dataSource' attribute is unrecognized in the table

Recently, I have been diving into the world of Material Library for Angular. Working with Angular version 15.0.1 and Material version 15.0.1, I decided to include a mat-table in my form (schedule.allocator.component.html): https://i.stack.imgur.com/c7bsO. ...

Retrieve the nth element from an array using a function that requires 2 arguments

During my coding journey, I encountered a challenge that has proven to be quite tricky. The task in question goes as follows: Create a function that accepts an array (a) and a value (n) as parameters Identify and store every nth element from the array in ...