Implementing position sticky on a div depending on its content text - step by step guide

If the text inside the .newsDate matches the previous or next .newsDate, I want to make its position sticky when scrolling, until it reaches the next .newsMiddleCont div.

What I'm trying to achieve:

The same date on multiple news items should stick if they were published on the same day.

The current code is not behaving as intended.

It applies and removes the sticky position to all .newsDate elements instead of only when .newsMiddleCont is visible and when the classes have matching innerText.

EDIT:

Further information:

The sticky behavior should be based on the date in .newsDate.

In my example HTML, the first "28. September 2022." should remain sticky until it reaches the second "28. September 2022."; and then continue until "13. October 1999.", after which it becomes static. This process repeats for similar scenarios.

IMPORTANT:

Dates should scroll uniquely. As we scroll down, the date sticks and moves accordingly. If the next article has the same date, the date shifts to that post. If the dates differ, the date stays at the bottom of the corresponding post and scrolls along with it.

Answer №1

It seems like I've grasped the essence of your query... My suggestion is to make a slight modification to the HTML, incorporating writing-mode: vertical-lr; along with transform: rotate(180deg); for the date section.
Below is an example of how your code could be structured:

body {
  padding: 0;
  margin: 0;
  background-color: #1e1e1e;
}

.sec_pub {
  display: grid;
  grid-gap: 64px;
}

.newsCont {
  display: grid;
  grid-template-columns: auto 1fr;
  max-width: 870px;
  color: white;
}

.newsLeftCont {
  writing-mode: vertical-lr;
  transform: rotate(180deg);
  position: sticky;
  top: 20px;
  border-inline-end: solid 1px #fff;
  padding: 20px;
  margin: 0 20px;
  margin-inline: 20px 0;
  white-space: nowrap;
  align-self: start;
  color: #F05663;
  font-size: 12px;
  font-weight: 700;
  text-transform: uppercase;
  background-color: #1e1e1e;
}

.newsContPosts {
  display: grid;
  grid-gap: 96px;
}

.newsMiddleCont {
  padding: 40px 56px;
  background: #242424;
  display: grid;
  grid-gap: 16px;
}
<section class="sec_pub">
 <div class="newsCont">
    <div class="newsLeftCont">27. September 2022.</div>
    <div class="newsContPosts">
    <div class="newsMiddleCont">
      (Content for the first date)
    </div>
    <div class="newsMiddleCont">
      (Additional content for the first date)
    </div>
  </div>
 </div>
...
</section>

Answer №2

Furthermore, by utilizing the top attribute, you can position the fixed element in a way that gives it the appearance of being sticky. Make sure to adjust your CSS settings accordingly.

$(window).on("scroll", function() {
  // Retrieve all news items.
  let newsItems = $(".newsCont");

  newsItems.each(function(index) {
// Get the current news date.
let currentDate = $(this).find(".newsDate").text().trim();

// Calculate the scroll top position.
let topPosition = $(this).offset().top - $(window).scrollTop();

// If the current date is '28. September 2022.', 
// and the topPosition is less or equal to 0, then add the sticky class.
if (currentDate === '28. September 2022.' && topPosition <= 0) {
  $(this).find(".newsLeftCont").addClass("sticky");
} else {
  // Remove the sticky class otherwise.
  $(this).find(".newsLeftCont").removeClass("sticky");
}
  });
});
html,
body {
  padding: 0;
  margin: 0;
  background-color: #1e1e1e;
}

.newsCont {
  max-width: 870px;
  min-height: 756px;
  position: relative;
  color: white;
}

.newsLeftCont {
  height: 222px;
  padding-top: 40px;
  padding-bottom: 40px;
  left: 0px;
  top: 50px;
  position: absolute;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  gap: 8px;
  display: inline-flex;
}

... (remaining CSS code remains the same as original)

