Debugging Bloomberg menu mimic

Francisco Presencia
4 min readJun 26, 2018

--

Working Demo | Broken Demo

Someone decided to redo a Javascript large menu into pure CSS. Looking at it and the author motivation brought back memories of the time I was hacking around pure CSS components with Picnic CSS.

But the menu is completely broken! As many cried on Hacker News. And it is in a sense: you cannot put the mouse over the left menu and move it over thr right one, since it will reset.

This is how pretty it looks right now so we’ll make it stay the same:

Small visual bug/red flag

However, if you try to use it you’ll find one of the most common issues when doing pure CSS advanced elements: links/anchor tags too small! See the target for the links:

Note: this is a visual issue since we don’t want the link hover effect to disappear until the pointer crosses the line, but it doesn’t actually affect the functionality.

Link size with blue box. Highlighted in red the gap.

That gap might give us trouble, so the first thing is to remove it! It comes currently from the right panel:

That padding-left is getting in the way

So now we only have to find it in the code and remove it:

nav.bmenu article.panel {
padding-left: 1.25rem; /* Remove this */
}

Of course if you remove it the panel will be too close to the >, so let’s add some padding-right to those links to compensate:

nav.bmenu a {
padding-right: 1.25rem;
}

See the arrow? We also have to move it to the left, since it’s an ::after element that is positioned absolutely:

nav.bmenu > a:not(.no-panel)::after {
right: calc(0.5*0.5em); /* before */
right: calc(0.5*0.5em + 1.25rem); /* after, add what we took out */
}

It starts to look better; if we superimpose the <a> and the <article.panel>, we see they are border-to-border now:

With a small adjustment we can move the left bar where it belongs. A border-left: 1px solid #fff would have worked wonders here as well, or even a box-shadow. But let’s keep it close to the original:

nav.bmenu article.panel::before {
left: 1.25rem; /* before */
left: 0; /* after */
}

Voilà! Here it is:

Fixing the Functionality

The issue remains though. That was a red flag, but it turns out it wasn’t the issue since the right padding is within the panel.

The issue is that, if none of the links is hovered, the display: flex is not triggering. So let’s make the panels self-aware of their hover:

/* Keep showing the panel when we log over it! */
nav.bmenu article.panel:hover {
display: flex;
}

And we also have to remove the selector for the first item, since this is giving some trouble with over-specificity. This will unfortunately hide the right panel while not hovering any specific link, but it’s a small price to pay for being able to use the menu. So just remove this whole block of code:

/* Remove all of this: */
nav.bmenu > a:not(:hover):not(:focus) ~ article.panel:nth-of-type(1),
nav.bmenu > a.no-panel:hover ~ article.panel:nth-of-type(1) {
display: flex;
}
nav.bmenu > a:focus:not(:nth-of-type(1)):not(.no-panel) ~ article.panel:nth-of-type(1) {
display: none;
}
nav.bmenu > a:hover:not(:nth-of-type(1)):not(.no-panel) ~ article.panel:nth-of-type(1) {
display: none;
}

Now it definitely is fixed. I’d add a negative margin of -1px to the right panel because some browsers in some resolutions render partial pixels weirdly, but it’s good enough for now. Of course a PR is waiting to fix the original one.

Working Demo | Broken Demo

If you like this, follow me! More blog posts like this to come ❤

--

--