Scroll Indicator in WordPress

Adding custom jQuery to your Wordpress site. A tutorial using the Scroll Indicator.


After posting the tutorial on creating a simple scroll indicator, I have received some comments and emails about adding it to a Wordpress site. This post is intended as a guide for doing so.

The Steps

To add the scroll indicator to your Wordpress site, you will need to do a few things:

  • Create a .js file with Wordpress-prepared jQuery
  • Add the CSS to your Wordpress theme CSS file
  • Add the HTML to your site where you want the arrow to appear
  • Enqueue the .js file within the Wordpress "header.php" file and activate jQuery

A Wordpress-prepared jQuery File

Before you upload any files to Wordpress, there is one specific change that needs to be made to the jQuery listed in the Scroll Indicator tutorial. We need to change each instance of "$" to "jQuery". This is because Wordpress runs jQuery in a "No Conflict" mode -- using "$" to call anything in Wordpress using jQuery simply won't work.

Below is the updated jQuery. Take this and save it as a .js file. We will use this to upload to Wordpress. For this tutorial, I will name my file "rs_scroll.js". This first function manages the arrow, the second is borrowed from CSS-Tricks to enable smooth scrolling.

jQuery(window).scroll( function(){
  var topWindow = jQuery(window).scrollTop();
  var topWindow = topWindow * 1.5;
  var windowHeight = jQuery(window).height();
  var position = topWindow / windowHeight;
  position = 1 - position;
  jQuery('.arrow-wrap').css('opacity', position);

jQuery(function() {
  jQuery('a[href*=#]:not([href=#])').click(function() {
    if (location.pathname.replace(/^\//,'') == this.pathname.replace(/^\//,'') && location.hostname == this.hostname) {
      var target = jQuery(this.hash);
      target = target.length ? target : jQuery('[name=' + this.hash.slice(1) +']');
      if (target.length) {
          scrollTop: target.offset().top
        }, 1000);
        return false;

Once you have created our .js file, we need to add it to Wordpress. To do so, you will need to add the file to the theme directory of your site. Use your standard FTP client to simply upload the file to your theme. It is best to do this to the "js" folder of the theme you are editing.

Adding the CSS

This part is the simplest. To add the CSS to your Wordpress page, you just need to copy and paste the below into the CSS file of your Wordpress theme. To do so, log in to your Wordpress site and go to the Wordpress theme editor: Appearance > Editor. Once there, Wordpress should default to showing the style.css file for editing. Double-check to make sure this is the file that is open and, if not, click on the item labeled "stylesheet" on the right of the editor.

Once you have the stylesheet open for editing, copy the below CSS and paste it into the stylesheet file of your Wordpress page. Make sure you find a good spot in the file for adding it to keep the file organized.


/* the wrapper element that will become the outer circle */
.arrow-wrap {
  padding:4em 2em;
  box-shadow:0px 0px 5px 0px #333;

/* a triangle to make the main part of the arrow. Adjust the border-color to fit your needs */
.arrow {
  width: 0px;
  height: 0px;
  border-style: solid;
  border-width: 3em 3em 0 3em;
  border-color: #ffffff transparent transparent transparent;
  -webkit-transform:rotate(360deg);/* added for better anti-aliasing on webkit browsers */

/* a pseudo element arrow placed on top of the other one with the same color as the wrapper */
.arrow:after {
  width: 0px;
  height: 0px;
  border-style: solid;
  border-width: 3em 3em 0 3em;
  border-color: #111 transparent transparent transparent;
  -webkit-transform:rotate(360deg);/* added for better anti-aliasing on webkit browsers */

@-webkit-keyframes arrows {
    0% { top:0; }
    10% { top:12%; }
    20% { top:0; }
    30% { top:12%; }
    40% { top:-12%; }
    50% { top:12%; }
    60% { top:0; }
    70% { top:12%; }
    80% { top:-12%; }
    90% { top:12%; }
    100% { top:0; }
  .arrow-wrap .arrow {
    -webkit-animation: arrows 2.8s 0.4s;
    -webkit-animation-delay: 3s;


As with any bit of code, you may need to adapt this to fit exactly how your site is structured. The arrow as defined above is set to appear at the top of its container. Important to note, as well, is that it will appear at the top of closest level container with a position set to "relative".

Adding the HTML

Adding the HTML is also pretty straightforward. Just like with adding the CSS, you can use the Wordpress theme editor. Here, however, you need to find the proper file that corresponds to the page you want to edit. For this, you need to have a bit of an understanding of the HTML structure of your site. Find the container in which you want to place the arrow, and paste the following code there.

  <a class="arrow-wrap" href="#the id of the element to which you want to scroll">
    <span class="arrow"></span>

Note that you need to edit the 'href=""' target to fit your site. Simply place the id (with "#" preceding it) of the HTML element to which you want the button to scroll.

Enqueue the jQuery file

The last step is telling Wordpress that you have want it to use the rs_scroll.js file that you just uploaded. By now you should see the arrow on your site, but scrolling and clicking on it won't work the way you want them to.

To enqueue the js file, we need to add a single line of code to the "header.php" file of your theme. In the Wordpress theme editor again, find the "header.php" file of your theme. You want to add the following line of code within the "head" section of the HTML (before the "/head" marker).

 <?php wp_enqueue_script('rs_scroll', get_stylesheet_directory_uri() . '/js/rs_scroll.js', array('jquery')); ?>

This will tell Wordpress to include the js file we just uploaded. It will look in the directory for the "js" folder within your theme directory and load the "rs_scroll.js" file. It also indicates that the file requires jQuery to run, so Wordpress will include jQuery to the page as well, if it isn't already loaded.

Wrapping Up

This tutorial was a bit more on the advanced side of things, so feel free to ask for clarification or help in the comments below. I hope that it touched on the specific parts that can cause trouble within Wordpress (jQeury noConflict mode and enqueueing scripts).

As always, happy coding.

12 thoughts on “Scroll Indicator in WordPress

  • Hi

    I have implemented the JS and the CSS fine I am just having a problem placing the HTML onto the page, I have tried placing in a text box in the page but it’s not working (the code dissapears and changes to 2   ?), could you help guiding me to where I might add the code for the homepage for the site? Many many thanks in advance

    • Hi James,

      Where are you currently adding the HTML to your page? Are you doing so in the theme editor (the PHP file for the page) or within the WordPress posts editor? Make sure you are adding it to the actual PHP file — to do so, go to the wordpress interface and go to Apprearance > Editor and then find the PHP file that corresponds to the page on which you wish for the arrow to appear. If you need more help with finding exactly where to add the code, feel free to shoot me an email :)

  • Pingback: Scroll Indicator | Rob Sawyer Design

    • Hi! Because the arrow sizes are all defined with ems, this means that we only have to change one value to have it propagate to the entire size of all the elements in the arrow. The magic line of code is:

      .arrow-wrap { font-size: 0.5em;}

      Just change the size here (e.g. “0.3em”) and it will change the size of the arrow. Be sure to continue using ems!

  • Hey Rob,

    Thanks a bunch for sharing this awesome walk-through and info! I got it set up fairly easy on a website I’ve been working on for a client, though I came across a curious bug after implementing the jQuery script. For anyone else reading this, keep in mind that this is for a theme (namely Salient in my case) that already has smooth scrolling already implemented, and there’s also no need to implement the second half of Rob’s jQuery script if that’s the case.

    In effect, after assigning the href target to a span as originally implemented in your code, I discovered that somehow, after loading, the page would immediately trigger the href pointing to the target span and automatically scroll down to that point.

    That might have had to do with the way I implemented the script, but I came up with a fairly simple fix. I simply switched out the id of the target span for a random id (using the .attr method) that isn’t referenced at all and wrapped it in a click event so that it would automatically switch over to the active target id as soon as someone clicked the arrow, like so:

    jQuery(document).ready(function($) {
    $(window).scroll( function(){
    var topWindow = $(window).scrollTop();
    var topWindow = topWindow * 1.5;
    var windowHeight = $(window).height();
    var position = topWindow / windowHeight;
    position = 1 – position;
    $(‘.arrow-top-wrap’).css(‘opacity’, position);
    // “pre-trigger” is not referenced following document-ready, but “below-fold” (the pre-referenced href id), is set and triggered following a click event…
    $(‘.arrow-top-wrap’).on(‘click’, function() {
    $(‘#pre-trigger’).attr({ “id” : “below-fold”});

    Anyhow, I hope that helps someone else should they come across a similar issue. Thanks again for your contribution, Rob! =)

  • Hi Rob,
    Thanks for sharing this script with a great amount of detail!

    I’ve integrated all the necessary bits of code, but the arrow seems to be stuck at the top of the page. I’ve tried relocating the HTML code but it doesn’t want to seem to place itself at the top of my 2nd section.

    What could I be doing wrong? What should I be looking for?
    Here’s the site I’m trying to implement it on:

    Thank you,

    • Hey! Am glad you are seeing some use out of it.

      For you, the arrow is showing up at the top of the page because the parent container of the arrow needs to be set to ‘position: relative;’. Because the arrow is positioned _absolutely_, it will be placed based on the closest parent container with a relative or absolute position. Since the container you have it placed in is neither, the arrow is defaulting to being placed based on the full page.

      To fix, simply add the ‘position: relative;’ declaration to your section with the id of ‘map’.

      Hope that helps :)

  • Awesome guide! Perhaps you should make this a plugin? :)

    What can I change to make the arrow show up longer? I would like it to stay stronger opacity for a slightly longer period of time, or begin the fading process a bit later?

    • Hey! Thanks. Will definitely think about making this a plugin at some point.

      As for customizing the opacity changing behavior, there are different methods depending on what you want to do. If you want to make the opacity change more gradual, you just need to modify this line of the jQuery (line 7) `var topWindow = topWindow * 1.5;`. Important there, is the `1.5` value. What it is doing, is modifying the rate at which the scrolling changes the opacity. A higher value means the arrow will become transparent more quickly. 1, for example, means it reaches 0 opacity exactly as it hits the top of the page; 2 would mean it would reach 0 at the half-way mark.

      To delay the opacity change, the easiest thing to do is just increase the opacity above `1`. That means that, as you scroll the page, the arrow will have an opacity that is 1 or greater for a while (thus being fully opaque). The line you need to change here is (line 15) `position = 1 – position;`. Pretty simply, you can just do something like: `position = (1 – position) + 0.5;`. This means as you start scrolling, the arrow will first have an opacity of 1.5, thus staying opaque for longer.

      Likely you would need to modify both of these values to get the behavior working for you. Feel free to ask more if you need further clarification! Here is a link to a forked codepen :)

  • Hey Rob,

    Thanks heaps for this, I’ve followed your steps and added it into the site and it’s perfect.
    Keep up the good work and thanks for sharing.

    Cheers :)

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>