How to Make a Floating Footer Share Bar

Cnet Social Share

In a recent redesign of one of our websites, I was tasked with recreating a footer share bar that would dock/undock as the footer came into view. Now, I may not have done a tremendous job explaining that, so I’d like to point you to Cnet to give you an idea of what I wanted to implement. There is a screenshot to the right.

Do you notice the black share bar at the bottom of the window? Now, scroll to the bottom of the page and notice how the share bar docks at the top of the footer. Cool, right?

After a couple of hours, I was able to replicate this functionality closely and I ended up with this below.

Optiniche Social Share

Since it’s been so long since I have posted a code tutorial, I wanted to show you guys how to do this for your own website!

Let’s Start With HTML

Before we get into any Javascript or CSS, let’s go ahead and insert our HTML so that we can have something to work with. Now, since we are wanting to dock this share bar to our footer when the footer is within view, be sure to enter this code directly before the footer on your website. I have included a screenshot of to show proper placement of this code.

Here is the code:

<div class="socialFooterWrap">
	<div class="social-links">
		<div class="socialClose"></div>
		<div class="fb">
		<script src=""></script>
		<script type="text/javascript">
		document.write('<fb:like layout="button_count" show_faces="false" width="100"></fb:like>')

		<div class="googplus">
		<g:plusone size="medium"></g:plusone></div>
		<div class="stumble">
		<script src=""></script></div>
		<div class="tweet">
		<a href="" data-url="<?php the_permalink(); ?>" class="twitter-share-button" data-count="horizontal">Tweet</a><script type="text/javascript" src=""></script></div>

Let’s Get Pretty With CSS

The HTML alone doesn’t look that pretty, does it? So, let’s go ahead and spruce it up with some CSS! Below is the CSS that I used to style the social share footer:

