Element with auto height overflowing with `overflow-y: scroll`

Viewed 38

So this problem has haunted me for a while, and despite the many other potential threads and answers to similar issues I still can't figure it out.

I have a layout mixed with CSS Grid and Flexbox, and the left sidebar contains a number of buttons that should be scrollable. So far this works fine, but I can't figure out why the sidebar makes the entire layout stick out of its parent once I set overflow-y: scroll to it.

example demo of problem

Looking at it, the layout always sticks out as much as the "Outer Title"'s height. Other than that, it's already flexible and adapts well to different screen heights and widths.

Can somebody explain to me this behavior and what fixes it?

Demo:

* {
  box-sizing: border-box;
}

body {
  display: grid;
  place-items: center;
  height: 100vh;
  margin: unset;
}

article {
  height: 600px;
  display: flex;
  flex-direction: column;
  padding: 24px;
  background-color: rgba(0, 0, 0, .1);
}

main {
  background-color: lightblue;
  flex: 1;
  max-width: 1300px;
  width: 100%;
  height: 100%;
  max-height: 1000px;
  display: grid;
  grid-template-columns: 200px auto 200px;
  grid-template-rows: 60px auto;
  padding: 24px;
  gap: 24px;
}

h1 {
  grid-column: 1 / 4;
  margin: unset;
  background-color: rgba(0, 0, 0, .1);
}

#categories {
  display: flex;
  flex-direction:column;
  background-color: rgba(0, 0, 0, 0.1);
  overflow: hidden;
}

#categories > button {
  width: 100%;
}

#categories .img {
  width: 100px;
  height: 100px;
}

#icons {
  overflow-y: scroll;
}

#pad {
  background-color: rgba(0, 0, 0, 0.1);
  display: flex;
  flex-direction: column;
  position: relative;
}

#pad canvas {
  background-color: white;
  width: 100%;
  flex: 1;
}

#pad button {
  position: absolute;
  bottom: 24px;
  right: 24px;
}

#sidebar {
  background-color: rgba(0, 0, 0, 0.1);
  display: flex;
  flex-direction: column;
}

#sidebar p {
  margin-bottom: auto;
}
<article>
  <p>Outer Title</p>

  <main>
    <h1>Inner Title</h1>

    <section id="categories">
      <h2>Sidebar</h2>

      <button type="button">Up</button>

      <div id="icons">
        <button type="button" class="img">#1</button>
        <button type="button" class="img">#2</button>
        <button type="button" class="img">#3</button>
        <button type="button" class="img">#4</button>
        <button type="button" class="img">#5</button>
        <button type="button" class="img">#6</button>
        <button type="button" class="img">#7</button>
        <button type="button" class="img">#8</button>
        <button type="button" class="img">#9</button>
        <button type="button" class="img">#10</button>

      </div>

      <button type="button">Down</button>
    </section>

    <section id="pad">
      <h3>Title</h3>
      <p>Lorem ipsum dolor sit amet consectetur adipisicing elit.</p>

      <canvas></canvas>

      <button type="button">Weiter</button>
    </section>

    <aside id="sidebar">
      <p>0:00</p>
      <button type="button">Help</button>
      <button type="button">Finish</button>
    </aside>
  </main>
</article>

1 Answers

Seems like the default margin from p is collapsing the main element outside of its parent. You'll notice if you set p to margin: 0; it fixes the problem.

However, the correct fix would be to put the max-height on .main as well as .categories since that is what is scrollable. Then set article to height: max-content;.

* {
  box-sizing: border-box;
}

body {
  display: grid;
  place-items: center;
  height: 100vh;
  margin: unset;
}

article {
  height: max-content;
  display: flex;
  flex-direction: column;
  padding: 24px;
  background-color: rgba(0, 0, 0, .1);
}

main {
  background-color: lightblue;
  flex: 1;
  max-width: 1300px;
  width: 100%;
  height: 100%;
  max-height: 600px;
  display: grid;
  grid-template-columns: 200px auto 200px;
  grid-template-rows: 60px auto;
  padding: 24px;
  gap: 24px;
}

h1 {
  grid-column: 1 / 4;
  margin: unset;
  background-color: rgba(0, 0, 0, .1);
}

#categories {
  display: flex;
  flex-direction: column;
  background-color: rgba(0, 0, 0, 0.1);
  max-height: 400px;
}

#categories>button {
  width: 100%;
}

#categories .img {
  width: 100px;
  height: 100px;
}

#icons {
  overflow-y: scroll;
}

#pad {
  background-color: rgba(0, 0, 0, 0.1);
  display: flex;
  flex-direction: column;
  position: relative;
}

#pad canvas {
  background-color: white;
  width: 100%;
  flex: 1;
}

#pad button {
  position: absolute;
  bottom: 24px;
  right: 24px;
}

#sidebar {
  background-color: rgba(0, 0, 0, 0.1);
  display: flex;
  flex-direction: column;
}

#sidebar p {
  margin: auto;
}

article > p {
  margin: 0;
}
<article>
  <p>Outer Title</p>

  <main>
    <h1>Inner Title</h1>

    <section id="categories">
      <h2>Sidebar</h2>

      <button type="button">Up</button>

      <div id="icons">
        <button type="button" class="img">#1</button>
        <button type="button" class="img">#2</button>
        <button type="button" class="img">#3</button>
        <button type="button" class="img">#4</button>
        <button type="button" class="img">#5</button>
        <button type="button" class="img">#6</button>
        <button type="button" class="img">#7</button>
        <button type="button" class="img">#8</button>
        <button type="button" class="img">#9</button>
        <button type="button" class="img">#10</button>

      </div>

      <button type="button">Down</button>
    </section>

    <section id="pad">
      <h3>Title</h3>
      <p>Lorem ipsum dolor sit amet consectetur adipisicing elit.</p>

      <canvas></canvas>

      <button type="button">Weiter</button>
    </section>

    <aside id="sidebar">
      <p>0:00</p>
      <button type="button">Help</button>
      <button type="button">Finish</button>
    </aside>
  </main>
</article>

Related