1

I've created a vertical navigation on the left of our site. We'd like the background color for a .item to change based on the subdirectory where a user is viewing content. So if someone clicks on a nav .item, the href will redirect them to a page and we want that .item to be highlighted a unique hex color that we can customize for each nav .item. All 6 nav items would have a different color.

One point of clarification is that sometimes folks may visit our site without having ever clicked a navigation item. I want the navigation items to still be highlighted based on the current subdirectory where a person is viewing content. This helps them easily identify where they are and how to get back if they navigate to other parts of the community. Also if a person does a global search and stumbles upon content in one of our 6 main areas, we want the nav menu to instantly identify their current location (based on url) and highlight that nav .item in our vertical nav bar.

Is Javascript or Jquery the way to go? Any help would be appreciated!!

Heres a FIDDLE with all the code.

sample CSS:

.navback {
  position: fixed;
  top: 0;
  left: 0px;
  width: 100px;
  height: 100%;
  background: #283237;
  z-index: 4;
}

.navbar {
  position: fixed;
  top: 44px;
  left: 0px;
  width: 100px;
  height: 60vh;
  background: #283237;
  display: flex;
  z-index: 5;
  flex-direction: column;
}

.topbar {
  border-top: 1px solid #000;
  top: 44px;
}

.navbar .item {
  flex: 1;
  text-align: center;
  display: flex;
  justify-content: center;
  flex-direction: column;
  padding-top: 40px;
  padding-bottom: 40px;
  max-height: 100px;
  z-index: 5;
}

.navbar .item div.label {
  color: #fff;
  position: relative;
  top: 5px;
  font-size: 13px;
  font-family: -apple-system, BlinkMacSystemFont, Helvetica, Arial, "Segoe UI", sans-serif;
  transition: all 300ms cubic-bezier(0.68, -0.55, 0.27, 1.55);
  left: -100px;
}

Sample HTML:

 <div class="topbar"></div>
  <div class="navback leftnav">
<div class="navbar">
  <div class="item hvr-shrink">
    <a href="https://community.canopytax.com/">
    <div>
        <img src="https://png.icons8.com/ios/35/ffffff/home.png"/>
      <div class="label">Home</div>
    </div>
  </a>
  </div>

  <div class="item hvr-shrink">
    <a href="https://community.canopytax.com/community-central/">
    <div>
      <img src="https://png.icons8.com/ios/40/ffffff/conference-call.png">
      <div class="label">Central</div>
    </div>
  </a>
  </div>
jord8on
  • 166
  • 1
  • 3
  • 18
  • Do you load your oages in w AJAX or do you do actual page loads? And can you edit backend code? –  May 22 '18 at 18:11
  • 1
    @D_N I don't know how to load my pages with AJAX. So when a person clicks on one of the nav links, it actually takes them to the page defined in the href. But if a person visits the site and never clicks the nav, I'd still like it to show where they are in the site. What would be ideal is if when a page loads, there is a script that runs and looks at the URL, then highlights a nav item based on a color that we've defined. So it's not as much about the click event on the actual nav but more focused around highlighting the nav menu `.item` where the user currently is (based on the url). – jord8on May 22 '18 at 18:49
  • For anyone who is looking for a vertical navigation bar that highlights an item on the bar, based on where the user is, on the site, you can find the final code that worked perfectly for us - https://jsfiddle.net/jord8on/4tp8a71q/3/ – jord8on May 23 '18 at 17:57

4 Answers4

1

To answer your question directly, yes this could be done also via JavaScript/jQuery but there is a far simpler way using the css :active selector.

For example, if the user clicks the .item then the code would be:

.item:active {
   background-color: #cecece; // or whatever styling you want
}

Sidenote: As a webdesigner myself, in general i'd advise using the :hover selector when it comes to navbar highlightng instead of the :active one.

