Sticky Stuff in SharePoint

Whether you are stuck in SharePoint or want to stick it to SharePoint or want to make things stick within SharePoint, sticky stuff in SharePoint is a hot topic.  I am going to focus on the latter.

What is sticky stuff?

More and more on the web you see web page components staying in a set location on the screen independent of how the page is being scrolled, or in the case of a footer, how short the page content is within a web page. Common sticky items are navigation bars, headers, contact us/chat now boxes,  sidebars and footers.

Sometimes the sticky item is “stuck” right away and there is no visual change as you scroll the page. Other sticky items have a starting position and then move and stick based on a page scroll. For example a web site has a 200 pixel tall header with a navigation bar underneath it. As the web page is scrolled the header scrolls away and the nav bar scrolls to the top of the page and remains there while the user continues to scroll down through the page content.

All of these sticky items can be implemented in SharePoint.

Sticky header (with or without navigation)

There is a big divide here for adding in a sticky header… will you be showing the SharePoint ribbon?  If it is an Intranet site the answer is likely yes.  If you are running a public facing brochureware type site, the answer is likely no.

Sticky header WITH the Ribbon

This is the easiest type of sticky element to add to your SharePoint site. This is because you can piggyback on the existing sticky aspect of the SharePoint ribbon.  OOTB, SharePoint is split into two panes – s4-ribbonrow and s4-workspace.  The s4-ribbonrow pane is fixed at the top of the web page and the content within s4-workspace scrolls separate from the ribbon.  Any web page components you add either above or within the s4-ribbonrow container will get the same fixed position treatment.

The following is a series of screenshots showing where content appears based on where you insert new HTML elements in the master page. Note in all of these examples the scroll bar remains connected only with s4-workspace and the size of the top pane changes as content is added to it.

Add HTML elements above or below the Suite Bar, but above and outside of the s4-ribbonrow container: 

HTML element inserted above the Suite Bar

 

HTML element added before the ribbon container

 

Add HTML elements within or under the s4-ribbonrow. Note that added content within or after this container affects other components and creates some UI issues.

HTML element added at the top of the ribbon container

(This is a H1 added at the bottom of the s4-ribbonrow)

HTML element added at the bottom of the ribbon container

 

HTML element added after and outside of ribbon container

 

The best option would be to add your custom HTML elements above the s4-ribbonrow container (not within it or after it).

  1. Open your custom master page file.
  2. Search for and locate the s4-ribbonrow ID. It is likely attached to a DIV tag.
  3. Add your custom HTML somewhere above and outside of the s4-ribbonrow HTML element.

Sticky header WITHOUT the Ribbon

If you have removed the ribbon or have code in place to not show the ribbon to certain levels of users, you can use traditional methods to add a sticky header.

  1. Open your custom master page file.
  2. Within the s4-workspace container, add your custom HTML header elements, adding a class or ID to the container.
    <div class="sticky-header">
    	<h1>This is a sticky header</h1>
    </div>
  3. In your custom CSS file, add the following style statement, making modifications as needed:
    .sticky-header {
      background: #000;
      width: 100%;
      height: 40px;
      position: fixed;
      top: 0;
    }
  4. At this point the header is stuck to the top of the web page, but showing on top of the web page content.
    Sticky header is on top of the page content
  5. Add another style statement to your custom CSS file that shifts the page content down based on the height of the header.
    #s4-workspace {
      margin-top: 40px;
    }

    Make adjustments to properly show header and content

You can alternatively add any SharePoint component that you want, such as the top nav bar (a.k.a. global navigation). Here is the result:

Top nav bar within sticky header HTML element

Sticky box – fixed

What was done above for “Sticky header WITHOUT the Ribbon” can be applied to any HTML element that you want located anywhere on the page.   All you have to do is modify the positioning.

  1. Open your custom master page file.
  2. Within the master page code, add your custom HTML element(s), adding a class or ID to the container. Because the HTML element will have fixed positioning on the page, it doesn’t  matter where you add the code.
    <div class="sticky-box">
    	<h1>This is a sticky box</h1>
    </div>
  3. In your custom CSS file, add the following style statement, making modifications as needed:
    .sticky-box {
      background: #000;
      padding: 8px;
      position: fixed;
      left: 10px;
      bottom: 10px;
    }

