Make the "⇤ Back to Start" Button Pulse When Visible (jQuery + CSS)

Last updated 3 weeks, 4 days ago | 41 views 75     5

Tags:- HTML JQuery CSS

Nineth page link: Dynamic Color Changing Scroll Progress Bar in jQuery

Yessss let's take this UX to the next cosmic level


✨ What We'll Add:

When the .back-to-start button appears,
it will gently pulse (grow/shrink) to grab attention.

✅ Smooth
✅ Eye-catching
✅ Subtle (not annoying)


Step 1: Add Pulse Animation in CSS

@keyframes pulse {
  0% {
    transform: scale(1);
    opacity: 1;
  }
  50% {
    transform: scale(1.1);
    opacity: 0.8;
  }
  100% {
    transform: scale(1);
    opacity: 1;
  }
}

/* Apply pulse only when active */
.back-to-start.pulsing {
  animation: pulse 1.5s infinite;
}

✅ This defines a soft grow/shrink loop every 1.5 seconds.


Step 2: Update jQuery to Control the Pulse Class

Inside your updateBackToStartButton() function,
add or remove the pulsing class dynamically.

function updateBackToStartButton($wrapper) {
    var scrollLeft = $wrapper.scrollLeft();
    var scrollWidth = $wrapper.get(0).scrollWidth - $wrapper.width();
    var $backButton = $wrapper.find('.back-to-start');

    if (scrollLeft > (scrollWidth * 0.2)) { // scrolled >20%
        $backButton.fadeIn();
        $backButton.addClass('pulsing'); // Start pulsing
    } else {
        $backButton.fadeOut();
        $backButton.removeClass('pulsing'); // Stop pulsing
    }
}

Key:

  • When visible, add .pulsing = animation starts

  • When hidden, remove .pulsing = animation stops


Full Working Example

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Make the "⇤ Back to Start" Button Pulse When Visible (jQuery + CSS)</title>
  <style>
    .table-wrapper {
	  overflow-x: auto;
	  max-width: 100%;
	  border: 2px solid #ccc;
	  margin: 20px 0;
	  padding-top: 30px;
	  position: relative;
	}

	.scroll-notice {
	  position: absolute;
	  top: 0;
	  left: 0;
	  background: #f9f9f9;
	  padding: 6px 10px;
	  font-size: 14px;
	  color: #555;
	  font-style: italic;
	  white-space: nowrap;
	  z-index: 10;
	  display: none;
	}

	.scroll-progress {
	  height: 4px;
	  background: #4caf50; /* initial green */
	  width: 0%;
	  position: absolute;
	  top: 28px;
	  left: 0;
	  transition: width 0.2s ease, background 0.4s ease;
	  z-index: 5;
	}

	table {
	  border-collapse: collapse;
	  width: 100%;
	  min-width: 600px;
	}

	th, td {
	  border: 1px solid #aaa;
	  padding: 8px 12px;
	  text-align: left;
	}
	
	.back-to-start {
	  position: absolute;
	  bottom: 10px;
	  right: 10px;
	  background: #4caf50;
	  color: #fff;
	  padding: 8px 14px;
	  font-size: 14px;
	  border-radius: 20px;
	  cursor: pointer;
	  box-shadow: 0 2px 5px rgba(0,0,0,0.2);
	  transition: background 0.3s;
	  z-index: 20;
	}

	.back-to-start:hover {
	  background: #388e3c;
	}
	
	@keyframes pulse {
	  0% {
		transform: scale(1);
		opacity: 1;
	  }
	  50% {
		transform: scale(1.1);
		opacity: 0.8;
	  }
	  100% {
		transform: scale(1);
		opacity: 1;
	  }
	}

	/* Apply pulse only when active */
	.back-to-start.pulsing {
	  animation: pulse 1.5s infinite;
	}
  </style>
  <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
</head>
<body>
<div class="table-wrapper">
  <div class="scroll-notice">Scroll to view ➡️</div>
  <div class="scroll-progress"></div>
  <div class="back-to-start" style="display: none;">⇤ Back to Start</div>
	<table>
	  <tr>
		<th>Product</th><th>Price</th><th>Stock</th><th>SKU</th><th>Category</th><th>Brand</th>
	  </tr>
	  <tr>
		<td>Phone</td><td>$699</td><td>Available</td><td>PH1234</td><td>Electronics</td><td>Samsung</td>
	  </tr>
	  <tr>
		<td>Laptop</td><td>$999</td><td>Available</td><td>LT5678</td><td>Electronics</td><td>Dell</td>
	  </tr>
	</table>
