1

I am trying to figure out the best method for moving my logo into the center of the main nav which is an unordered list (preferably as a new list item), at sizes above 980px.

I'm using a WordPress theme called Understrap, which is similar to the blank Underscores theme with Bootstrap baked-in. It uses wp-bootstrap-navwalker for navs, and the logo is uploaded through customizr (the client needs to be able to change the logo through the customizr UI, and set menu items through the dash, so a static solution isn't really do-able).

I have a solution, but I am not sure if it's the best way to go. Something definitely FEELS wrong about it.

The method I used was to move div#logo-wrapper from the parent div, into the main nav "ul", using 'insertAfter' with jQuery.

After that, I added a function that refreshes the browser at window resize, because simply appending/prepending, or using insertAfter doesn't work when the user resizes their browser.

My jQuery

jQuery(document).ready(function() {

  if($(window).width() > 980)
  {  jQuery("#logo-wrapper").insertAfter(".navbar-nav li:eq(2)");}
    else{

    }
});

$(window).bind('resize', function(e)
{
  if (window.RT) clearTimeout(window.RT);
  window.RT = setTimeout(function()
  {
    this.location.reload(false); /* false to get page from cache */
  }, 100);
});


My Logo PHP
In my header.php file I wrapped all of the site's branding php in a div called "#logo-wrapper"

<div id="logo-wrapper">
<button class="dev-navbar-toggler-button navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNavDropdown" aria-controls="navbarNavDropdown" aria-expanded="false" aria-label="Toggle navigation">
  <span class="dev-navbar-toggler-icon navbar-toggler-icon"></span>
</button>
  <?php if ( ! has_custom_logo() ) { ?>

    <?php if ( is_front_page() && is_home() ) : ?>

      <h1 class="dev-navbar-brand navbar-brand mb-0"><a rel="home" href="<?php echo esc_url( home_url( '/' ) ); ?>" title="<?php echo esc_attr( get_bloginfo( 'name', 'display' ) ); ?>"><?php bloginfo( 'name' ); ?></a></h1>

    <?php else : ?>

      <a class="dev-navbar-brand-lnk navbar-brand" rel="home" href="<?php echo esc_url( home_url( '/' ) ); ?>" title="<?php echo esc_attr( get_bloginfo( 'name', 'display' ) ); ?>"><?php bloginfo( 'name' ); ?></a>

    <?php endif; ?>
    <?php } else {
    the_custom_logo();
  } ?>
</div>

By doing this I can successfully move my div#logo-wrapper that wraps my logo options, link, image, and fallback text into the Main Nav's "ul", after the 3rd "li". I moved the HTML element this way, because I couldn't quite nail it with CSS. Basically every positioning technique I tried seemed more janky than manipulating the DOM (I could be wrong, but I tried every CSS trick could think of).

First problem:
As you can see I am still basically moving the entire div#logo-wrapper that I wrapped my php with, into the "ul" because I couldn't figure out how to move the logo link into a newly created "li", after the 3rd "li". It would be nice to at least move it into a new "li" instead of it being moved by itself.

Second problem:
I would like to figure out a way to move the div#logo-wrapper to the center of the "ul", no matter how many new list items are added, instead currently moving it into place after the 3rd "li". I was thinking of trying this with the use of a modulus or something mathematical with JS.

Third Problem:
I really don't like that I have the browser refreshing every time the page is resized, that will get annoying. I just need the script to fire at only sizes above 980px, and then go back to the way it was below 980px. Just like a normal CSS media query.

CSS Issues vs. JS Issues
I only want this to happen at desktop, so it seems like CSS would be the way to go, but I could never get it to sit as perfect as this does when it's apart of the list. With CSS, the biggest problems were that the positioning would slip, or it wouldn't look the same in all browsers, or if a new menu item was added by the client, the whole menu would slip and be off, making the whole nav look and act poorly. So JS seemed like the cleanest way to do this while keeping everything in tact.

Question:
To simplify my question, I know there has to be simple way to achieve this. It's too common of a problem, but I haven't found any definite answers online for specifically achieving this. Does anyone know of a simple way to do this with either Javascript, CSS, or just through Nav Walker with PHP.

My Full Header PHP

<?php
/**
 * The header for our theme.
 *
 * Displays all of the <head> section and everything up till <div id="content">
 *
 * @package understrap
 */

