Highlight the title with a stylish CSS animation effect

I have a challenge with animating div tags once they come into view on the page. Thanks to waypoint.js, I have successfully achieved the 'in viewport' trigger, but now I need help with the animation part.

Specifically, I am looking to add a grey underline to all h1 tags at all times. When these tags become visible, I want a black line to smoothly slide from right to left, covering the grey line, and then almost exit the scene, halting at approximately 25% of the grey line.

In trying to demonstrate this effect, I modified it to work on hover so you can see the progress. However, I am struggling with getting the black line to stop at the 25% mark on the grey line:

Here is an example of the HTML:

<div class="section-header">
  <span>Hello</span>
</div>

And here is the CSS:

.section-header {
    text-transform: uppercase;
    font-weight: 700;
    font-size: 2em;
    letter-spacing: 5px;
    position: relative;
    text-align: center;

    > span {
        display: inline-block;
        position: relative;
        border-bottom: 1px solid #ccc;
        &:before {
            content: "";
            position: absolute;
            width: 0;
            height: 1px;
            bottom: -1px;
            right: 0;

            background-color: #000;
            visibility: hidden;
            -webkit-transition: all 0.9s ease-in-out 0s;
            transition: all 0.9s ease-in-out 0s;
        }
        &:hover {
            &:before {
                visibility: visible;
                width: 100%;
            }
        }
    }

}

Check out the code in action here: http://codepen.io/anon/pen/RWoxBv

Do you think achieving this effect purely in CSS is possible, or should I resort to using Javascript for the animation?

To better visualize the animation process, imagine the black line moving like this:

           - (starts from right hand side and goes to left)
          --
         ---
        ----
       -----
      ------
     -------
    --------
   ---------
  ----------
 -----------
------------ (covers the grey line and starts to 'leave the scene') 
-----------
----------
---------
--------
-------
------
-----
----
--- (stops here)

Answer №1

Try animating an element from left 100% to left -75% (making it 25% visible!)
Check out the demo on jsBin

Take a look at this neat example that utilizes a small jQuery plugin sourced from here along with some standard CSS:

/**
 * inViewport jQuery plugin by Roko C.B. stackoverflow.com/questions/24768795/
 *
 * Returns a callback function with an argument holding
 * the current amount of px an element is visible in viewport
 * (The min returned value is 0 (element outside of viewport)
 * The max returned value is the element height + borders)
 */
;(function($, win) {
  $.fn.inViewport = function(cb) {
    return this.each(function(i,el) {
      function visPx(){
        var elH = $(el).outerHeight(),
            H = $(win).height(),
            r = el.getBoundingClientRect(), t=r.top, b=r.bottom;
        return cb.call(el, Math.max(0, t>0? Math.min(elH, H-t) : (b<H?b:H)));  
      }
      visPx();
      $(win).on("resize scroll", visPx);
    });
  };
}(jQuery, window));
// Let's rock!
$("h1 span").inViewport(function(px){
  $(this).toggleClass("animateLine", !!px);
});
p{height:900px;}/*FOR DEMO ONLY*/

