Improved scrollbar-fix-(inner|outer) classes, inner class expands content to avoid...
authorNick Downing <nick@ndcode.org>
Tue, 1 Feb 2022 03:20:37 +0000 (14:20 +1100)
committerNick Downing <nick@ndcode.org>
Tue, 1 Feb 2022 09:09:22 +0000 (20:09 +1100)
_lib/navbar.jst
css/bootstrap/_custom.scss

index 2fe089d..edd7c80 100644 (file)
@@ -127,156 +127,158 @@ return async (env, head, body, scripts) => {
       let index = env.parsed_url.pathname.indexOf('/', 1)
       let dir = index === -1 ? '' : env.parsed_url.pathname.slice(1, index)
 
-      div.scrollbar-fix {
-        div.container {
-          div.row.align-items-center.py-3 {
-            div.col-sm-8 {
-              _out.push(logo_large)
-            }
-            div.'col-sm-4' {
-              div.'mb-1'.text-right {
-                span#navbar-signed-in-status {
+      div.scrollbar-fix-outer {
+        div.scrollbar-fix-inner {
+          div.container {
+            div.row.align-items-center.py-3 {
+              div.col-sm-8 {
+                _out.push(logo_large)
+              }
+              div.'col-sm-4' {
+                div.'mb-1'.text-right {
+                  span#navbar-signed-in-status {
+                    if (signed_in_as !== undefined)
+                      'Signed in.' //`Signed in as ${signed_in_as}.`
+                    else
+                      'Browsing as guest.'
+                  }
+                  ' '
+                  if (signed_in_as !== undefined)
+                    a#navbar-sign-in(href="#" hidden) {'Sign in'}
+                  else
+                    a#navbar-sign-in(href="#") {'Sign in'}
+                  ' '
+                  if (signed_in_as !== undefined)
+                    a#navbar-sign-up(href="/my_account/sign_up/index.html" hidden) {'Sign up'}
+                  else
+                    a#navbar-sign-up(href="/my_account/sign_up/index.html") {'Sign up'}
+                  ' '
                   if (signed_in_as !== undefined)
-                    'Signed in.' //`Signed in as ${signed_in_as}.`
+                    a#navbar-sign-out(href="#") {'Sign out'}
                   else
-                    'Browsing as guest.'
+                    a#navbar-sign-out(href="#" hidden) {'Sign out'}
                 }
-                ' '
-                if (signed_in_as !== undefined)
-                  a#navbar-sign-in(href="#" hidden) {'Sign in'}
-                else
-                  a#navbar-sign-in(href="#") {'Sign in'}
-                ' '
-                if (signed_in_as !== undefined)
-                  a#navbar-sign-up(href="/my_account/sign_up/index.html" hidden) {'Sign up'}
-                else
-                  a#navbar-sign-up(href="/my_account/sign_up/index.html") {'Sign up'}
-                ' '
-                if (signed_in_as !== undefined)
-                  a#navbar-sign-out(href="#") {'Sign out'}
-                else
-                  a#navbar-sign-out(href="#" hidden) {'Sign out'}
-              }
 
-              form(action="/search/index.html") {
-                div.input-group {
-                  input.form-control(name="query" type="text" placeholder="Search" aria-describedby="search-button") {}
-                  div.input-group-append {
-                    button.btn.btn-outline-secondary#navbar-search-button(type="submit") {
-                      div.icon24-outer {
-                        div.icon24-inner {_out.push(fa_search)}
+                form(action="/search/index.html") {
+                  div.input-group {
+                    input.form-control(name="query" type="text" placeholder="Search" aria-describedby="search-button") {}
+                    div.input-group-append {
+                      button.btn.btn-outline-secondary#navbar-search-button(type="submit") {
+                        div.icon24-outer {
+                          div.icon24-inner {_out.push(fa_search)}
+                        }
                       }
                     }
                   }
                 }
               }
-            }
 
-            //div.'col-sm-1'.vbottom {
-            //  // a nested div is used to avoid hover colour on the padding
-            //  div.nav-li-a(style="text-align: center;") {
-            //    a(href="/online_store/view_cart/index.html") {
-            //      div.cart-icon {
-            //        _out.push(icon_cart_small)
-            //      }
-            //      div.cart-number {
-            //        div.cart-circle {
-            //          `${(env.cart.items || []).length}`
-            //        }
-            //      }
-            //    }
-            //  }
-            //}
-          }
-          nav.navbar.navbar-expand-lg.navbar-dark.bg-primary.extend-background {
-            //a.navbar-brand(href="#") {'Navbar'}
-            //' '
-            button.navbar-toggler(type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation") {
-              span.navbar-toggler-icon {}
+              //div.'col-sm-1'.vbottom {
+              //  // a nested div is used to avoid hover colour on the padding
+              //  div.nav-li-a(style="text-align: center;") {
+              //    a(href="/online_store/view_cart/index.html") {
+              //      div.cart-icon {
+              //        _out.push(icon_cart_small)
+              //      }
+              //      div.cart-number {
+              //        div.cart-circle {
+              //          `${(env.cart.items || []).length}`
+              //        }
+              //      }
+              //    }
+              //  }
+              //}
             }
-            div.collapse.navbar-collapse#navbarSupportedContent {
-              ul.navbar-nav.mr-auto {
-                // the active entry in the navbar bar is based on which top-level
-                // page we are under, even if we are not directly on that page
-                // but one of its children, this may be unexpected as the active
-                // entry does not highlight on hover, but you can still click it;
-                // we determine here the path to the corresponding top-level page
-                let component_prefix = component_names.slice(0, 1)
-
-                for (let i = 0; i < menu_titles.length; ++i) {
-                  // construct path to the top-level page about to be described
-                  let menu_prefix =
-                    i == 0 ? [] : [menu_names[i - 1]]
-                  let menu_prefix_path =
-                    menu_prefix.map(name => '/' + name).join('') + '/index.html'
-
-                  if (arrays_equal(menu_prefix, component_prefix))
-                    li.nav-item.active {
-                      a.nav-link(href=menu_prefix_path) {
-                        `${menu_titles[i]}`
-                        span.sr-only {' (current)'}
+            nav.navbar.navbar-expand-lg.navbar-dark.bg-primary.extend-background {
+              //a.navbar-brand(href="#") {'Navbar'}
+              //' '
+              button.navbar-toggler(type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation") {
+                span.navbar-toggler-icon {}
+              }
+              div.collapse.navbar-collapse#navbarSupportedContent {
+                ul.navbar-nav.mr-auto {
+                  // the active entry in the navbar bar is based on which top-level
+                  // page we are under, even if we are not directly on that page
+                  // but one of its children, this may be unexpected as the active
+                  // entry does not highlight on hover, but you can still click it;
+                  // we determine here the path to the corresponding top-level page
+                  let component_prefix = component_names.slice(0, 1)
+
+                  for (let i = 0; i < menu_titles.length; ++i) {
+                    // construct path to the top-level page about to be described
+                    let menu_prefix =
+                      i == 0 ? [] : [menu_names[i - 1]]
+                    let menu_prefix_path =
+                      menu_prefix.map(name => '/' + name).join('') + '/index.html'
+
+                    if (arrays_equal(menu_prefix, component_prefix))
+                      li.nav-item.active {
+                        a.nav-link(href=menu_prefix_path) {
+                          `${menu_titles[i]}`
+                          span.sr-only {' (current)'}
+                        }
                       }
-                    }
-                  else
-                    li.nav-item {
-                      a.nav-link(href=menu_prefix_path) {
-                        `${menu_titles[i]}`
+                    else
+                      li.nav-item {
+                        a.nav-link(href=menu_prefix_path) {
+                          `${menu_titles[i]}`
+                        }
                       }
-                    }
+                  }
+                  //li.nav-item.dropdown {
+                  //  a.nav-link.dropdown-toggle#navbarDropdown(href="#" role="button" data-toggle="dropdown" aria-expanded="false") {
+                  //    'Dropdown'
+                  //  }
+                  //  div.dropdown-menu(aria-labelledby="navbarDropdown") {
+                  //    a.dropdown-item(href="#") {
+                  //      'Action'
+                  //    }
+                  //    ' '
+                  //    a.dropdown-item(href="#") {
+                  //      'Another action'
+                  //    }
+                  //    div.dropdown-divider {}
+                  //    a.dropdown-item(href="#") {
+                  //      'Something else here'
+                  //    }
+                  //  }
+                  //}
+                  //li.nav-item {
+                  //  a.nav-link.disabled {
+                  //    'Disabled'
+                  //  }
+                  //}
                 }
-                //li.nav-item.dropdown {
-                //  a.nav-link.dropdown-toggle#navbarDropdown(href="#" role="button" data-toggle="dropdown" aria-expanded="false") {
-                //    'Dropdown'
-                //  }
-                //  div.dropdown-menu(aria-labelledby="navbarDropdown") {
-                //    a.dropdown-item(href="#") {
-                //      'Action'
-                //    }
-                //    ' '
-                //    a.dropdown-item(href="#") {
-                //      'Another action'
-                //    }
-                //    div.dropdown-divider {}
-                //    a.dropdown-item(href="#") {
-                //      'Something else here'
-                //    }
-                //  }
-                //}
-                //li.nav-item {
-                //  a.nav-link.disabled {
-                //    'Disabled'
-                //  }
-                //}
-              }
-              ul.navbar-nav.ml-auto {
-                li.nav-item {
-                  a.nav-link#navbar-give-feedback(href="#") {'Give feedback'}
+                ul.navbar-nav.ml-auto {
+                  li.nav-item {
+                    a.nav-link#navbar-give-feedback(href="#") {'Give feedback'}
+                  }
                 }
               }
             }
-          }
 
-          await body(_out)
+            await body(_out)
 
-          footer.extend-background {
-            a(rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/") {
-              img(alt="Creative Commons License" style="border-width:0;" src="/images/by-sa_3.0_88x31.png") {}
-            }
-            p {
-              'This website is '
-              a(href="https://git.ndcode.org/public/ndcode_site.git") {
-                'open source'
-              }
-              ' and licensed under a '
+            footer.extend-background {
               a(rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/") {
-                'Creative Commons Attribution-ShareAlike 3.0 Unported License'
+                img(alt="Creative Commons License" style="border-width:0;" src="/images/by-sa_3.0_88x31.png") {}
+              }
+              p {
+                'This website is '
+                a(href="https://git.ndcode.org/public/ndcode_site.git") {
+                  'open source'
+                }
+                ' and licensed under a '
+                a(rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/") {
+                  'Creative Commons Attribution-ShareAlike 3.0 Unported License'
+                }
+                '.'
               }
-              '.'
-            }
 
-            p {'Example code fragments embedded within the text are placed in the public domain unless otherwise noted.'}
+              p {'Example code fragments embedded within the text are placed in the public domain unless otherwise noted.'}
 
-            p {`Copyright © ${new XDate(env.now).getUTCFullYear()} ${copyright}.`}
+              p {`Copyright © ${new XDate(env.now).getUTCFullYear()} ${copyright}.`}
+            }
           }
         }
       }
index 58393b7..c04669a 100644 (file)
@@ -5,11 +5,17 @@ $footer-link-hover-color: darken($footer-link-color, 10%);
 
 // apply this to a div inside the body tag
 // prevents page shifting to left/right as scrollbar appears/disappears
-// it works by calculating the width of the scrollbar and then adding
-// the corresponding amount of padding to left to keep things centered
-// see https://stackoverflow.com/questions/45524214/how-do-i-stop-my-web-content-from-shifting-left-when-the-vertical-scrollbar-appe
-.scrollbar-fix {
-  padding-left: calc(100vw - 100%);
+// uses negative margin to force content to be drawn under the scrollbar
+// (this is useful for modals since scrollbar disappears during a modal)
+// note: intended to be used with div.container which adds padding for
+// media sizes sm and above, don't do it for xs to avoid losing content
+.scrollbar-fix-outer {
+  overflow-x: hidden;
+}
+.scrollbar-fix-inner {
+  @include media-breakpoint-up(sm) {
+    margin-right: calc(100% - 100vw);
+  }
 }
 
 // place a container div around entire page, and then use this