.social-links { margin:20px 0px 10px 0px; height:35px; }
.fb { float: left; margin-right : 10px; }
.googplus { float: left; }
.tweet { float: left; }
.linkedinshare { float: left; margin-right : 10px; }
.stumble { float: left; margin-top: 2px; margin-right: 10px; }
.socialFooterWrap {
	width: 100%;
	position: relative;
	bottom: 0;
	left: 0;
	z-index: 999;
	display: none;
.social-links {
	margin: 0 auto;
	background: url(**Your Logo Image Here**) no-repeat 20px center #000;
	border-radius: 10px 10px 0px 0px;
	box-shadow: 0 -1px 1px #524c4c;
	border-top: 1px solid #999;
	width: 268px;
	max-width: 100%;
	position: relative;
	padding: 12px 0 0 140px;
.socialClose {
	background: url(;
	height: 31px;
	width: 31px;
	position: absolute;
	top: -14px;
	right: -14px;
	cursor: pointer;
.show {
	display: inline;
.fixedPosition {
	position: fixed;

This CSS should be able to be added anywhere. Now, we’re only missing some jQuery to make this bad boy work!

jQuery Makes Things Cool

First things first, you need to make sure that you have added the jQuery library to your website. Your theme may have an option to include it, but if not, here is an awesome snippet from Chris Coyier (Think CSS-Tricks) that will add the jQuery to your website. This snippet needs to be added to the functions.php file of your WordPress website.

if (!is_admin()) add_action("wp_enqueue_scripts", "my_jquery_enqueue", 11);
function my_jquery_enqueue() {
   wp_register_script('jquery', "http" . ($_SERVER['SERVER_PORT'] == 443 ? "s" : "") . "://", false, null);

Once you have added jQuery, you now need to create a custom.js file in your theme directory so that you can add some other javascript. Within that file, you are to add the code below:

 * author Remy Sharp
 * url
(function ($) {
    function getViewportHeight() {
        var height = window.innerHeight; // Safari, Opera
        var mode = document.compatMode;

        if ( (mode || !$.support.boxModel) ) { // IE, Gecko
            height = (mode == 'CSS1Compat') ?
            document.documentElement.clientHeight : // Standards
            document.body.clientHeight; // Quirks

        return height;

    $(window).scroll(function () {
        var vpH = getViewportHeight(),
            scrolltop = (document.documentElement.scrollTop ?
                document.documentElement.scrollTop :
            elems = [];

        // naughty, but this is how it knows which elements to check for
        $.each($.cache, function () {
            if ( && {

        if (elems.length) {
            $(elems).each(function () {
                var $el = $(this),
                    top = $el.offset().top,
                    height = $el.height(),
                    inview = $'inview') || false;

                if (scrolltop > (top + height) || scrolltop + vpH < top) {
                    if (inview) {
                        $'inview', false);
                        $el.trigger('inview', [ false ]);                        
                } else if (scrolltop < (top + height)) {
                    if (!inview) {
                        $'inview', true);
                        $el.trigger('inview', [ true ]);

    // kick the event to pick up any elements already in view.
    // note however, this only works if the plugin is included after the elements are bound to 'inview'
    $(function () {
 * jQuery Cookie Plugin
 * Copyright 2011, Klaus Hartl
 * Dual licensed under the MIT or GPL Version 2 licenses.
(function($) {
    $.cookie = function(key, value, options) {

        // key and at least value given, set cookie...
        if (arguments.length > 1 && (!/Object/.test( || value === null || value === undefined)) {
            options = $.extend({}, options);

            if (value === null || value === undefined) {
                options.expires = -1;

            if (typeof options.expires === 'number') {
                var days = options.expires, t = options.expires = new Date();
                t.setDate(t.getDate() + days);

            value = String(value);

            return (document.cookie = [
                encodeURIComponent(key), '=', options.raw ? value : encodeURIComponent(value),
                options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE
                options.path    ? '; path=' + options.path : '',
                options.domain  ? '; domain=' + options.domain : '',
        ? '; secure' : ''

        // key and possibly options given, get cookie...
        options = value || {};
        var decode = options.raw ? function(s) { return s; } : decodeURIComponent;

        var pairs = document.cookie.split('; ');
        for (var i = 0, pair; pair = pairs[i] && pairs[i].split('='); i++) {
            if (decode(pair[0]) === key) return decode(pair[1] || ''); // IE saves cookies with empty string as "c; ", e.g. without "=" as opposed to EOMB, thus pair[1] may be undefined
        return null;


  var settings = {
        speed: 350 //animation duration
      , easing: "linear" //use easing plugin for more options
      , padding: 10
      , constrain: false
    , $window = $(window)
    , stickyboxes = []
    , methods = {

            settings = $.extend(settings,opts);
            return this.each(function () {
              var $this = $(this);
              stickyboxes[stickyboxes.length] = $this;

        , remove:function(){
            return this.each(function () {
              var sticky = this;
              $.each(stickyboxes, function (i, $sb) {
                if($sb.get(0) === sticky){
                reset(null, $sb);
                stickyboxes.splice(i, 1);
                return false;

        , destroy: function () {
            $.each(stickyboxes, function (i, $sb) {
              reset(null, $sb);
            $window.unbind("scroll", moveIntoView);
            $window.unbind("resize", reset);
            return this;


  var moveIntoView = function () {
    $.each(stickyboxes, function (i, $sb) {
      var $this = $sb
        , data = $"stickySB");
      if (data) {
        var sTop = $window.scrollTop() -
          , currOffs = $this.offset()
          , origTop = -
          , animTo = origTop;
        //scrolled down out of view
        if (origTop < sTop) {
					//make sure to stop inside parent
          if ((sTop + settings.padding) > data.offs.bottom)
            animTo = data.offs.bottom;
          else animTo = sTop + settings.padding;
              {top: animTo}
            , settings.speed
            , settings.easing

  var setPosition = function ($sb) {
    if ($sb) {
      var $this = $sb
        , $parent = $this.parent()
        , parentOffs = $parent.offset()
        , currOff = $this.offset()
        , data = $"stickySB");
      if (!data) {
        data = {
            offs: {} // our parents offset
          , orig: { // cache for original css
                top: $this.css("top")
              , left: $this.css("left")
              , position: $this.css("position")
              , marginTop: $this.css("marginTop")
              , marginLeft: $this.css("marginLeft")
              , offset: $this.offset()
      //go up the tree until we find an elem to position from
      while (parentOffs && "top" in parentOffs
        && $parent.css("position") == "static") {
        $parent = $parent.parent();
        parentOffs = $parent.offset();
      if (parentOffs) { // found a postioned ancestor
        var padBtm = parseInt($parent.css("paddingBottom"));
        padBtm = isNaN(padBtm) ? 0 : padBtm;
        data.offs = parentOffs;
        data.offs.bottom = settings.constrain ?
          Math.abs(($parent.innerHeight() - padBtm) - $this.outerHeight()) :
      else data.offs = { // went to far set to doc
          top: 0
        , left: 0
        , bottom: $(document).height()
          position: "absolute"
        , top: Math.floor( - + "px"
        , left: Math.floor(currOff.left - data.offs.left) + "px"
        , margin: 0
        , width: $this.width()
      }).data("stickySB", data);

  var reset = function (ev, $toReset) {
    var stickies = stickyboxes;
    if ($toReset) { // just resetting selected items
      stickies = [$toReset];
    $.each(stickies, function(i, $sb) {
      var data = $"stickySB");
      if (data) {
            position: data.orig.position
          , marginTop: data.orig.marginTop
          , marginLeft: data.orig.marginLeft
          , left: data.orig.left
          , top:
        if (!$toReset) { // just resetting

  $window.bind("scroll", moveIntoView);
  $window.bind("resize", reset);

  $.fn.stickySidebar = function (method) {

    if (methods[method]) {
      return methods[method].apply(
        ,, 1)
    } else if (!method || typeof method == "object") {
      return methods.init.apply(this, arguments);



jQuery(document).ready(function($) {

	if( $.cookie('first') == null ) { 
		$.cookie( 'first', '1',  { expires: 28, path: '/' } );
	$('#footer').bind('inview', function (event, visible) {
	  if (visible == true) {
	    // element is now visible in the viewport
	  } else {
	    // element has gone out of viewport


There’s a lot of code right here, but let me explain. First, we have two plugins – a jQuery cookie plugin that makes it easy to work with cookies and a plugin that checks if element are in the viewport.

Then, within the document ready function, we do several things.

  1. Check if there is a cookie name socialFooter. If this cookie exists, that means that the visitor has clicked the hide button in the past. Therefore, we don’t want to show the social share footer.
  2. Second, we have a piece of code that will drop the socialFooter cookie if the close button is clicked.
  3. Lastly, we toggle between position fixed and position relative/station when #footer is in view. This is how we create the effect of the share bar ‘docking’ with the bottom when the footer is in view.


This code is not exactly trivial if you’ve never played around with jQuery. But, don’t be afraid since much of this is copy and paste. I did the searching for you :)

In this example, I left about 140px for your logo to be included in the social share footer. Be sure to include an image and update the CSS when you include this in your website.

Are you having issues or would like to suggest any features? Leave a comment below and let me know what’s on your mind.

Eric Binnion is a computer science student at Midwestern State University. When Eric is not online, he is usually volunteering in his community or enjoying time with his family. You can find Eric on Twitter.

Written by Eric Binnion

Eric Binnion is a computer science student at Midwestern State University. When Eric is not online, he is usually volunteering in his community or enjoying time with his family. You can find Eric on Twitter.



  • Chris Langille says:

    Awesome tut Eric! I’m definitely gonna give this a try!

  • Flash Buddy says:

    Great work. I grabbed your code and had it up and running in two minutes. I’m looking forward to experimenting some more with it; if only I had more hours in a day…

  • shamsudeen says:

    nice tutorial eric, i will give it a try on my blog.but may be you try and break it down a little more for a newbie.thanks.

    • Eric Binnion says:

      Thanks! It’s hard to break it down much more than that since themes are all different. You will have to edit your core files, or use some custom php function in Thesis/Genesis. I can answer a more specific question if you have one though. Let me know how it goes :)

      • Avinash D'Souza says:

        Hey Eric,

        Awesome sauce!

        I’m guessing that this tut is Standard theme focussed. How would I use this in Thesis?

  • Geoff says:

    HI Eric,
    I like the idea of this, and I got it all happening until the custom.js bit.
    “create a custom.js file in your theme directory so that you can add some other javascript. Within that file, you are to add the code below:”
    Is this simply a file named “custom.js” that includes all the following code and placed in the theme’s directory? This is how I read it, but it doesn’t work. Any ideas?

    • Eric Binnion says:

      Hi Geoff,

      What’s important here is the the Javascript I have given you, goes after the jQuery call, preferably in the footer. You could just add it to the footer within script tags, but using a separate file will allow the file to be cached between multiple page visits.

      With that said, create a file in your theme’s directory. Then in the footer, right before the closing body tag, add this:

      <script src="path to your custom.js file"></script>

      That should get it working.

  • Geoff says:

    Sorry,Eric, I can’t see the code

    • Eric Binnion says:

      Hey Geoff,

      I was an idiot and didn’t escape the HTML before adding it in the comment. DOH! You should be able to see the script call in my last comment now.

  • Robert says:

    It works like a charm. Just copy and paste in one of my website and let the sharebar running in 2 minutes. Thank you Eric

  • Chad Agrawal says:

    Hey Eric, this is a very in-depth tutorial. It shows you put a lot of work into it. Will probably spend a while going through the post. Right now, I’m using a scrolling share bar on the left of my blog. Hopefully this one will get more exposure.

  • Richard says:

    Great work was looking for something like this. looking forward to trying it out

  • fawad says:


    thanks for the great article. How do I use this on HTML website?


    • Eric Binnion says:

      This would be done by adding the HTML code above the footer in your HTML then adding the CSS and JS to your project.

  • Ali says:

    Thank you Eric, It works like a charm! tested it successfully.Now will implement in my site after some customization.Is there a way to disable the cookie?

  • Ali says:

    Or is there a way to clear the cookie automatically when the browsing session is closed?

    • Eric Binnion says:

      You’re wanting a session cookie. This can be implemented by not setting an expires date. Here is some example code.

      $.cookie('the_cookie', 'the_value');

      Notice that only the name of the cookie and value are present. There is no longer an expires date in this cookie. This cookie should clear as soon as the window or browser are closed.

      Does that help?

  • Ansh says:

    This is really in depth tutorial Eric.. thumbs up for the help… cheers