In June 2017 we published our new company website here at Guava. It was quite a milestone for us because this new version consolidated our visual identity.

There were a lot of changes compared to the previous version: we added beautiful new illustrations made by our incredible designers, reviewed our color palette, wrote a lot of new content, implemented a magazine-ish experience with covers on all pages and divided the inner sections with gorgeous curvy shapes.

All these things are amazing, but one important detail to notice is that, from a front-end implementation point of view, it’s very tricky to deal with the interaction between those curvy shapes and fixed elements following the user’s scroll. As the proud craftsmen and women we are, getting rid of the fixed elements wasn’t an option we wanted to pursue, which meant we had to come up with a way to make it work like envisioned. This is the challenge that we’re going to discuss in this post.

Motivation

Contrast affecting the readability of a fixed menu when changing from a section to another

From the early drafts of the new website concept, we had our minds set on the idea of a fixed navigation menu for desktop screens. Locking down its position was going to work very well with our vision of the ideal navigation for this particular project, but it created the issue of maintaining its readability across several different background colors and their different contrast palettes.

First, we considered protecting the menu contents with a flat, simple background color. This solution would address the readability problem pretty well, but — besides looking a little weird in our experiments — it ended up hiding parts of key illustrations in some page sections. We didn’t want that. And there was still a key issue to address…

Enter curved section separators. Solid background fills were getting worse by the minute. The only acceptable course of action left was to find a way to make the menu adjust its colors depending on which section it is hovering, while still respecting all the curvy and non-curvy section boundaries along the way. Damn.

The technique

Searching for existent solutions to our problem, we stumbled upon an exciting library called Midnight.js. By allowing you to change your website header on the fly, this small jQuery plugin caught our attention. Unfortunately for us, the lib only handled rectilinear sections, at least at that point in time.

Even if we couldn’t use the lib, the idea behind its implementation would be the key to developing our own technique.

The behavior we’re aiming for. It can be checked out here.

The menu-changing behavior we wanted was quite peculiar. The menu styles should change immediately when hovering over a different section with different background colors. Also, this hovering could be partial, meaning that just a word, or even a small section of a word, would have different styles. This requirement alone discarded any potential solutions using the classic CSS/JS class toggle technique.

That’s where the Midnight.js implementation comes into play, bringing in the notion of mask elements, that along with menu animations make up the two core concepts applied in our solution.

Mask elements

Initially, when we introduced you to our little challenge, we may have been tempted to speculate a solution in which the menu kinda “knows” the section it is hovering and what styles to apply on itself. I know I have. With the mask elements, the problem is turned exactly the opposite way: the sections are the “intelligent” elements here, knowing what menu or styles to render.

It makes sense, right? Each actual page section has its own fixed menu, hiding the overflows, so the menus don’t overlap. Well, easier said than done.

The first problem that we should notice is that HTML elements with fixed positioning don’t respect positioned parent’s boundaries. Instead, fixed positioning pins an element in place relative to the browser viewport itself. So that clever overflow: hidden; property applied to the section elements won’t work.

Second, we don’t want to slip in the entire menu markup inside each page section. It would be very confusing to mix the navigation with contents of every section on the page; not to mention the accessibility issues. This is where the mask elements come in handy.

These masks are nothing more than transparent elements, created with the exclusive purpose of mimicking the original section format, restraining each section’s menu inside it. Their properties are cloned from the actual section elements. The snippets below illustrate this step of the implementation.

All snippets in this post are generic HTML/jQuery code.

Suppose we have a section element that needs a mask.

For that, we need a mask element on the page (at the end of the page, preferably, for reasons already mentioned).

This mask has some interesting properties:

class : the additional classes are used to set some particular properties of a given mask. Remember the curves mentioned above? Well, we need to implement these section curves in CSS and replicate them in the masks. This way, the mask element has the same form of the section element.

: the additional classes are used to set some particular properties of a given mask. Remember the curves mentioned above? Well, we need to implement these section curves in CSS and replicate them in the masks. This way, the mask element has the same form of the section element. data-menu-class : this is the class applied to the menu element appended to this mask children.

: this is the class applied to the menu element appended to this mask children. data-menu-mask : a string indicating a selector for its respective section element.

With that out of the way, we can use jQuery to clone the section CSS properties using the attributes defined in the snippet above.

Very straightforwardly we clone the section styles into the mask elements. In addition to the properties above, we need to make the mask absolute-positioned so that they can be precisely above the sections. We can do that using the mask’s additional classes.

After that, our next task should be appending a menu clone to the mask’s children. Let’s not forget the menu modifier class, specified in the data-menu-class attribute. It defines the styles for that section’s menu.

A quick note about accessibility on this approach: the menus are still being replicated. It is recommended to place an aria-hidden="true" property on all menus, except the first.

"Authors MAY, with caution, use aria-hidden to hide visibly rendered content from assistive technologies only if the act of hiding this content is intended to improve the experience for users of assistive technologies by removing redundant or extraneous content."

(W3C WAI-ARIA. Thanks to Thibaut Allender for noticing.)

Since the pure CSS fixed positioning won’t work for the menus, they need to be positioned absolutely, and we need to move them up and down using JavaScript, simulating the fixed-positioning behavior. That’s our hook for the next subsection: menu animation.