Samuel Hulla
  • 6,617
  • 7
  • 36
  • 70
  • Won’t :active deactivate once another click event fires? Not to mention if the page changes? –  May 22 '18 at 18:09
  • @D_N yes it will. `:active` applies strictly to the click event only. Obviously, if you want to keep the changes even after the click event, it's better to use the jQuery `.addClass()` function as shown in other examples. It's more of an issue here, that it's not exactly clear *(at least to me)* as to what the OP actually wants to achieve. – Samuel Hulla May 22 '18 at 18:16
  • I am currently using the `:active` selector for other buttons/CTAs on our site. In the case of my OP I'm sorry for not being more clear. I want to make it so when a person clicks on one of our 6 nav items, they navigate to the subdirectory where they clicked to and have a unique background color persist for that nav `.item`, helping the users see which place they are in. Then if they click to another location in the nav, it would take them to that page and the nav item they just clicked would then appear "active" with a different, uniquely defined hex background color. Does that make sense? – jord8on May 22 '18 at 18:41
1

JS/jQuery

// get the first directory by splitting "/dir/path/name" into an array on '/'
// get [1] instead of [0] b/c the first should be blank. wrap in /s.
hereDir = "/" + window.location.pathname.split("/")[1] + "/";

// rebuild the URL since you're using absolute URLs (otherwise just use hereDir)
hereUrl = window.location.protocol + "//" + window.location.host + hereDir;

$(".item")
    .find("[href^='" + hereUrl + "']")
        .closest(".item").addClass("here");

Note .find("[href^=...]") selects things that start with what you're looking for.

CSS

/* now use .here to style */
.item.here {
    background-color: purple;
}
.item.here .label {
    font-weight: bold;
}
  • Thanks for the reply. I'm having a heck of a time trying to understand what i'm supposed to substitute in the code you provided. I've created a jsFiddle based on what you said. https://jsfiddle.net/jord8on/4tp8a71q/ Would you mind forking it and adding your suggestion so I can see it in action? – jord8on May 23 '18 at 02:16
  • You had it right, but I had it wrong--copy and use `.find("[href^='" + window.location.protocol + "//" + window.location.host + "/" + hereDir + "']")` (had missed some characters). Note that it won't work in the fiddle--what it's looking for isn't really there. –  May 23 '18 at 12:27
  • Tried to simplify and clarify it further. See the whole answer again. –  May 23 '18 at 12:38
  • 1
    That was really helpful! I got it working using the method you outlined in your post. My last challenge is that I'd like to have the highlight color be different based on the where the person is. i.e. if they are in the "questions" location, I want that nav `.item` to be #1498F5 and if they are in the "resources" nav `.item` I want it to be highlighted as #964BD6. Check out my updated Fiddle to see what's working. I just need to know how to have variable colors for that `.here` class... https://jsfiddle.net/jord8on/4tp8a71q/2/ – jord8on May 23 '18 at 16:29
  • Hey @D_N your answer got me as close as I could get. We tweaked the JS a little bit and now have a class (with color) being assigned to the `.item` based on the url they are visiting. Here's the final HTML, CSS, and JS that is working perfectly for us! https://jsfiddle.net/jord8on/4tp8a71q/3/ – jord8on May 23 '18 at 17:55
  • 1
    Another way to have done it is to assign a class to the body or html tags, and then style `.central .item.central` or similar. Glad you got it how you want it! –  May 24 '18 at 17:35
0

Use jquery in your html (https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js)

Add the following script

$('.item').click(function(){
    $('.item.active').removeClass("active");
    $(this).addClass('active');
})

CSS

.item.active {
  background-color: red;
}

Please see updated fiddle

Nandita Sharma
  • 13,287
  • 2
  • 22
  • 35
  • This worked, sort-of ツ. When I clicked the navigation menu `.item` it lit up with the color selected but when it moved to the next page, the color was no longer selected. What would be ideal is if when a page loads, a script that we place in the footer runs and looks at the URL, then highlights a nav item based on a color that we've defined. So it's not as much about the click event on the actual button but more focused around highlighting the nav menu `.item` where the user currently is (based on the url). – jord8on May 22 '18 at 18:45
  • instead of checking in url, keep the last active item in localstorage and on next page load check the localstorage and update the active class accordingly. – Nandita Sharma May 22 '18 at 18:47
  • i think this is similar to what you want. https://stackoverflow.com/q/18999501/4990572 – Nandita Sharma May 22 '18 at 18:49
  • One point of clarification is that sometimes folks may visit our site without having ever clicked a navigation item. I want the navigation items to still be highlighted based on the current subdirectory where a person is viewing content. This helps them easily identify where they are and how to get back if they navigate to other parts of the community. Also if a person does a global search and stumble upon content in one of our 6 main areas, we want the nav menu to instantly identify their current location (based on url). Does that help clarify? – jord8on May 22 '18 at 18:57