h1{
  text-align:center;
}
h1 span{
  display:inline-block;
  position:relative;
  overflow:hidden;
}
h1 span:after,
h1 span:before{
  content:"";
  height:1px;
  width:100%;
  position:absolute;
  bottom:0px;
  left:0;
  transition: 3s;
}
h1 span:before{
  background:#ccc;
}
/* We'll animate this one to -75% */
h1 span:after{ 
  background:#000;
  left:100%;
}
h1 span.animateLine:after{
  left: -75%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h1><span>This is title 1</span></h1>
<p>1 Scroll down to find more titles</p>
<h1><span>This is title 2</span></h1>
<p>2 Scroll down to find more titles</p>
<h1><span>This is title 3</span></h1>
<p>3 Scroll down to find more titles</p>
<h1><span>This is title 4</span></h1>
<p>4 Scroll down to find more titles</p>
<h1><span>This is title 5</span></h1>
<p>5 Scroll down to find more titles</p>

Essentially, you need to set the pseudo :after to start at 100% left and then use the CSS3 class to trigger the transition to left -75% using the jQuery plugin as shown in the demo.

Additional information can be found here
Learn more about CSS3 animations while elements are in the viewport

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

Difficulty accessing `evt.target.value` with `RaisedButton` in ReactJS Material UI

My goal is to update a state by submitting a value through a button click. Everything works perfectly when using the HTML input element. However, when I switch to the Material UI RaisedButton, the value isn't passed at all. Can someone help me identif ...

Troubleshooting issues with Vue.js page routing

Currently, I am diving into the world of vue.js and encountering difficulties with setting up routing. My goal is to utilize templates stored in separate HTML files, rather than inline templates. The issue I'm facing is that the routing does not seem ...

Updating the image source using Javascript

I've implemented a timer in my JavaScript that animates something on a website. While everything is functioning perfectly, I am struggling to change an image whenever the animation is triggered. The script utilizes jQuery: if(options.auto && ...

What is the most effective method for altering HTML form components using PHP?

Can you explain how to manipulate and add form elements using PHP? Let's say I have a form stored in a PHP variable like this: $originalForm = ' <form method="post" action="whatever.php"> <input type="text" name="iamtextfield" id="text ...

Searching and selecting columns in React using Material-UI

Currently, I am using Material-UI data tables and have implemented a search functionality similar to this Codesandbox example, which only searches the Name/Food column. This is my existing code snippet: const [filterFn, setFilterFn] = useState({ fn: items ...

Navigate to a new webpage using a string of characters as a legitimate web address

When a user performs a search, I pass the search term as a string to direct them to a new page. How can I create a valid URL (e.g., remove spaces from the string)? It's crucial that the next page can recognize where any spaces were in the search word ...

Tips on securely passing dates in JavaScript without leaving them vulnerable to manipulation

The date and time stored in my database appear to be manipulated when fetched. Specifically, when I send this data directly via email from the server, the date and time change. When accessing the date on the client side, it appears as expected. However, i ...

Using PHP to globally access a JavaScript object named

I have a collection of CSS attributes stored in a MySQL database that are accessed using PHP. These attributes need to be accessible to JavaScript once the page has finished loading. To achieve this, I loop through each row and create a JavaScript object ...

Should each navigation item be enclosed within its own div element?

Currently, I am studying HTML + CSS and developing a website that requires a vertical navigation bar on the left side with four interactive elements. I'm wondering if it is customary to enclose each of these four elements in a div, or if there is a mo ...

Attempting to modify the array content using useState, but unfortunately, it is not functioning as expected

Starting out with react.js and trying to update an array's content using useState upon clicking a send-button, but it's not working as expected. Struggling with adding date and number in the row. Check image here Here's what I'm aiming ...

Photo positioned on top of the form with Bootstrap 5

I am working on creating a responsive webpage using Bootstrap, where I need to display a large image above a form. To manage the size of the image, I have placed it inside a "peek-view" container which allows scrolling both horizontally and vertically to v ...

Traversing an array of objects to extract and display the key-value pairs for each object

Here is an array I am working with: const cuisines = [ { african: "African" }, { american: "American" }, { arabian: "Arabian" }, { argentine: "Argentine" }, { asian: "Asian" }, { asian_fusion: "Asian Fusion" }, { australian: "Australi ...

What is the process for transferring an existing collection or data in Firestore to a subcollection?

My firestore database currently has the following structure with documents: root | |---transactions/... I am looking to transfer all transactions to a new subcollection as shown below: root | |---users/user/transactions/... Any suggestions on how I can a ...

Reacting to the dynamic removal of spaces

Is there a way to dynamically remove the space between removed chips and older chips in Material-UI when deleting one of them? <div className="row contactsContainer"> {contacts.map((contac ...

Is it possible to link a JavaScript object to a dropdown Select Option?

As I work on populating a select list with options using Javascript, I am looking for a way to attach a corresponding Javascript object to each option that can be easily accessed during the change event. While formulating this question, I began thinking a ...

The functionality of displaying an animated gif will not work when submitting a CakePHP ajax form before or after completion

I have exhaustively tested all possible scenarios using prototype, but I am unable to get my busy indicator to show no matter what I do. Despite cross-browser testing, I've had no luck. <?php echo $ajax->submit('Submit', array(' ...

ways to remove a specific category from a search

Recently, I came across some code that displays the title headings of the latest 10 WordPress posts from a database. However, I need to modify this code to exclude a specific category. Can anyone provide assistance with this? <?php require_once 'n ...

Implementing column resizing functionality similar to Bootstrap using inline CSS for HTML email layout

Utilizing Bootstrap CSS in an HTML page creates a responsive Grid layout system, allowing columns to expand or shrink based on the screen size. By declaring grid columns using classes like col-sm-12 and col-md-6, we can control the layout effectively. I a ...

Dragging objects on a map is done using jQuery and it causes them to bounce

Currently, I am working on implementing the JQuery Draggable feature. My idea is to create a map where I can attach image Divs to it dynamically using Jquery. So far, I have been successful in adding the Divs and making them draggable around the map effici ...

Identify when a click occurs outside specific elements

I've been searching for solutions to address this issue, but so far nothing has worked. Here is the JavaScript code I am using: var specifiedElement = document.getElementById('a'); document.addEventListener('click', function(eve ...