.sticky {
  position: sticky;
  top: 0;
  visibility: visible;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<section class="sec_pub">
  <div class="innerWrap newsWrap">
    <div class="newsCont">
      <div class="newsLeftCont">
        <div class="newsLeftContInner">
          <div class="newsDate">28. September 2022.</div>
        </div>
      </div>
      <div class="newsMiddleCont">
        ... (Lorem Ipsum text remains the same as original)
      </div>
    </div>
  </div>
  ... (additional HTML structure remains the same as original)
</section>

Answer №3

I have created a modified version of the problem you provided. These changes are just minor adjustments

$(window).on('scroll', function() {
  var previousDate = null;

  $('.newsLeftCont').each(function() {
    var newsLeftCont = $(this);
    var newsDate = newsLeftCont.find('.newsDate');
    var isElementVisible = isElementInViewport(newsLeftCont);

    newsLeftCont.addClass('sticky');
    
    if (isElementVisible && newsDate.text().trim().toLowerCase() !== previousDate) {
      newsLeftCont.addClass('sticky');
      previousDate = newsDate;
    } else if(previousDate != null) {
      previousDate.removeClass('sticky');
    }
  });
});

function isElementInViewport(element) {
  var rect = element[0].getBoundingClientRect();
  return rect.top >= 0 && rect.bottom <= $(window).height();
}
html,
body {
  padding: 0;
  margin: 0;
  background-color: #1e1e1e;
}

.newsCont {
  max-width: 870px;
  min-height: 756px;
  position: relative;
  color: white;
}

.newsLeftCont {
  height: 222px;
  padding-top: 40px;
  padding-bottom: 40px;
  left: 0px;
  top: 50px;
  position: absolute;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  gap: 8px;
  display: inline-flex;
}

.newsLeftContInner {
  align-self: stretch;
  padding-top: 16px;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  gap: 8px;
  display: flex;
  height: 160px;
}

.newsDate {
  transform: rotate(-90deg);
  transform-origin: 0 0;
  color: #F05663;
  font-size: 12px;
  font-weight: 700;
  text-transform: uppercase;
  word-wrap: break-word;
  width: 140px;
  border-right: 0.50px #D6D6D6 solid;
  height: 40px;
  line-height: 37px;
  top: 50px;
  position: relative;
  background-color: #1e1e1e;
}

.newsMiddleCont {
  padding-left: 56px;
  padding-right: 56px;
  padding-top: 40px;
  padding-bottom: 40px;
  left: 76px;
  top: 0px;
  position: absolute;
  background: #242424;
  flex-direction: column;
  justify-content: flex-start;
  align-items: flex-start;
  gap: 16px;
  display: inline-flex
}

.newsLeftCont {
  position: static;
}

.sticky {
  position: sticky;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<section class="sec_pub">
  <div class="innerWrap newsWrap">
    <div class="newsCont">
      <div class="newsLeftCont">
        <div class="newsLeftContInner">
          <div class="newsDate">28. September 2022.</div>
        </div>
      </div>
      <div class="newsMiddleCont">
        Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Lectus urna duis convallis convallis tellus id interdum. Sit amet nisl purus in mollis nunc sed id semper. Pharetra magna ac placerat
        vestibulum lectus. Suscipit adipiscing bibendum est ultricies integer quis auctor. Neque ornare aenean euismod elementum nisi quis. Risus nullam eget felis eget nunc lobortis mattis aliquam. Vitae nunc sed velit dignissim sodales ut eu sem. Ullamcorper
        morbi tincidunt ornare massa. Consequat mauris nunc congue nisi. Morbi blandit cursus risus at ultrices mi. Tellus orci ac auctor augue mauris. Id diam vel quam elementum pulvinar etiam non quam lacus. Sem fringilla ut morbi tincidunt augue interdum
        velit euismod. Nulla posuere sollicitudin aliquam ultrices sagittis orci a.<br>Sed augue lacus viverra vitae congue. Molestie ac feugiat sed lectus vestibulum. Venenatis cras sed felis eget velit aliquet sagittis id consectetur. Enim nulla
        aliquet porttitor lacus luctus accumsan tortor posuere. Arcu dictum varius duis at ...

/** Note: The remaining code has been truncated for brevity **/

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

A guide on initiating a get request with URL in React

Utilizing React for the frontend and express for the backend has been my approach. By defining get methods in my express like this:- app.get('/addBill',(req,res)=>{ // --first method res.render("addBill"); }); app.get(&a ...

The priority of custom attributes in HTML

There seems to be some ambiguity regarding whether data- attributes should be considered primary or secondary syntax. Is there a defined standard for this in major frameworks like Angular? For example, if an attribute is specified as both my-attr and dat ...

Error: The function Object.entries is not defined

Why does this error persist every time I attempt to start my Node.js/Express server? Does this issue relate to the latest ES7 standards? What requirements must be met in order to run an application utilizing these advanced functionalities? ...

Dynamic horizontal div elements laid out in a repeating pattern using CSS Grid

I'm fairly new to CSS/Html/JS and I'd like to create a row of Boxes (loaded from a json file) displayed horizontally. Something similar to this: Here's the code snippet I've been using: <style> .wrapper { display: grid; ...

Guide to saving an Object to a file (JSON) within the project directory using React Native for Debuggingpurposes

Feeling a bit overwhelmed trying to tackle this issue. My goal is to save data to a JSON file in real-time while debugging my application. I have a Redux store state that I want to organize neatly in a file for easier debugging, so exporting/writing the ob ...

Lighthouse Issue: Facing PWA Challenges with a "Request Blocked by DevTools" Error

For hours now, I've been struggling to make Lighthouse work in Chrome for my initial PWA project. I feel completely lost as nothing seems to be making sense despite the basic code I have included below. The issue arises when I load the page normally ...

Managing and updating arrays in VueJS2: Conditionally push new items and update only if their properties have changed

I am currently facing an issue with my form where each time a user updates a value in an input field, a new array element is created and added to the form results. I'm looking for a way to update the properties of the existing array element without cr ...

What is the best way to choose the initial p tag from an HTML document encoded as a string?

When retrieving data from a headless CMS, the content is often returned as a string format like this: <div> <p>1st p tag</p> <p>2nd p tag</p> </div> To target and select the first paragraph tag (p), you can extract ...

loading times of Bootstrap-select are slow when used in multiples

I am facing performance issues on my website when I try to include more than 20 select options. The jQuery execution slows down significantly and there is a stop/continue alert, taking minutes to load. Is there any way to optimize the code for faster loadi ...

Guide on implementing jQuery Validation plugin with server-side validation at the form level

Does anyone have a suggestion for how to handle server-side validation errors that occur after passing the initial client-side validation on a form? $("#contact_form").validate({ submitHandler: function(form) { $.ajax({ type: 'POST', ...

Using Fetch API in NextJS requires pressing the Enter key twice for it to work properly

The functionality of this component should display JSON data in the console log after entering input into the search bar and hitting the enter key. However, there is a lag where the data doesn't show until the enter key is pressed a second time. Addit ...

CSS swapping versus CSS altering

Looking to make changes to the CSS of a page, there are two methods that come to mind: Option 1: Utilize the Jquery .css function to modify every tag in the HTML. For instance: $("body").css("background : red") Alternatively, you can disable the current ...

Tips on invoking a Stencil component function or method from beyond the Vue instance

Is it possible to trigger a function in a Stencil component from the parent Vue instance? For example, I would like to call the callChild() method in the Vue instance, which will then trigger the doSomething() function in the Stencil component. The main ...

I desire to incorporate a subtle fading effect into the script

I have written the script code and now I am looking to add a fade effect to it. Can anyone guide me on how to achieve this? Your help is much appreciated! â€ğI used an online translator as English is not my native language. Please bear with any awkward ph ...

Adjust the width of content within a wrapper using HTML and CSS to automatically resize

I am facing an issue with a content div that has variable length content arranged horizontally. I want the width of this content div to adjust automatically based on the length of its content. Removing the arbitrary "20%" value from the width property is c ...

Identifying copy and paste behavior within an HTML form using .NET CORE MVC 2.1

I inherited a project at my current company and one of the tasks involves allowing users to paste multiple ISBN numbers from Excel into a search field on my Index page (HTML). Sometimes, the ISBNs are poorly formatted with letters or special symbols mixed ...

Is there a way to verify if a FormData file has no content?

Currently working on an AJAX form where users can choose a background color or upload a background image. The aim is to have the bgColor field ignored if a file is specified for bgImg. <label>Color: <input type="color" name="bgColor" value="#0000 ...

Vue3 - Utilizing a method to dynamically alter an input property

Currently, I am in the process of developing a Vue application that incorporates a map feature. The main functionality involves determining whether a given position on the map is over water or land. If the position is over water, I want to iterate through ...

Issues with setSelectionRange functionality in JavaScript unit tests leading to unexpected behavior

Currently, I am utilizing the qunit framework to perform unit testing on interactions within an HTML element that has been dynamically created using jquery (specifically, var $textarea = $('')) in Chrome. Below is the code snippet I am employing ...

Displaying a success dialog after closing a Bootstrap modal

I have set up a bootstrap modal containing a form. Upon submitting the form, the form content is hidden and a bootstrap alert message is displayed. However, upon clicking the bootstrap popup, the same alert message is shown in the popup instead of displayi ...