0

I have static top bar and left menu, and scrollable long content on right. In my (long) submenu I use position: absolute to not change row height. Submenu position for rows 2 and 3 in below snippet is wrong and non-intuitive and unwanted scroll bar appear. How to fix it?

body { margin: 0}
button { height: 20px}
.hide { display:none; }
.container { display: flex; }
.topBar { background: red; height: 30px; }

.side__menu {
  height: calc(100vh - 30px);
  background: yellow;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  width:100px;
}

.main__panel {
  overflow: auto;
  height: calc(100vh - 30px);
  width: calc(100vw - 100px);
}

.row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  height: 200px;
  background: #ddd;
  margin: 10px;
}

.submenu {
  position: absolute;
  right: 100px;
  background: #fdd;
  height: 70px;
}
<div class="topBar">Top Bar</div>
<div class="container">
  <div class="side__menu">
    <div>item1</div><div>item2</div><div>menu footer</div>    
  </div>

  <div class="main__panel">

    <div class="row">
      Row 1
      <button onclick="s1.classList.toggle('hide')">toggle submenu</button>
      <div id="s1" class="submenu hide">submenu</div>
    </div>
    
    <div class="row">
      Row 2
      <button onclick="s2.classList.toggle('hide')">toggle submenu</button>
      <div id="s2" class="submenu hide">submenu</div>
    </div>
    
    <div class="row">
      Row 3
      <button onclick="s3.classList.toggle('hide')">toggle submenu</button>
      <div id="s3" class="submenu hide">submenu</div>
    </div>
    
  </div>
</div>
Kamil Kiełczewski
  • 85,173
  • 29
  • 368
  • 345
  • https://www.w3.org/TR/CSS21/visudet.html#containing-block-details *If the element has 'position: absolute', the containing block is established by the nearest ancestor with a 'position' of 'absolute', 'relative' or 'fixed', ... If there is no such ancestor, the containing block is the initial containing block.* ---> focus on the last part, in your case absolute is behaving as a fixed element – Temani Afif Dec 09 '20 at 20:14
  • @TemaniAfif thank you - by default submenu parent has `positon: static`, but when I change it to `relative` then that parent starts to be submenu (which has `position: absolute`) containing block and this is why it is draw in proper way. You could create answer with this because in my opinion it is not trivial - but thank you again :) – Kamil Kiełczewski Dec 09 '20 at 20:33

1 Answers1

0

I make some investigation and discover that height: 100vh (with calc or not) "create problems" with submenu. I accidentally find one solution - just add following style to row class

position: relative;

But I totally don't know why it actually works - so feel free to create answer and explain it if you know why (or show some alternative approach)

body { margin: 0}
button { height: 20px}
.hide { display:none; }
.container { display: flex; }
.topBar { background: red; height: 30px; }

.side__menu {
  height: calc(100vh - 30px);
  background: yellow;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  width:100px;
}

.main__panel {
  overflow: auto;
  height: calc(100vh - 30px);
  width: calc(100vw - 100px);
}

.row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  height: 200px;
  background: #ddd;
  margin: 10px;
  position: relative;
}

.submenu {
  position: absolute;
  right: 100px;
  background: #fdd;
  height: 70px;
}
<div class="topBar">Top Bar</div>
<div class="container">
  <div class="side__menu">
    <div>item1</div><div>item2</div><div>menu footer</div>    
  </div>

  <div class="main__panel">

    <div class="row">
      Row 1
      <button onclick="s1.classList.toggle('hide')">toggle submenu</button>
      <div id="s1" class="submenu hide">submenu</div>
    </div>
    
    <div class="row">
      Row 2
      <button onclick="s2.classList.toggle('hide')">toggle submenu</button>
      <div id="s2" class="submenu hide">submenu</div>
    </div>
    
    <div class="row">
      Row 3
      <button onclick="s3.classList.toggle('hide')">toggle submenu</button>
      <div id="s3" class="submenu hide">submenu</div>
    </div>
    
  </div>
</div>

Tested on: Chrome, Safari and Firefox

Kamil Kiełczewski
  • 85,173
  • 29
  • 368
  • 345