0

If you are using jQuery you can loop through each anchor and test it against the current URL of the page like this:

$(function highlightCurrentUrl() {
  var currentUrl = window.location.href;
  var items = $(".item").each(function() {
    var anchor = $(this).find('a');
    $(this).removeClass('active');

    //comparison logic
    if (anchor.prop('href') == currentUrl) {
      $(this).addClass("active");
    }

  });
});

What this does is add a class to the matching .item in the menu. (This won't work in JSFiddle due to Content Security policy so you will have to test it your own environment.)

Next, you will need to define the styles that will be applied to an .item.active DIV tag. And, if you want different colors for different items, you should probably give them ID's in you markup, so you can reference them individually:

  <div class="item hvr-shrink" id="home-link">
    <a href="https://community.canopytax.com/">
      <div>
        <img src="https://png.icons8.com/ios/35/ffffff/home.png"/>
        <div class="label">Home</div>
      </div>
    </a>
  </div>

  <div class="item hvr-shrink" id="central-link">
    <a href="https://community.canopytax.com/community-central/">
      <div>
        <img src="https://png.icons8.com/ios/40/ffffff/conference-call.png">
        <div class="label">Central</div>
      </div>
    </a>
  </div>

These rules are saying that when the active class is added to the div with the ID home-link or central-link it should have the following properties

#home-link.active {
  background-color: blue;
}
#central-link.active {
  background-color: green;
}
Pop-A-Stash
  • 6,572
  • 5
  • 28
  • 54
  • I haven't been able to get this to work, unfortunately. Should I be modifying any of the jQuery code you provided? I want to make it so when you click on an item, it navigates to that page and the jQuery runs and grabs a color that I define, which would be respective to the url. Where/how would I define the colors for each nav `.item`? – jord8on May 22 '18 at 18:36
  • This will add an `active` class to the `div` (with class`item`). You still need to define the css class `.item.active` and give it the colors you want in your CSS file. – Pop-A-Stash May 22 '18 at 19:02
  • That was very helpful! I added `.item.home.active { background-color: #899ea9;}` to the css for each respective menu item, identifying different colors. it worked! There's one more thing this script is not helping me with. See my updated OP for clarification... "Sometimes folks may visit our site without having ever clicked a navigation item. Every time any page loads we want the nav menu to instantly identify (via colored backgrnd) their current location (based on url) and highlight that nav `.item` in our vertical nav bar based on where a person is viewing content. – jord8on May 22 '18 at 19:20
  • This should still apply. Unless they are on a page where the URL does not match any of the URLs in the navbar, something will be highlighted. They don't have to click anything for this to work. – Pop-A-Stash May 22 '18 at 19:31
  • So the initial part of the URL does match. e.g. `https://community.canopytax.com/central/` ➞ I would also want any of the content items within that directory to also highlight the nav menu. e.g `https://community.canopytax.com/central/w/guides/37/community-guidelines` ⬅︎ this is also part of the same group/space so we want the nav item to be highlighted. Is there a way to add some kind of wildcard to the script so it's searching the top level directory and anything within that same directory, before it determines which `.item` to highlight? – jord8on May 22 '18 at 19:38
  • Yes. The code I have written is looking for an exact match. You will have to decide on the comparison logic if you want something different than that. Take a look at this question on how to parse URLs with JS: https://stackoverflow.com/questions/736513/how-do-i-parse-a-url-into-hostname-and-path-in-javascript – Pop-A-Stash May 22 '18 at 19:45
  • That link is a bit over my head . Is there a simpler way where i could have the script say something like this... IF the exact string: `canopytax.com/central/` is anywhere in the url, THEN mark a specific nav `.item` as active? – jord8on May 22 '18 at 20:01