Vertically Align on Variable Height objects

Vertically Align the Navigation…

Recently a client requested a change in their company portfolio navigation.  I thought on the outset this would be easy. However, it wasn’t quite easy as I had hoped.

To cover the background: the site is a wordpress site, the portfolio is part of the proprietary theme, using a proprietary function to call navigation: <?php ci_pagination(); ?> This old navigation which sat at the bottom of the portfolio looked like this:

Example of the Navigation 

 

The client request was for a simple directional arrows that vertical align (justified centrally) on either side of the portfolio.

Considerations

My first considerations were that the website is responsive, and depending on the screen resolution the portfolio content would display differently (images would resize).  The second consideration, on mobile devices, the portfolio is 1 image wide, and having a navigation aligned centrally would be confusing. Lastly, cross browser compatibility is always a must.

Setting out

To begin with, I had been looking at the existing code I saw that the pagination function was below and outside of the portfolio containing <div>  which would make it a little tricky to vertically align to.

I first needed to only get arrows instead of the numbered pages. I did this by replacing pagination with previous and next pages function from the wordpress codex:  Function Reference/previous posts link and using &#9665;  and &#9655;  for the respective arrows: ◁ ▷

<nav id="porfolioNav" class="navigation">
  <div class="alignleft"><?php previous_posts_link('&#9665;') ?></div>
  <div class="alignright"><?php next_posts_link('&#9655;') ?></div>
</nav><!-- #portfolioNav -->

The concept I had was to vertically align the navigation 50% down from the porfolio top… simple really.  However, in CSS alone I was having nightmares, one minute I had it working in Chrome next it was fouling up in Microsoft Edge/Internet Explorer (no surprises).

Then to my horror, when I had it working on the navigation I was seeing that it was throwing off the logo from the header given the parent element was doing something like this:

.ParentElement { /* my class was different but not so obvious in this situation */
  width: 100%; 
  height:100%; 
}

This was, not acceptable!  I did not want to have to compensate for adjustments to the code for a secondary change.

Another observation I made was that vertical align in percentage does not work, yet static values do not accommodate for change in window size.

Solution

I decided to use jQuery to help me align the #portfolioNav  ID to the parent.   I used the jQuery animate() function to position the element into place with motion. This served two fold, both aesthetically more pleasing as it loads, but mostly also aided with the default delay, I found some browsers were having issues on first load using the standard jQuery css()  function due to the delay in images rendering the height would load later than the page load.

I also later realised that I would still require the ci_pagination()  for mobile devices, so left it loading as usual but used the screen resolution to regulate which navigation would be visible depending on device/screen size in CSS.

Vertically Align the Navigation on the Portfolio

 

jQuery

The following jQuery function simply sets the pixel distance from the top of the overall height of the #portfolioNav  parent element and divides by two, and returns the CSS top distance for the child element.  As you can see I apply the CSS value to the DIV elements not the specific classes, this saves for repetition in the .alignleft  and the .alignright  classes as for now, I know there are only 2 child classes within the #portfolioNav  ID.

jQuery(window).ready(function($) {
	"use strict";

	/* -----------------------------------------
	 Vertically align Menus
	 ----------------------------------------- */
	$.fn.navVcenter = function(parent) {
		if (parent) {
			parent = this.parent();
		} else {
			parent = window;
		}
		this.animate({
			"top": ((($("#portfolioNav").parent().height() - this.outerHeight()) / 2 )  + "px")
		});
	return this;
	}
	$("#portfolioNav > div").navVcenter(true);		
});

This jQuery function loads inside a JavaScript file called: scripts.js  in my theme.   However, if you have no other java-script files that load in your theme you could create something similar by doing the following into your functions.php file:

function my_theme_scripts() {
    wp_enqueue_script( 'my-javascript', get_template_directory_uri() . '/js/my-javascript.js', array( 'jquery' ), '1.0.0', true );
}
add_action( 'wp_enqueue_scripts', 'my_theme_scripts' );

PHP

As discussed earlier, I have chosen to load both navigation elements in the page, but using CSS I will be hiding elements depending on screen resolution.  Note the #portfolioNav ID appears inside the  #portfolio.row  while the  .sectNavBot class navigation appears below.

         <?php endwhile; endif; ?> 
<!-- This where the porfolio ends being listed I place this here so you have a reference point -->

		 <nav id="portfolioNav" class="navigation">
			<div class="alignleft"><?php previous_posts_link('&#9665;') ?></div>
			<div class="alignright"><?php next_posts_link('&#9655;') ?></div>
		</nav><!-- #portfolioNav -->

		 </div><!-- #portfolio .row -->

      <div class="row">
         <div class="col-xs-12 sectNavBot">
		<?php ci_pagination(); ?>
         </div>
      </div> <!-- #row -->

 

CSS

Using the: @media {min-width:  I was able to hide the bottom navigation and set the parameters for the #portfolioNav ID in place.  Using the reverse width (bottom) I was able to then accommodate for smaller screens and show the lower navigation and hiding the #portfolioNav ID.

@media (min-width: 1065px){  /* this is the width of the screen that the arrows would ordinarily disappear on the page */
	.sectNavBot{
		display: none;  /* hide the bottom navigation while the screen width permits the #portfolioNav */
	}
	#portfolioNav {
		margin: 0 auto;
		max-width: 1140px; /* this is relevant to my portfolio element perhaps yours may be a different width */
		width: 100%;
		position: relative;
	}
	#portfolioNav .alignleft {
		position: absolute;
		left: -50px; /* position arrow 50px before (or to the left of the initial position) of the portfolio */
	}

	#portfolioNav .alignright {
		position: absolute;
		right: -50px; /* position to the right of the portfolio by 50px beyond it's width */
	}

	#portfolioNav a {
		font-size: 300%;  /* this makes the arrows much larger than the existing text size on the site, I found 300% was a good size */
		font-weight: bold;
		display:inline-block;
	}
}
@media (max-width: 1064px){  /* this is the remaining width if the arrows cannot be displayed */
		#portfolioNav{
		display: none;  /*hide the #portfolioNav element */
	}
}

I hope you find this blog post helpful!

Leave a Reply