tufte-jekyll
tufte-jekyll copied to clipboard
Collapsible navbar
This is not a bug but more like a feature/enhancement request. I'm still trying to tweak my pages and have run into this minor issue:
I'd like to have a collapsible navbar.
Currently the navigation bar is created from the site.pages
and while the tex size scales with device/media size it is not uncommon to get something that is wider that a single line if there are more than a few pages in the menu.
If the text width becomes too large then I'd like either all the menu items (besides the site name) to collapse or just the ones that there aren't room for.
For starters I moved the navigation part to a separate file _includes/nav.html
(shown below)
<header>
<nav id="menu">
<ul>
<li><a href="{{site.baseurl}}/">sitename</a></li>
{% for node in site.pages %}{% unless node.nav_exclude %}{% if page.url == node.url %}
<li><a class="active" href="{{node.url | prepend: site.baseurl}}">{{node.title}}</a> </li>
{% else %}
<li><a href="{{node.url | prepend: site.baseurl}}">{{node.title}}</a></li>
{% endif %}{% endunless %}{% endfor %}
</ul>
</nav>
</header>
where the menu items are items in an unordered list. Now I found some previous code to work as a collapsible navbar. Here's the part of the script that does all the computation with the width of the menu bar entries and moves them back and forth between being hidden (included as part of the footer).
/*--------------------------------------------------
Hidden Nav
--------------------------------------------------*/
hiddenNavBar = {
$menu: $('#menu'),
init: function () {
this.resize();
$('<div id="on-hidden-menu"><div class="toggle"><span></span></div><ul></ul></div>').hide().insertAfter(this.$menu);
// toggle
$('#on-hidden-menu .toggle').click(function () {
$('#on-hidden-menu').toggleClass('open');
});
// win load & resize
$(window).on('load resize', function () {
hiddenNavBar.resize();
});
},
resize: function () {
setTimeout(function () {
var menuWidth = $('ul', this.$menu).width() + 60;
var winW = $(window).width();
console.log(menuWidth, winW);
if (menuWidth > winW) {
console.log('init');
$('#on-hidden-menu').show();
/* $clone = $('li:not(".on-hidden"):last', this.$menu).addClass('on-hidden').clone(); */
$clone = $('#menu li:not(".on-hidden"):last', this.$menu).addClass('on-hidden').clone();
if ($clone.parent().size() == 0) {
$clone.prependTo($('#on-hidden-menu ul'));
}
hiddenNavBar.resize();
/** this.menu */
} else if (menuWidth + $('li.on-hidden:first').width() < winW) {
$('li.on-hidden:first').removeClass('on-hidden');
$('#on-hidden-menu ul li:first').remove();
}
if ($('.on-hidden').size() == 0) {
$('#on-hidden-menu').removeClass('open').hide();
}
}, 10);
}
};
/*--------------------------------------------------
DOC READY
--------------------------------------------------*/
$(function () {
hiddenNavBar.init();
})
and then there's the corresponding css file information (included in the header).
/*--------------------------------------------------
Nav
--------------------------------------------------*/
header {
padding: 15px 5px;
position: relative;
z-index: 1;
}
body.full-width > header {
}
#menu {
white-space:nowrap;
position: relative;
z-index: 1;
width: auto;
}
#menu ul {
list-style: none;
list-style-type: none;
margin: 0;
padding: 0;
white-space: nowrap;
display: inline-block;
}
#menu ul li {
display: inline-block;
position: relative;
}
#menu ul li a {
text-decoration: none;
padding: 0.7em;
}
/*--------------------------------------------------
On Hidden Menu
--------------------------------------------------*/
#menu ul li.on-hidden { display: none; }
#on-hidden-menu {
display: block;
position: absolute;
z-index: 10;
right: 0;
margin-top: 15px;
min-width: 280px;
}
#on-hidden-menu ul {
margin: 0;
padding: 0;
list-style: none;
position: relative;
overflow: hidden;
height: 0;
}
#on-hidden-menu li {
background: #30424d;
border-bottom: 1px solid #273640;
opacity: 0;
-moz-transition: all .4s ease-in-out .2s;
-o-transition: all .4s ease-in-out .2s;
-webkit-transition: all .4s ease-in-out .2s;
transition: all .4s ease-in-out .2s;
position: relative;
}
#on-hidden-menu li a {
color: rgba(255,255,255,.9);
text-decoration: none;
padding: 10px 15px;
display: block;
}
#on-hidden-menu li a:hover { background: #354C5A; }
/* on hidden menu open */
#on-hidden-menu.open ul {
display: block;
height: 100%;
}
#on-hidden-menu.open ul li {
opacity: 1;
}
#on-hidden-menu.open ul li:last-child {
border-bottom-left-radius: 5px;
}
/* toggle */
#on-hidden-menu .toggle {
width: 32px;
position: absolute;
top: -42px;
right: 10px;
height: 32px;
background-color: #f73a14;
z-index: 1;
cursor: pointer;
border-radius: 2px;
}
#on-hidden-menu .toggle:before, #on-hidden-menu .toggle:after,
#on-hidden-menu .toggle span:before {
content: '';
width: 4px;
height: 4px;
background: #fff;
border-radius: 5px;
position: absolute;
top: 17px;
left: 5px;
-moz-transition: all .4s ease-in-out;
-o-transition: all .4s ease-in-out;
-webkit-transition: all .4s ease-in-out;
transition: all .4s ease-in-out;
}
#on-hidden-menu .toggle:after {
left: 13px;
-moz-transition-delay: .1s;
-o-transition-delay: .1s;
-webkit-transition-delay: .1s;
transition-delay: .1s;
}
#on-hidden-menu .toggle span:before {
left: 21px;
-moz-transition-delay: .2s;
-o-transition-delay: .2s;
-webkit-transition-delay: .2s;
transition-delay: .2s;
}
/* close */
#on-hidden-menu.open .toggle:before, #on-hidden-menu.open .toggle:after {
width: 20px;
-moz-transform: rotate(225deg);
-ms-transform: rotate(225deg);
-o-transform: rotate(225deg);
-webkit-transform: rotate(225deg);
transform: rotate(225deg);
top: 14px;
height: 3px;
}
#on-hidden-menu.open .toggle:after {
-moz-transform: rotate(-225deg);
-ms-transform: rotate(-225deg);
-o-transform: rotate(-225deg);
-webkit-transform: rotate(-225deg);
transform: rotate(-225deg);
left: 5px;
-moz-transition-delay: .0s;
-o-transition-delay: .0s;
-webkit-transition-delay: .0s;
transition-delay: .0s;
}
#on-hidden-menu.open .toggle span:before {
top: 14px;
left: 13px;
width: 2px;
height: 2px;
-moz-transition-delay: .0s;
-o-transition-delay: .0s;
-webkit-transition-delay: .0s;
transition-delay: .0s;
}
Okay. So far so good. Then I want to fix the nav.html
so it matches the collapsible code (forget about the aesthetics here for now - it's not a beauty but that could be fixed). I add the ID's to nav.html
<header>
<nav id="menu">
<ul id="menu">
<li><a href="{{site.baseurl}}/">sandsynlig<b>vis</b>.dk</a></li>
{% for node in site.pages %}{% unless node.nav_exclude %}{% if page.url == node.url %}
<li><a class="active" id="menu" href="{{node.url | prepend: site.baseurl}}">{{node.title}}</a> </li>
{% else %}
<li><a id="menu" href="{{node.url | prepend: site.baseurl}}">{{node.title}}</a></li>
{% endif %}{% endunless %}{% endfor %}
</ul>
</nav>
</header>
which makes the collapsible navbar function. Sort or anyway. The width calculation is not working perfectly and the menu item pops in and out of existence until there's two items in the hidden part of the menu. Can anyone help with this and/or would help make it blend in with the rest of the Tufte-CSS format?
I can set up a (version) of the page so you can see what is wrong, but I haven't pushed it to the official server since it isn't working.
Okay. I did a bit of tweaking and seems to have it almost working. You can see a working example here. There's still a few corrections to be made to make it blend in completely but it's somewhat acceptable as it is.
I can write it up in case anyone else would be of interest.
I haven't had time to look at this, but at first glance this seems like a good idea, particularly for the smaller device width use cases. If it can be easily added I will add it to the repo.
Want me to try to extract the necessary bits and put them into a pull request?
That would be great if it wont chew up too much of your time.
Thanks
Sent using 100% all-natural biodynamic electrons
On Apr 4, 2016, at 7:17 PM, Claus Ekstrøm [email protected] wrote:
Want me to try to extract the necessary bits and put them into a pull request?
— You are receiving this because you commented. Reply to this email directly or view it on GitHub