$container = get_theme_mod( 'understrap_container_type' );
?>
<!DOCTYPE html>
<!--[if IE 6]>
<html id="ie6" <?php language_attributes(); ?>>
<![endif]-->
<!--[if IE 7]>
<html id="ie7" <?php language_attributes(); ?>>
<![endif]-->
<!--[if IE 8]>
<html id="ie8" <?php language_attributes(); ?>>
<![endif]-->
<!--[if !(IE 6) | !(IE 7) | !(IE 8)  ]><!-->
<html <?php language_attributes(); ?>>
<head>
  <meta charset="<?php bloginfo( 'charset' ); ?>">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <meta name="mobile-web-app-capable" content="yes">
  <meta name="apple-mobile-web-app-capable" content="yes">
  <meta name="apple-mobile-web-app-title" content="<?php bloginfo( 'name' ); ?> - <?php bloginfo( 'description' ); ?>">
  <link rel="profile" href="http://gmpg.org/xfn/11">
  <link rel="pingback" href="<?php bloginfo( 'pingback_url' ); ?>">
  <?php wp_head(); ?>
</head>

<body <?php body_class(); ?>>

<div class="hfeed site" id="page">


  <!-- ******************* The Navbar Area ******************* -->

  <div class="dev-nav-wrapper wrapper-fluid wrapper-navbar" id="wrapper-navbar">

    <a class="dev-scrn-skpcntnt-rdr-lnk skip-link screen-reader-text sr-only" href="#content"><?php esc_html_e( 'Skip to content',
    'understrap' ); ?></a>

    <nav class="dev-navbar-tggl navbar navbar-toggleable-md navbar-inverse bg-inverse">

    <?php if ( 'container' == $container ) : ?>
      <div class="dev-nav-container container">
    <?php endif; ?>
      <div id="logo-wrapper">
        <button class="dev-navbar-toggler-button navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNavDropdown" aria-controls="navbarNavDropdown" aria-expanded="false" aria-label="Toggle navigation">
          <span class="dev-navbar-toggler-icon navbar-toggler-icon"></span>
        </button>

          <!-- Your site title as branding in the menu -->
          <?php if ( ! has_custom_logo() ) { ?>

            <?php if ( is_front_page() && is_home() ) : ?>

              <h1 class="dev-navbar-brand navbar-brand mb-0"><a rel="home" href="<?php echo esc_url( home_url( '/' ) ); ?>" title="<?php echo esc_attr( get_bloginfo( 'name', 'display' ) ); ?>"><?php bloginfo( 'name' ); ?></a></h1>

            <?php else : ?>

              <a class="dev-navbar-brand-lnk navbar-brand" rel="home" href="<?php echo esc_url( home_url( '/' ) ); ?>" title="<?php echo esc_attr( get_bloginfo( 'name', 'display' ) ); ?>"><?php bloginfo( 'name' ); ?></a>

            <?php endif; ?>


          <?php } else {
            the_custom_logo();
          } ?><!-- end custom logo -->
        </div>
        <!-- The WordPress Menu goes here -->
        <?php wp_nav_menu(
          array(
            'theme_location'  => 'primary',
            'container_class' => 'collapse navbar-collapse',
            'container_id'    => 'navbarNavDropdown',
            'menu_class'      => 'navbar-nav',
            'fallback_cb'     => '',
            'menu_id'         => 'main-menu',
            'walker'          => new WP_Bootstrap_Navwalker(),
          )
        ); ?>
      <?php if ( 'container' == $container ) : ?>
      </div><!-- .container -->
      <?php endif; ?>

    </nav><!-- .site-navigation -->

  </div><!-- .wrapper-navbar end -->

Desktop & Mobile Screenshot of Current Nav
[Desktop Nav][1]
[1]: https://i.stack.imgur.com/ulueF.jpg
[Mobile Nav][1]
[1]: https://i.stack.imgur.com/aAhLp.jpg

rw1982
  • 40
  • 1
  • 7
  • PS Doing something like this -- https://stackoverflow.com/questions/39080069/wp-add-logo-into-center-of-menu-whist-ignoring-sub-menus -- isn't really the route I want to take. There is a lot of php going on inside the logo divi, so simply adding the logo image and link with JS isn't really a good choice for a dynamic website. – rw1982 May 28 '17 at 06:56

2 Answers2

1

For problems #1 & #2, you just need to calculate the middle element, as you can see in https://stackoverflow.com/a/2269052/5794076:

function addLogoToMiddle() {
    var middle = Math.ceil($(".navbar-nav li").length / 2);
    var logoListItem = $('#logo-wrapper').appendTo('<li id="logo-item"></li>');
    $(".navbar-nav li:nth-child(" + middle + ")").after(logoListItem);
}

And as for problem #3, you can bind the logic directly to the resize event listener, as long as you also run the logic on page load, as can be seen here: https://stackoverflow.com/a/15840415/5794076

Additionally, you need to include logic to return the logo when resized back to a smaller screen. This is a bit trickier with your current HTML, so I would advise wrapping the #logo-wrapper div element in another div with an id of #small-screen-logo (or something to that effect...). Then you can add another function:

function addLogoToSide() {
    $('#small-screen-logo').append($('#logo-wrapper'));
    // don't forget to remove the list item element from the navbar
    $('#logo-item').remove();
}

And then, finally:

$(window).resize(function() {
    if ($(window).width() > 980) {
        addLogoToMiddle();
    } else {
        addLogoToSide();
    }
});

$(document).ready(function() {
    if ($(window).width() > 980) {
        addLogoToMiddle();
    } 
});
Gil Browdy
  • 69
  • 5
  • Yes! For problems 1 & 2, that fixed everything. You are a wizard. Thanks for the tip. I would thumbs up this answer but I just started using Stack more frequently and I apparently don't have enough points :( For problem three, I was able to have the logo go back where it came from from under 980, but I haven't quite figured out how to do that automatically when I drag the browser in horizontally. – rw1982 May 28 '17 at 19:43
  • Hey! Happy to help! What do you mean when you say "I haven't quite figured out how to do that automatically when I drag the browser in horizontally"? Can you be more specific with what the problem is at this point? Also, you can't upvote, but I believe you can still choose an answer as accepted. – Gil Browdy May 28 '17 at 20:04
  • Ok I see what you mean, sorry. When I drag my browser to my left, making it smaller, or when emulating the device size to go smaller, the nav disappear, when I inspect with dev tools, it looks like it's keeping the same DOM structure that jQuery applies, even below 980px. But it seems to be working when I scale up by either dragging my browser to my right, making it bigger, or emulating a larger device size. So I guess if I had to be more specific, I am not seeing it automatically go back to being on the top left side, outside of the "ul" at sizes below 980px. – rw1982 May 28 '17 at 20:14
  • You just need to add logic to check for resizing to a smaller screen size. I've updated my answer. – Gil Browdy May 28 '17 at 20:29
  • I am still having the issue of it only firing when I scale the width up from small browser size. I thought it might have something to do with the scripts my theme uses for the mobile nav. However, I am not having any console errors and its not actually interfering with the current script in any way. I made a static example in Codepen, so you can see my issue. When you scale down in width, you have to refresh to see the logo on the left, when you scale up in width it pops into the "ul" with no issue. https://codepen.io/rw1982/pen/aWrGrm – rw1982 May 29 '17 at 00:06
  • Everything looks fine, you just forgot to wrap `
    ` in `
    – Gil Browdy May 29 '17 at 07:12
  • Yes, that did it. I can't believe I missed that. Thanks again, I learned a lot from this. – rw1982 May 29 '17 at 20:02
0

(Final Implementation)

Yes! wrapping with the new div did it!
Thanks For this.

jQuery(document).ready(function() {

  function addLogoToMiddle() {
      var middle = Math.ceil($(".navbar-nav li").length / 2);
      var logoListItem = $('#logo-wrapper').appendTo('<li id="logo-item"></li>');
      $(".navbar-nav li:nth-child(" + middle + ")").after(logoListItem);
  }

  function addLogoToSide() {
      $('#small-screen-logo').append($('#logo-wrapper'));
      // don't forget to remove the list item element from the navbar
      $('#logo-item').remove();
  }

  $(window).resize(function() {
      if ($(window).width() > 980) {
          addLogoToMiddle();
      } else {
          addLogoToSide();
      }
  });

  $(document).ready(function() {
      if ($(window).width() > 980) {
          addLogoToMiddle();
      }
  });

});
rw1982
  • 40
  • 1
  • 7
  • Do I need to add something to the current code that un-does this at sizes below 980? Similar to what it is doing above 980px? Since it seems to be working fine when scaling up the window size? – rw1982 May 28 '17 at 20:19