Addem
Addem

Reputation: 3919

HTML/CSS: What is the right way to make sticky menus?

I am trying to make a page that has a header and sticky horizontal menu. Underneath that, on the left, should be a sticky vertical menu. The rest of the page should be content. To give it in a picture:

enter image description here

To accomplish this I've tried using grids, then divs that were in fixed or absolute or relative position, and so on. So far the best I've come up with after looking at a bunch of examples is this:

HTML

<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="../css/layout.css">
</head>
<body>

  <div class="header">
    <h1>Banner</h1>
    <p>Subtitle</p>

    <div class="breadcrumbs">
      <a class="menuitem button disabled">></a>
    </div>
  </div>

  <div class="verticalMenu">
    <a href="#" class="menuitem">Home</a><br>
    <a href="#" class="menuitem">Map</a><br>
    <a href="#" class="menuitem">1. </a><br>
    <a href="#" class="menuitem">2. </a><br>
    <a href="#" class="menuitem">3. </a><br>
    <a href="#" class="menuitem">4. </a><br>
  </div>

  <div class="content" style="">
    <button class="accordion">Intro</button>
    <div class="panel">
      <button class="accordion">Summary</button>
      <div class="panel">
        <p><span>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ducimus, porro, beatae. Accusantium veniam iure quaerat temporibus ex, nam impedit! Voluptatem suscipit natus eligendi, consectetur ratione porro, facere iusto perferendis harum.</span>
        <span>Accusamus praesentium dolore eveniet adipisci non, molestias ut repudiandae sunt. Libero modi in dignissimos dolore cumque mollitia possimus maiores repudiandae dolorum praesentium. Minima repudiandae inventore dolores numquam vitae, ipsa accusantium!</span>
        <span>Eveniet magni tenetur similique quo possimus aperiam illo. Consectetur exercitationem delectus quibusdam ducimus possimus adipisci soluta ipsam iure animi, nisi, laborum autem doloremque nemo iste voluptatum explicabo quaerat! Hic, illo!</span>
        <span>Eos quidem enim corrupti voluptates nesciunt temporibus, illum explicabo velit totam tempore ad eius, soluta. Ipsa velit recusandae in voluptates, numquam aperiam labore nobis non, fugiat qui? Similique, omnis, natus.</span>
        <span>Quam, nulla, minus ipsum consectetur nesciunt veniam illum magnam facere, debitis fugit atque nihil tenetur. Animi a sit soluta in officia error? Quisquam reprehenderit repellendus facilis optio reiciendis soluta iste.</span>
        <span>Recusandae quis molestias error in ab, labore quas officiis tempore omnis, beatae, corporis iste consequuntur veritatis. Debitis, veniam voluptatibus molestias dignissimos corporis, magni esse saepe harum rem dolorem neque fugiat.</span>
        <span>Officia quo voluptatem ipsum, dolorum quisquam unde illum accusantium velit quidem similique magnam. Tempora, reprehenderit, veritatis! Incidunt neque, perferendis magnam, itaque vel sunt veniam consectetur vitae libero ipsam, dignissimos asperiores!</span>
        <span>Quibusdam quae, incidunt accusamus sed cumque maxime reiciendis optio quasi similique, fugit, non facere placeat tempora. Ipsa, ea, dolorum! Labore nesciunt, distinctio inventore dolor ullam sint saepe incidunt enim molestias.</span>
        <span>Placeat quod nulla, soluta distinctio quis consequuntur earum dicta quae rerum magnam tenetur iste nesciunt ab facilis eum suscipit, reprehenderit molestias repudiandae, repellendus adipisci eaque aperiam. Praesentium adipisci itaque quidem!</span>
        <span>Error in, veritatis earum sit dignissimos numquam? Minus voluptatem, soluta blanditiis voluptatibus tenetur sapiente reprehenderit cupiditate impedit sed, consectetur fuga recusandae inventore, harum voluptates porro deserunt? Quae vero, necessitatibus dolorum?</span></p>
      </div>
      <button class="accordion">Section</button>
      <div class="panel">
        <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
      </div>
    </div>


  </div>

  <script type="text/javascript" src="../js/layout.js"></script>

  </body>
</html>

CSS

.content {
  position: relative;
  top: 150px;
  left: 100px;
  z-index: 1;
  margin-bottom: 180px;
  width: auto;
}
.verticalMenu {
  display: inline-block;
  position: fixed;
  left: 0;
  top: 150px;
  width: 100px;
  height: 100%;
}
.header {
  position: fixed;
  z-index: 100;
  top: 0px !important;
  width: 100%;
  background: white;
}
.button {
  background-color: blue;
  color: white;
}
.breadcrumbs {
  background-color: green;
  position: fixed;
  top: 110px;
  left: 5px;
  width: 100%;
}