</div>

<script>
$(document).ready(function() {
    $("table").each(function() {
        var columnCount = $(this).find('tr:first-child td, tr:first-child th').length;

        if (columnCount > 5) {
            if (!$(this).parent().hasClass('table-wrapper')) {
                $(this).wrap("<div class='table-wrapper'></div>");
                $(this).before('<div class="scroll-notice" style="display:none;">Scroll to view ➡️</div><div class="scroll-progress"></div><div class="back-to-start" style="display:none;">⇤ Back to Start</div>');
            }
        }
    });

    function updateScrollNotices() {
        $(".table-wrapper").each(function() {
            var $wrapper = $(this);
            var $table = $wrapper.find('table');
            var $notice = $wrapper.find(".scroll-notice");

            if ($table.outerWidth() > $wrapper.width()) {
                $notice.show();
            } else {
                $notice.hide();
            }
        });
    }

    function updateProgressBar($wrapper) {
        var scrollLeft = $wrapper.scrollLeft();
        var scrollWidth = $wrapper.get(0).scrollWidth - $wrapper.width();
        var progressPercent = (scrollLeft / scrollWidth) * 100;
        var $progress = $wrapper.find('.scroll-progress');

        $progress.css('width', progressPercent + "%");

        // Dynamic color change
        if (progressPercent <= 50) {
            $progress.css('background', '#4caf50'); // Green
        } else if (progressPercent > 50 && progressPercent <= 80) {
            $progress.css('background', '#ffeb3b'); // Yellow
        } else {
            $progress.css('background', '#f44336'); // Red
        }
    }

    function updateBackToStartButton($wrapper) {
    var scrollLeft = $wrapper.scrollLeft();
    var scrollWidth = $wrapper.get(0).scrollWidth - $wrapper.width();
    var $backButton = $wrapper.find('.back-to-start');

    if (scrollLeft > (scrollWidth * 0.2)) { // scrolled >20%
        $backButton.fadeIn();
        $backButton.addClass('pulsing'); // Start pulsing
    } else {
        $backButton.fadeOut();
        $backButton.removeClass('pulsing'); // Stop pulsing
    }
}

    updateScrollNotices();

    $(window).on('resize', function() {
        updateScrollNotices();
    });

    $(".table-wrapper").each(function() {
        var $wrapper = $(this);
        var $notice = $wrapper.find(".scroll-notice");
        var $backButton = $wrapper.find(".back-to-start");
        var timer = null;

        $wrapper.on('scroll', function() {
            if ($notice.is(":visible")) {
                if (timer) {
                    clearTimeout(timer);
                }
                timer = setTimeout(function() {
                    $notice.fadeOut();
                }, 3000);
            }

            updateProgressBar($wrapper);
            updateBackToStartButton($wrapper);
        });

        // Back to Start click
        $backButton.on('click', function() {
            $wrapper.animate({scrollLeft: 0}, 600);
        });

        // Initial setup
        updateProgressBar($wrapper);
        updateBackToStartButton($wrapper);
    });
});
</script>
</body>
</html>

Full Behavior Summary

Action Result
User scrolls right Button fades in & starts pulsing
User scrolls back left Button fades out & pulse stops

What Users See:

  • Button smoothly appears.

  • Button gently pulses, catches eye naturally.

  • Button stops pulsing when hidden — no unnecessary CPU drain!


UX Tips:

  • Pulse speed:
    Adjust 1.5s in animation: pulse 1.5s infinite;
    (slower for softer feeling, faster for urgency)

  • Mobile consideration:
    On very small screens, maybe use a slightly smaller pulse (scale(1.05)).


Common Pitfalls:

  • Too aggressive scaling (scale >1.2) looks silly or cartoonish.

  • Missing removeClass('pulsing') = animation keeps running invisibly.

  • Forget smooth transitions — that's why we use opacity too!


Final Result:

✅ Wide table with scroll notice
✅ Scroll progress bar changing colors
✅ "Back to Start" button that pulses beautifully when active!

Your table UI will look and feel like a million bucks now! ✨