Sticky box – scroll then fix

A popular UI element on web pages these days is to have an HTML element nested in the page design, then as you scroll the page the nested item moves to a new location and stays there as you continue scrolling.  For this effect you are going to need to also use some jQuery or JavaScript.

The plan

You will be adding the sticky item to your master page and creating two different CSS classes and style statements for the sticky item. The first one will be for the static view when you first load the page. The second will be modifications that will be used when you start to scroll the page. jQuery can then be used to switch in the scroll class based on page scroll.

The code

  1. Open your custom master page file.
  2. Within the master page code, add your custom HTML element(s), adding a class or ID to the container. For this example I am adding the code below the Quick Launch (current navigation) but within the sideNavBox HTML element (which is present in seattle.master).
    <div class="sticky-box-static">
    	<h1>This is a sticky box</h1>
    </div>
  3. In your custom CSS file, add the following style statements, making modifications as needed:
    .sticky-box {
      background: #000;
      padding: 8px;
      margin-top: 20px;
      width: 130px;
    }
    
    #s4-workspace.scroll .sticky-box {
      position: fixed;
      top: 60px;
    }
    

    This is the result:
    Sticky box added to the side bar

  4. Now that the static version of the sticky box is in place, you can use a little jQuery to add in the other class on page scroll. Thanks to Chris Coyier’s post for the code bits. Add the following script to the BOTTOM of your master page file, before the closing BODY tag.
    <script type="text/javascript">
    	var wrap = $("#s4-workspace");
    
    	wrap.on("scroll", function(e) {
    
    	  if (this.scrollTop > 300 ) {
    	    wrap.addClass("scroll");
    	  } else {
    	    wrap.removeClass("scroll");
    	  }
    
    	});
    </script>
    

    This script watches for the page scroll to move to 300+ pixels from the top of the viewport. Once that happens, another CSS class (scroll) is being added to the s4-workspace container. The scroll class is referenced in our new CSS and adds the fixed positioning and sets a top pixel location for the fixed sticky box. If the page is scrolled back to less than 300 pixels, the added CSS class is removed.

  5. This is a jQuery script and in order for it to work you need  a reference to include the jQuery library. Add the following to the HEAD of your master page file. You can grab the latest version of this library path from Google.
    <script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Here is the result:

Script and CSS creates a fixed sticky box on scroll

Sticky box – scroll then fix: alternative code

The above technique relies on you knowing the exact position for where the sticky box hits the top on scroll and should start to stick. In this example it is 300 pixels. If your sticky box is in a location that can change based on surrounding content, you can still use this technique but with a slight change to the code.  In our existing example, if you added items to the Quick Launch bar you would need to modify the value (300) in the jQuery script.  This isn’t practical if the Quick Launch bar length is changing all of the time, such as when you navigate from page to page.

  1. Return to the jQuery script you added to the bottom of the master page.
  2. Replace the script with the following (thanks to Dustin Miller for the code tweaks):
    <script type="text/javascript">
    	var wrap = $("#s4-workspace");
    	var stickytop = $('.sticky-box').offset().top;
    
    	wrap.on("scroll", function(e) {
    
    	  if (this.scrollTop > stickytop ) {
    	    wrap.addClass("scroll");
    	  } else {
    	    wrap.removeClass("scroll");
    	  }
    
    	});
    </script>
    

Here is the result:

Script and CSS creates a fixed sticky box on scroll

The Suite Bar and ribbon make it look a little wonky because the class isn’t kicked in until the sticky box hits the top of the viewport.  If your design doesn’t include these elements, the result is much smoother:

Script and CSS creates a fixed sticky box on scroll

This final version also includes some tweaks to the CSS:

.sticky-box {
  background: #000;
  padding: 8px;
  width: 130px;
}
#s4-workspace.scroll .sticky-box{
  position: fixed;
  top: 0px;
}
.ms-core-navigation {
  margin-bottom: 20px;
}

Spice up your sticky stuff with CSS3 transitions

If the sticky version of an item needs to change in size or some other style, you can create a smoother transition using CSS3.

Using the last technique and code bits as a springboard, all that needs to be done is to modify the existing CSS:

