Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This is a bug fix, and also an enhancement or feature.
Summary
I've identified 2 bugs related to the navbar and implemented fixes to those bugs, and I've changed the way the jquery.greedy-navigation script measures the available space for items, which results in consistency and precision:
1st bug:
Behavior:
On pages both with and without logos, though rarely, the "visible-link" "ul" object takes more space than it should, making some items on the navbar appear completely or partially hidden.
The cause:
On the _base.scss file, it is set both "-webkit-transition" and "transition" attributes for a bunch of elements, and importantly to our case, the "a" elements and the "img" elements.
On the Navbar there are 3 types of "a", which are affected by transitions and are relevant to this bug: "site-logo", "site-title" and ".visible-links -> li -> a" (which are the navbar visible section links) also, the "img" object under "site-logo".
On the greedy navigation script,
jquery.greedy-navigation.js
, the lineavailableSpace = $vlinks.width() - 10;
measuresvlinks
(the ".visible-links" "ul" object) width, and this calculation is crucial to determine how many items may fit on the navbar. After some debugging, I've found out that the measured size ofvlinks
was not consistent, which was... strange. I thought this had to do with the script, but nothing seemed to be wrong there.Then finally it clicked to me! It was a race condition. Most of the times, the measurement is done after the transition on the "a" (and img) objects width is done, but yeah, most of the times is not always. Sometimes, the
vlinks
object's width is measured before or during the transition, and thus getting the wrong value.The fix:
We could wait for the transition to occur in order to execute the greedy navigation script logic (relevant related discussion here), but... I mean... Is it worth it? We would have to add a considerable amount of complexity to the code in order to control the transition's execution with js/jquery.
My suggestion is simply: "transitions on navbar -> bad":
diff between my fix and original code:
_navigation.scss
note:
.visible-links a::before
elements also have a transition, but they don't seem to influence the code, so I've ignored it.My conscience says it would be better to disable all transitions on the navbar, since it would make harder for an user customization on the template or even, who knows, an update, to bring this bug back again. But this should work for now.
2nd bug:
Behavior:
On pages with logos, not so rarely, the "visible-link" "ul" object takes more space than it should, making some items on the navbar be completely or partially hidden. The same effect as the first bug, but more frequently, and limited to pages with logos.
The cause:
Although we've target both the
.site-logo
element and theimg
element inside of it on the first solution, this is not enough to fix this. After some testing, I've noticed yet another race condition: similar as before, thevlinks
measurement can occur before the.site-logo img
is even loaded. If the image happens to take a little more time to load, since the widths are not fixed, thevlinks
object is measured without it, and when the image is finally loaded, all the calculation with the wrong values is already done.The fix:
We need to wait for the images on the navbar to load before doing the relevant calculation. As discussed here, the best way to make this happen without much hassle seems to be using David DeSandro’s imagesLoaded library since "it has no dependencies, is pretty small, and works with jQuery".
I've come up with something studying imagesloaded and relevant discussions here and here.
This doesn't add any dependencies and simply doesn't do anything if the page doesn't have a logo.
If it does have a logo, it checks if it's loaded before continuing:
I've tested with Chrome/Firefox mobile browsers, as well as Instagram and Telegram's in-app browsers and it worked 100% of the time, even if the logo has a broken src.
It should work with legacy browsers as well.
Then I faced something that had me boggled since I've started analyzing the greedy-nav script: The way it calculates the available space for links on the navbar. The relevant line is
availableSpace = $vlinks.width() - 10;
. So what this does is to presume that the available space for items in the navbar is the totality of the width of visible links element minus 10px. I had in my mind this was strange because 10 pixels is a static value, that couldn't take into account the dynamic nature of css with it's media queries and so on.The width of the visible links element decreased by 10 pixels is an educated guess of the available space, but it is not precise. The developers of greedy-nav are certainly not to blame, as doing precise calculations adds a considerable amount of complexity, and in my opinion, defeats the purpose of it as a versatile and lightweight priority+ navbar implementation.
If you want to calculate the precise available space for navItems, you need to take the navbar inner width and decrease from it the width of every visible element (except for the links). But how different the precise measurement and the approximation could be, you may ask? On a page without a logo, I've measured a 10px difference on a 360px width Android device, and a remarkable 30px difference on a 320px width Iphone device. Thats not at all insignificant as it represents +9% of the Iphone device width and can easily result in consistent glitches on some devices in some pages (as in my test case).
As we're talking about precision (and good use of space), there's 2 another issues.
So I've implemented in the script all those things I've mentioned. I've done my best, doing performance tests all along, to make this the less performance greedy as I could. This of course inevitably added time complexity to the code, since I've added some grabby calculations (particularly elements widths measurements). That being said, at least in my test cases the added complexity is not at all performance critical, nor can it be perceived by the user, or outside of performance testing. This is tested both with and without the logo and the search toggle. I'm proud to say this adds what I call "pixel perfect responsivity". :)
Context
Fixes #2664