Fix sidebar scrolling (#2860)

* Simplify both left and right sidebars

- Rewrite the sidebars to use the same CSS class instead of having two
  very similar classes. This involves removing all affix related
  attributes and functionality from the sidebars and replaced them with
  `position: sticky`.
- The table of content elements should not be floated
- Removed unused CSS rules related to the sidebars
- Remove JavaScript used to resize the sidebars

* Improve the mobile menu to be fixed

- Simply JS used to hide/display the navigation bar on mobile viewports
- The mobile menu should be fixed so it can be viewable from the bottom
  of the page. Before this change, you would have to scroll up to see
  the menu that `position: absolute`

* Fix disappearing top navbar on homepage

- Change the calculation of the affix offset for the navbar on the home
  page to ensure the navbar never leaves the viewport. This change also
  takes into account the change of how the sidebars' offsets are used

* Fix auto scrolling on overflow

* Add polyfill for 'position: sticky' on IE

* Fix hamburger menu at incorrect breakpoint

* Fix left nav hidden after expanding from mobile

If you expand and collapse the left nav while on mobile and expand to a
desktop view, the left nav would be hidden; this has been fixed

* Unify navbar on homepage with rest of website
This commit is contained in:
Vladimir Jimenez 2017-04-21 09:04:19 -07:00 committed by John Mulhausen
parent cffdc1e574
commit f466f24742
12 changed files with 91 additions and 213 deletions

View File

@ -69,38 +69,12 @@
</a>
</div>
<!-- nav-secondary -->
<nav class="nav-secondary-tabs" data-spy="affix" data-offset-top="490">
<div class="container-fluid-fluid">
<div class="row">
<div class="col-xs-12 col-sm-3 col-md-3 col-lg-3">
<div class="search-form">
<form class="search form-inline ng-pristine ng-valid" id="searchForm" action="/search/">
<input class="search-field form-control ds-input" id="st-search-input" value="" name="q" placeholder="Search the docs" type="search" autocomplete="off" spellcheck="false" dir="auto" style="position: relative; vertical-align: top;">
<div id="autocompletecontainer-fluid">
<div id="autocompleteResults"></div>
</div>
<!-- <button type="submit" class="search-submit btn btn-default">Search</button> -->
</form>
</div>
<div class="sidebar-toggle">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
</div>
</div>
<div id="tabs">
<!-- <ul class="tabs nav navbar-nav navbar-collapse collapse navbar-left"> -->
<ul class="tabs nav navbar-nav navbar-collapse navbar-left">
{% include treebuilder.html %}
</ul>
</div>
<div class="ctrl-right">
{% include archive-list.html %}
</div>
<!-- data-offset-top should calculated as follows: (height of <header> - header of <nav>) -->
<nav class="nav-secondary-tabs" data-spy="affix" data-offset-top="385">
<div class="container-fluid">
<div class="navbar-collapse" aria-expanded="false" style="height: 1px;">
{% include navigation.html %}
</div>
</div>
</nav>
</div>

View File

@ -8,36 +8,7 @@
<a href="/"><img class="logo" src="/images/docker-docs-logo.svg" alt="Docker Docs" title="Docker Docs"></a>
</div>
<div class="navbar-collapse" aria-expanded="false" style="height: 1px;">
<div class="search-form" id="search-div">
<form>
<form class="search-form form-inline ng-pristine ng-valid" id="searchForm" action="/search/">
<input class="search-field form-control ds-input" id="st-search-input" value="" name="q" placeholder="Search the docs" type="search" autocomplete="off" spellcheck="false" dir="auto" style="position: relative; vertical-align: top;">
<div id="autocompleteContainer">
<div id="autocompleteResults"></div>
</div>
<!-- <button type="submit" class="search-submit btn btn-default">Search</button> -->
</form>
</div>
<div class="sidebar-toggle">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
</div>
<div>
<div class="nav-container">
<div id="tabs">
<ul class="tabs">
{% include treebuilder.html %}
</ul>
</div>
<div class="ctrl-right hidden-xs hidden-sm">
<a href="javascript:void(0)" id="menu-toggle"><i class="fa fa-indent" aria-hidden="true"></i></a>
{% include archive-list.html %}
</div>
</div>
{% include navigation.html %}
</div>
</div>
</nav>

28
_includes/navigation.html Normal file
View File

@ -0,0 +1,28 @@
<div class="search-form" id="search-div">
<form class="search-form form-inline ng-pristine ng-valid" id="searchForm" action="/search/">
<input class="search-field form-control ds-input" id="st-search-input" value="" name="q" placeholder="Search the docs" type="search" autocomplete="off" spellcheck="false" dir="auto" style="position: relative; vertical-align: top;">
<div id="autocompleteContainer">
<div id="autocompleteResults"></div>
</div>
<!-- <button type="submit" class="search-submit btn btn-default">Search</button> -->
</form>
</div>
<div class="sidebar-toggle">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
</div>
<div class="nav-container">
<div id="tabs">
<ul class="tabs">
{% include treebuilder.html %}
</ul>
</div>
<div class="ctrl-right hidden-xs hidden-sm">
<a href="javascript:void(0)" id="menu-toggle"><i class="fa fa-indent" aria-hidden="true"></i></a>
{% include archive-list.html %}
</div>
</div>

View File

@ -1,5 +1,5 @@
{% if page.landing == true %}<div id="navbar" class="nav-sidebar">{%else%}<div id="navbar" class="nav-sidebar">{% endif %}
<ul class="nav" affix" {% if page.landing == true %}data-spy="affix" data-offset-top="490"{% endif %}>
<ul class="nav">
{{ leftnav }}
</ul>
</div>

View File

@ -146,12 +146,12 @@ else %}{% assign edit_url = "" %}{% endif %} {% break %} {% endif %} {% endfor %
</section>
</main>
<nav class="col-nav">
<div class="sidebar{% if page.landing == true %}-home{%else%}{% endif %} hidden-sm hidden-xs">
<div id="sidebar-nav" class="sidebar hidden-sm hidden-xs">
{% include side-menu.html %}
</div>
</nav>
<div class="col-toc">
<div id="{% if page.landing == true %}sidebar-right{%else%}sidebar-wrapper{% endif %}" class="{% if page.landing == true %} affix-top hidden-xs hidden-sm{%else%}sidebar-wrapper hidden-xs hidden-sm{% endif %}" {% if page.landing == true %} data-spy="affix" data-offset-top="490"{% endif %}>
<div class="sidebar hidden-xs hidden-sm">
<div class="toc-nav">
<div class="feedback-links">
<ul>
@ -215,6 +215,7 @@ else %}{% assign edit_url = "" %}{% endif %} {% break %} {% endif %} {% endfor %
<script defer src="/js/menu.js"></script>
<script src="/js/jquery.js"></script>
<script src="/js/bootstrap.min.js"></script>
<script src="/js/stickyfill.min.js"></script>
<script defer src="/js/docs.js"></script>
</body>

View File

@ -154,35 +154,6 @@ section.section {
*
*/
#sidebar-wrapper {
background-color: $bg-sidebar;
// border-left: 1px solid rgba(204, 204, 204, 0.29);
height: 100%;
position: fixed;
padding: 70px 0 0;
overflow-y: auto;
overflow-x: hidden;
right: 250px;
margin-right: -250px;
width: 0;
transition: all 0.5s ease;
}
#sidebar-right {
background-color: $bg-sidebar;
// border-left: 1px solid rgba(204, 204, 204, 0.29);
height: 100%;
padding-top: 20px;
width: 270px;
min-height: 800px;
}
#sidebar-right.affix {
top: 10px;
position: fixed;
min-height: 800px;
}
.wrapper.right-open #sidebar-wrapper {
width: 270px;
}
@ -197,43 +168,27 @@ section.section {
* Sidebar
*/
.sidebar-home {
background-color: $bg-sidebar;
// border-right: 1px solid rgba(204, 204, 204, 0.29);
overflow-x: hidden;
overflow-y: auto;
min-height: 800px;
height: 100%;
width: 270px;
padding-top: 20px;
.col-nav,
.col-toc {
min-height: 100vh;
}
.sidebar-home .affix {
.col-nav,
.col-toc,
.sidebar {
background-color: $bg-sidebar;
// border-right: 1px solid rgba(204, 204, 204, 0.29);
}
.col-toc {
margin-left: auto;
}
.sidebar {
position: -webkit-sticky;
position: sticky;
top: 55px;
overflow-x: hidden;
overflow-y: auto;
padding-bottom: 100px;
height: 100%;
width: 270px;
}
/*.sidebar-home .affix {}*/
.sidebar,.sidebar.affix {
background-color: $bg-sidebar;
// border-right: 1px solid rgba(204,204,204,0.29);
top: 51px;
bottom: 0;
left: 0;
display: block;
padding: 0;
overflow-x: hidden;
overflow-y: auto;
padding: 20px 10px 100px 0;
position: fixed;
height: 100% !important;
width: 270px;
overflow: auto;
max-height: calc(100vh - 55px);
padding-top: 20px;
padding-bottom: 20px;
}

View File

@ -23,16 +23,7 @@
font-size: 13px;
padding: 19px 10px 11px;
}
// .sidebar-home,
// .sidebar-home.affix,
// .sidebar,
// .sidebar.affix {
// position: absolute;
// width: 100%;
// height: 500px;
// overflow: scroll;
// }
h1,
h2,
h3 {
@ -70,15 +61,10 @@
font-size: 13px;
padding: 19px 10px 11px;
}
.sidebar-home,
.sidebar-home.affix,
.sidebar,
.sidebar.affix {
position: absolute;
.sidebar {
position: fixed;
width: 100%;
height: 500px;
overflow: scroll;
z-index: 100;
}
.content {
padding: 50px;
@ -179,8 +165,7 @@
padding: 0;
overflow-x: hidden;
overflow-y: auto;
padding: 60px 10px 100px 15px;
position: absolute;
position: fixed;
width: 100%;
}
.sidebar-home,
@ -265,8 +250,7 @@
padding: 0;
overflow-x: hidden;
overflow-y: auto;
padding: 10px 10px 100px 0;
position: absolute;
position: fixed;
width: 100%;
}
.component-full {
@ -357,7 +341,6 @@
}
}
/* Landscape */
@media only screen
and (min-device-width: 768px)
@ -368,9 +351,6 @@
margin: 10px 15px 0 0px;
width: 160px;
}
.navbar-toggle {
display: none!important;
}
.ctrl-right {
display: block;
}
@ -384,8 +364,16 @@
}
}
@media (max-width: 768px) {
.navbar-toggle {
display: block;
}
@media (min-width: 992px) {
.navbar-toggle {
display: none;
}
.nav-sidebar.collapse {
display: block;
}
}

View File

@ -164,10 +164,6 @@
*
*/
.toc-nav {
padding: 0;
}
.toc-toggle {
width: 25px;
height: 25px;
@ -177,15 +173,13 @@
.toc-nav ul {
list-style: none;
margin: 0;
padding: 0 60px 0 0;
width: 300px;
padding-left: 0;
line-height: 24px;
li {
padding: 2px 8px 2px 15px;
float: left;
width: 100%;
a {
display: block;
display: inline-block;
font-size: 12px;
padding: 0 10px 0 10px;
text-decoration: none;
@ -214,8 +208,6 @@ div#side-toc-title {
font-size: 12px;
font-weight: bold;
margin: 11px 0 10px 13px;
float: left;
width: 100%;
}
.edit {

View File

@ -67,7 +67,7 @@ i.fa.fa-outdent {
.search-form {
float: left;
margin: 10px 15px 0 0px!important;
margin: 5px 15px 0 0px;
width: 200px;
& input[type=text] {
background: rgba(0, 0, 0, 0.17) url("/images/search.png") no-repeat;
@ -93,12 +93,6 @@ i.fa.fa-outdent {
-o-transition: all 0.2s ease;
transition: all 0.2s ease;
padding: 0px 0 0 35px;
min-width: 260px;
}
.nav-secondary-tabs .search-form {
// width: 240px;
margin: 10px 0 0 10px!important;
}
.search-form input[type=text]:focus {

View File

@ -6,11 +6,6 @@
*
*/
.toc-nav
{
padding-bottom: 50px !important;
}
.alert-info {
border: 0;
border-radius: 0;

View File

@ -6,10 +6,11 @@ var headerOffset = document.getElementsByClassName("container-fluid")[0].getBoun
// ensure that the left nav visibly displays the current topic
var current = document.getElementsByClassName("active currentPage");
var body = document.getElementsByClassName("col-content content");
if (current[0]) {
if (sidebarObj) {
current[0].scrollIntoView(true);
sidebarObj.scrollTop -= 150;
body[0].scrollIntoView(true);
}
}
@ -54,29 +55,8 @@ function highlightRightNav(heading)
}
}
}
function checkNavSizes()
{
sidebarBottom = sidebarObj.getBoundingClientRect().bottom;
footerTop = document.getElementsByClassName("footer")[0].getBoundingClientRect().top;
headerOffset = document.getElementsByClassName("container-fluid")[0].getBoundingClientRect().bottom;
if (footerTop < sidebarBottom || (sidebarBottom < footerTop && sidebarBottom < $(window).height()))
{
// the footer is overlapping the sidebar
var sidebarHeight = (footerTop < $(window).height()) ? footerTop : $(window).height();
var tocNavHeight = (footerTop < $(window).height()) ? footerTop : $(window).height();
sidebarObj.style.height = sidebarHeight + "px";
document.getElementsByClassName("toc-nav")[0].style.height = tocNavHeight + "px";
$(sidebarObj).clearQueue().finish();
setTimeout(highlightRightNav(currentHeading),1);
}
}
$(window).resize(function() {
checkNavSizes();
});
var currentHeading = "";
$(window).scroll(function(){
checkNavSizes();
var headingPositions = new Array();
$("h1, h2, h3, h4, h5, h6").each(function(){
if (this.id == "") this.id="title";
@ -154,19 +134,9 @@ $("#menu-toggle-left").click(function(e) {
$(".col-nav").toggleClass("col-toc-hidden");
});
$(".navbar-toggle").click(function(){
$(".sidebar, .sidebar-home").each(function(){
if($(this).hasClass("hidden-sm")) {
$(this).removeClass("hidden-sm");
$(this).css("overflow-y","scroll");
} else {
$(this).addClass("hidden-sm");
}
if($(this).hasClass("hidden-xs")) {
$(this).removeClass("hidden-xs");
$(this).css("overflow-y","scroll");
} else {
$(this).addClass("hidden-xs");
}
$("#sidebar-nav").each(function(){
$(this).toggleClass("hidden-sm");
$(this).toggleClass("hidden-xs");
});
});
@ -210,6 +180,8 @@ $(document).ready(function(){
$(document).ready(function(){
$(".sidebar").Stickyfill();
// Add smooth scrolling to all links
$(".nav-sidebar ul li a").on('click', function(event) {

8
js/stickyfill.min.js vendored Normal file

File diff suppressed because one or more lines are too long