button.accordion {
    background-color: #eee;
    color: #444;
    cursor: pointer;
    padding: 18px;
    width: 100%;
    border: none;
    text-align: left;
    outline: none;
    font-size: 15px;
    transition: 0.4s;
}

button.accordion.active, button.accordion:hover {
    background-color: #ddd;
}

div.panel {
    padding: 0 18px;
    display: none;
    background-color: white;
}

.test {
  position: absolute;
  top: 150px;
  left: 100px;
  z-index: 1;
  margin-bottom: 180px;
}

JavaScript

var acc = document.getElementsByClassName("accordion");
var i;

for (i = 0; i < acc.length; i++) {
   acc[i].onclick = function(){
       this.classList.toggle("active");
       var panel = this.nextElementSibling;
       if (panel.style.display === "block") {
           panel.style.display = "none";
       } else {
           panel.style.display = "block";
       }
   }
}

But right now I'm running into the problem that the button for the accordion is supposed to span the remaining width of the screen. However, it seems to only span the width of the button text. If I set width to 100% in the CSS for the containing element (the content class) then this exceeds the width of the window. I hypothesize that it does this because I made the banner and nav bars with position fixed, and then to put the content where it's supposed to appear, I offset it with position absolute. However, that just shifts it rather than "fill the remaining space". So if I force the width to be 100% that will take 100% of the screen width, and therefore leave a chunk offset beyond the screen.

Since I've run into a large number of issues like this, and every time I fix one I eventually encounter another, it's making me suspect that I'm just approaching this all wrong. Is there a better way to make sticky and non-sticky components so that they still fill the space without spilling out of it? It feels like one ought to be able to carve out portions of the screen dedicated to certain tasks, and inside of those portions, just fill with their own HTML page so that the contents in one place don't affect the contents in another (unless specifically instructed to). Grids kind of do that, but as I've tried to make this work with grids, they don't seem to really allow you to fill the grid cells with anything you want--if the content is too big, or if you want it to be sticky, it disrupts the rest of the layout.

Upvotes: 2

Views: 577

Answers (1)

Incisor
Incisor

Reputation: 370

For a sticky Top bar

      <div id="navbar">
  <a href="#home">Home</a>
  <a href="#news">News</a>
  <a href="#contact">Contact</a>
</div>

CSS

/* Style the navbar */
#navbar {
  overflow: hidden;
  background-color: #333;
}

/* Navbar links */
#navbar a {
  float: left;
  display: block;
  color: #f2f2f2;
  text-align: center;
  padding: 14px;
  text-decoration: none;
}

/* Page content */
.content {
  padding: 16px;
}

/* The sticky class is added to the navbar with JS when it reaches its scroll position */
.sticky {
  position: fixed;
  top: 0;
  width: 100%;
}

/* Add some top padding to the page content to prevent sudden quick movement (as the navigation bar gets a new position at the top of the page (position:fixed and top:0) */
.sticky + .content {
  padding-top: 60px;
}

For the sticky vertical bar you can use this.

<div class="sidenav">
  <a href="#">About</a>
  <a href="#">Services</a>
  <a href="#">Clients</a>
  <a href="#">Contact</a>
</div>

<!-- Page content -->
<div class="main">
  ...
</div>

The CSS

 /* The sidebar menu */
    .sidenav {
        height: 100%; /* Full-height: remove this if you want "auto" height */
        width: 160px; /* Set the width of the sidebar */
        position: fixed; /* Fixed Sidebar (stay in place on scroll) */
        z-index: 1; /* Stay on top */
        top: 0; /* Stay at the top */
        left: 0;
        background-color: #111; /* Black */
        overflow-x: hidden; /* Disable horizontal scroll */
        padding-top: 20px;
    }

    /* The navigation menu links */
    .sidenav a {
        padding: 6px 8px 6px 16px;
        text-decoration: none;
        font-size: 25px;
        color: #818181;
        display: block;
    }

    /* When you mouse over the navigation links, change their color */
    .sidenav a:hover {
        color: #f1f1f1;
    }

    /* Style page content */
    .main {
        margin-left: 160px; /* Same as the width of the sidebar */
        padding: 0px 10px;
    }

    /* On smaller screens, where height is less than 450px, change the style of the sidebar (less padding and a smaller font size) */
    @media screen and (max-height: 450px) {
        .sidenav {padding-top: 15px;}
        .sidenav a {font-size: 18px;}
    }

Upvotes: 2

Related Questions