.sticky-box {
  background: #000;
  padding: 8px;
  width: 130px;
  transition: all 1s ease;
}
.sticky-box h1 {
  transition: all 1s ease;	
}
#s4-workspace.scroll .sticky-box{
  position: fixed;
  top: 0px;
  background: blue;
}
#s4-workspace.scroll .sticky-box h1 {
  font-size: 20px;
  color: #fff;
}
.ms-core-navigation {
  margin-bottom: 20px;
}

Here is the result:

CSS3 transitions added to smoothly change sticky box styles

Sticky footer

Any pure CSS sticky footer solutions you find on the web will not work in SharePoint due to how it treats the s4-ribbonrow and s4-workspace containers.  The best thing to do is to use script, and Randy Drisgill has a solution posted.

What to do if your sticky stuff is under another element

Depending on where you add a sticky HTML element in your code, it is possible that another HTML element will appear on top of your sticky element. You can correct this easily with the z-index property in CSS. The trick is to understand how z-index works and not just slap in a z-index: 100000 like you see everywhere on the web.

HTML element stack order

As HTML elements are listed in the code, they are put in a stack.  It is like adding sheets of paper to pile one at a time.  The first piece of paper, or HTML element, is set on a table.  Then the second piece of paper, or second HTML element is placed next, and on top of it.  The third piece goes on top of the second, so on and so forth.

“Display” joins the party

When you are working with HTML elements, each one has a default display of inline or block.  A block element like a DIV forces it’s siblings to go on either side of the element.  It would be like spreading the three sheets of paper out on the table.  They are now next to each other, but they were still put down in an order.    If you set a negative margin on the second HTML element, it will slide on top of the first HTML element.  For our paper metaphor, you have just overlapped the second piece of paper partially over the first.

“Position” messes with your stuff

When you set absolute or fixed positioning, you are removing that HTML from the flow of the document so the surrounding HTML elements slide up and take the space the other element previously occupied. But the stack order is still intact. If you set a fixed position to element #1, element #2 is now on top of element #1, thus  potentially obscuring element #1.

Fix it with z-index

The default stack order can be altered in CSS using the z-index property.

.selector {
  z-index: 2;
}

The higher the z-index value, the higher in the stack order the element is.

What gets tricky about the stack order is when you introduce children elements. Each group of elements have their own stack order.  The following nested, numbered list shows the layering of elements and their children.  Note that each child list starts over with #1. For the paper metaphor, you would write on each existing piece of paper it’s respective children elements.

  1. Element A (first piece of paper)
    1. First child of element A (written on page 1)
    2. Second child of element A (written on page 1)
  2. Element B (second piece of paper)
    1. First child of element B (written on page 2)
    2. Second child of element B (written on page 2)
  3. Element C (third piece of paper)
    1. First child of element C (written on page 3)
    2. Second chid of element C (written on page 3)

If you want First child of element A to show on top of Element C, you have to change the layer order of the parent to force Element A to be on top of Element C. If you were to target the child element and alter the stack order, you would only be affecting the stack order of the children elements. Think back to writing the child elements on the pieces of paper – you can’t make the first child listed on page 1 sit on top of the 3rd page without shuffling the pages.

My head hurts

Z-index can be confusing and seemingly complicated on the surface, but if you remember how it works with the parent/child relationships you will be able to fix your stack order by targeting the right element.  Below the z-index property has been added to the .sticky-box class.

.sticky-box {
  background: #000;
  padding: 8px;
  position: fixed;
  left: 10px;
  bottom: 10px;
  z-index: 3;
}

One last thing…

If adding the z-index property to your CSS doesn’t fix the issue, you probably need to specify a position property on the element you are trying to layer your sticky stuff on top of.

.item-under-sticky-box {
  z-index: 2;
  position: relative;
}

What the future holds

Just as a head’s up, as it does not have wide browser support at the time of this writing, the CSS3 spec includes a new “sticky” value for the position property.  The Mozilla Developer Network has the best summary of what the sticky property will do:

“Sticky positioning is a hybrid of relative and fixed positioning.  The element is treated as relative positioned until it crosses a specified threshold, at which point it is treated as fixed positioned.”

In the future you can use sticky positioning to create pure CSS sticky stuff solutions and drop any jQuery or JavaScript you previously used.