Is it possible to do this?


(Garth Poon) #1

Hi, I have a client who is wondering if it’s possible to create a notification badge on a nav menu item, similar to the one on this website: http://www.theartof.com/

Is there a stack out there that can do it? Or maybe even some awesome CSS trick?


(Marten Claridge ) #2

Hi Garth,

Yes it is possible, but would likely depend upon which theme you settle on, and then editing the theme’s index.html file.

In your example site above they have inserted a <div class="bubble"></div> inside the navigation’s list item (<li>)… Like this:

<li>
<div class="bubble">3</div>
</li>

They then target the bubble with the following (slightly edited by me) CSS:

 li {
    display: block;
    position: relative;
}
    .bubble {
        width: 10px;
        height: 15px;
        background: #f40707;
        color: #fff;
        padding: 0px 2px 2px 6px;
        font-weight: bold;
        position: absolute;
        top: -10px;
        right: 0px;
        font-size: 11px;
        line-height: 18px;
        -webkit-border-radius: 50%;
        border-radius: 50%;
    }

Note how the bubble is positioned absolutely.

However, although the solution above is possible, changing the number in the bubble would mean manually editing the theme’s index.html file each time you wanted to change it.

I’m not sure about a more dynamic solution but if your client is insistent on such a feature, try contacting ThemeFlood’s Will Woodgate who may well be able to custom-build such a feature into one of his themes for you.

Marten
RapidWeaver Central


(Garth Poon) #3

Wow, thanks for the reply @Marten_Claridge! I’ll give it a try.


(Jon C. Munson II) #4

@Marten_Claridge, you could change the number in the bubble without manually changing the index file. And, additionally, you could add the bubble to that list item without modifying the index.html file at all - provided it is somehow explicitly declared such that a jQuery call could find it. :wink:

Sample 1: $( ".bubble" ).html( data );

Sample 2: $("head").append(html);

Both examples should get one going in the right direction…


(Garth Poon) #5

That’s super cool, @JCMII! I don’t know much about jQuery…would I copy and paste your sample into the javascript section of the RW page? (and also add Marten’s CSS to the CSS section?)


(Jon C. Munson II) #6

That is only a sample. You’ll have to work a bit harder to get it to function the way you want.

First, you’ll need to add a reference to jQuery in the head section (if it isn’t referenced already).

Second, while the first sample should work as is, the second will require further digging. Take a look at the .find() method for jQuery.

After that, you’ll have to do some research on how that bubble is being generated - is it dynamic, once on refresh, etc., in order to be able to implement your intended solution.


(Garth Poon) #7

Oh, okay, thanks! I’ll look into it.


(Andrew Tavernor) #8

You can of course do it in pure CSS without resorting to jQuery and DOM modifications at all. CSS pseudo elements are, as they say, not actual dom elements an totally defined in CSS. This has the additional advantage that it is never render blocking while waiting for jQuery to load and it pretty much theme independent (assuming you get the correct selector for the menu)

You can assign 2 pseudo elements to a DOM element namely ::before and ::after.
If, like the example you can simply target the :first-child, however to target any numbered menu item, the more general case could use :nth-of-type.

So in your case, for example to target the 4th <li> in the menu you could simply use some CSS along the lines of the following :
#menu ul>li:nth-of-type(4) a::after{
position:absolute;
right: 0;
top:-10px;
width:16px;
height:16px;
content: “1”; /* this is the text that will appear in the bubble */
background: orange;
border-radius: 50%; /*make the bubble background round */
box-sizing: content-box;
text-align: center;
}


(Jon C. Munson II) #9

@tav, what would you recommend using to change that ‘content’ value dynamically in response to the appropriate event?


(Andrew Tavernor) #10

That entirely depends on where the data is coming from but content: will accept data attributes so this would seem the most sensible. It is a cleaner and entirely more modern way of dealing with things like this.

In addition in the context of RW, adding DOM elements - particularly to menus is generally a bad idea. Most responsive menus stand a good chance of messing up in their mobile state for instance. When so much is out of your control (i.e. in the control of the theme, you can end up with an horrendous amount of overrides and DOM manipulation very easily.) The CSS solution avoids all this and totally compartmentalises the problem.


(Jon C. Munson II) #11

The fact that you are not in control of the theme means that no matter your customizations, you might have to revisit things. CSS is no guarantee of safety there.

I understand what you are saying, but I’m not so sure I agree with that POV. :wink:


(Andrew Tavernor) #12

By adding a pseudo element you are in absolutely no danger of breaking anything. It does not affect the dom structure. Worst case scenario is that it doesn’t display.

I don’t know what you mean by revisit things?

But worst case scenario - my mobile menu structure, where the divs and thus selectors can change for different arrangements (and may do) only requires a media query to handle the revised pseudo.

If you do it by DOM manipulation via JS then you immediately introduce the over head of a listener on the window resize, which you then need to debounce. You will also likely need a lot more code to detect exactly when the DOM has changed as the chances are you will have no knowledge of the breakpoint set in the theme.

I suppose, the real point here is though, what is the most elegant and code efficient way to do it. If it can be proved to me that it can be done in less JS that one line i.e.
$('#menu').data('num-items','2');
plus the above CSS then I will concede.


Targeting active top menu level on foundation topbar
(Garth Poon) #13

@tav, you are amazing!

Okay, I’m trying to add a badge to the “Speakers” menu item here: http://digitalbuzz.ca

A CSS solution is totally fine with me. Every time I add new speakers to the website, they’d like me to add a little badge that shows the number of new additions.

I’ve tried it out on this page: http://digitalbuzz.ca/privacy-policy/

I’m using Foundation, so I tried adding this CSS:

.top-bar-section ul>li:nth-of-type(2) a::after{
position:absolute;
right: 0;
top:-10px;
width:16px;
height:16px;
content: "3"; /* this is the text that will appear in the bubble */
background: red;
border-radius: 50%; /*make the bubble background round */
box-sizing: content-box;
text-align: center;
}

I feel like I’ve almost got it, but the number doesn’t line up with the bubble. Any tweaks or suggestions, Andrew?


(Andrew Tavernor) #14

Sorry, I forgot the line-height.

line-height: 1.2;

should be about right - you may need to tweak it up and down a little.


(Andrew Tavernor) #15

You will also probably want to stop the badge appearing on the child <a> elements in which case just add the direct descendent selector > thus:

.top-bar-section ul>li:nth-of-type(2)>a::after{

There is more description of specifying the selectivity of the menu selectors in this post http://bigwhiteduck.typed.com/blog/topbar-dropdown-transition


(Garth Poon) #16

@tav, thank you so much for your help! I got it working!!!


(Andrew Tavernor) #17

@garth Great stuff. It works a treat on your page, really drawing the reader to that menu - nice job.


(Jon C. Munson II) #18

Very cool. Best part is the learning. :slight_smile: Thanks @tav for your examples. :smile:


(Andrew Tavernor) #19

My pleasure - all good.