1

I am using CSS to set the style for two sibling DIVs (a div.header and a div.body) so that their width is equal and the minimum width of the header is the minimum width of its div.wrapper so that scrollbars will appear on the browser window when narrower than the header.

BUT I am also trying to have scrollbars appear on div.body when the div.content within it expands outside of div.body. Currently the div.body expands to fit its content. I would also like div.body to fill the vertical space when div.content is small.


Edit: It's difficult to explain, so here is a picture that might help. Left side is when the full .header width is visible. Right side adds scrollbars at the outer level (browser window) when narrower than the .header text. illustration of goal


I am not confident that my current approach is on the right path, but I have the header enforcing the minimum width based on https://stackoverflow.com/a/48226415

.content {
  background-color: pink;
  margin: 1rem;
  width: 100px;
}

body {
  margin: 0;
}

.root {
  background-color: yellow;
  position: absolute;
  top: 0;
  bottom: 0;
  width: 100%;
  height: 100%;
  overflow-x: auto;
  overflow-y: hidden;
}

.wrapper {
  background-color: lightgray;
  overflow: hidden;
  display: inline-block;
  min-width: 100%;
  min-height: 100%;
}

.header {
  background-color: lightgreen;
  white-space: nowrap;
}

.body {
  background-color: lightblue;
  display: flex;
  flex-grow: 1;
  overflow-x: scroll;
  overflow-y: auto;
}
<div class="root">
  <div class="wrapper">
    <div class="header">
      header header header header header header header header header header header header
    </div>
    <div class="body">
      <div class="content">
        content
      </div>
    </div>
  </div>
</div>

Here is my JSFiddle with comments in the .content style at the top of the CSS.

dpdearing
  • 1,726
  • 3
  • 17
  • 21
  • 2
    Please don't use external code sites for what can as well be represented right within SO, as a snippet. – connexo Jun 19 '22 at 21:21

2 Answers2

0

Flex

If I understand right, I think might have found the issue. The display: flex; in the .body class is preventing you from getting any scrollbar.

Flex makes the element aware of the space around it and will size itself accordingly, no matter what width or overflow values you set for it or its parents.

.content {
  background-color: pink;
  margin: 1rem;
  width: 1000px;
}

body {
  margin: 0;
}

.root {
  background-color: yellow;
  position: absolute;
  top: 0;
  bottom: 0;
  width: 100%;
  height: 100%;
  overflow-x: auto;
  overflow-y: hidden;
}

.wrapper {
  background-color: lightgray;
  overflow: hidden;
  display: inline-block;
  min-width: 100%;
  min-height: 100%;
}

.header {
  background-color: lightgreen;
  white-space: nowrap;
}

.body {
  background-color: lightblue;
  width: 500px;
  overflow-x: scroll;
  overflow-y: auto;
}
<div class="root">
  <div class="wrapper">
    <div class="header">
      header header header header header header header header header header header header
    </div>
    <div class="body">
      <div class="content">
        content
      </div>
    </div>
  </div>
</div>

I gave the content and body some more width to make it more obvious that now a scrollbar WILL appear.

Here is the same example in a fiddle.

H3AR7B3A7
  • 4,366
  • 2
  • 14
  • 37
  • Thanks, that might be the correct direction. How would I style the `.body` class to remove the `width: 500px` and make it fill the entire `.wrapper` height/width? I want it to be minimum width of the `.header` and otherwise fill the height/width – dpdearing Jun 19 '22 at 22:08
  • If you want it to be the minimum width of the header, then why would you need 2 scrollbars? I don't understand. Can you maybe draw what you want the result to look like? – H3AR7B3A7 Jun 19 '22 at 23:09
  • I'll try to explain better. I want the `.body` below the `.header` to always match the header width. The `.header` should have a minimum width based on its own text, but the `.body` should just match that width. If the `.content` within the `.body` is larger than this, then I want scrollbars on the `.body`. I only want the scrollbars at the outer-most `.root` level when the browser/window width is smaller than the header text. Yes, this would have double scrollbars when the browser is narrow and the nested `.content` is very wide – dpdearing Jun 19 '22 at 23:21
  • I also updated the post with an image – dpdearing Jun 19 '22 at 23:32
0

1. Force the .body width to both 0 and 100%

  • Force the width of .body class to be 0 so the width of the container is defined by the .header (the .body doesn't contribute to the width)
  • Then force the width of the .body again to be 100% using min-width

This gets the .body and its scrollbars to behave as desired relative to the .wrapper.

(I got inspiration for this step from this not-obviously related answer: https://stackoverflow.com/a/55041133/186818)

2. Change the .wrapper to inline-flex and fill the visible space

  • Set the .body height to 100% to fill the vertical space of the .wrapper.
  • Change the .wrapper to inline-flex with:
    display: inline-flex;
    flex-grow: 1;
    flex-direction: column;
    /* fill the visible space */
    min-width: 100%;
    height: 100%;
    
    This stacks the .header over the .body and expands to fill the space without extending past the visible boundaries.

Revised Code Snippet

.content {
  background-color: pink;
  margin: 1rem;

  /* example large content within the .body */
  height: 200px;
  width: 1000px;
}

body { margin: 0; }
.root {
  background-color: yellow;
  position: absolute;
  top: 0;
  bottom: 0;
  width: 100%;
  height: 100%;

  /* allow scrolling to see all of header */
  overflow-x: auto;
  /* y-direction scroll should be within .body */
  overflow-y: hidden;
}

.wrapper {
  background-color: lightgray;
  overflow: hidden;
  
  /* Do this:               */
  display: inline-flex;
  flex-grow: 1;
  flex-direction: column;
  /* fill the visible space */
  min-width: 100%;
  height: 100%;

  /* Not this: */
  /* display: inline-block; */
  /* min-height: 100%;      */
}
.header {
  background-color: lightgreen;
  white-space: nowrap;
}
.body {
  background-color: lightblue;

  /* Do this:       */
  display: block;
  width: 0;
  min-width: 100%;
  height: 100%;

  /* Not this:      */
  /* display: flex; */
  /* flex-grow: 1;  */

  overflow-x: scroll;
  overflow-y: auto;
}
<div class="root">
  <div class="wrapper">
    <div class="header">
      header header header header header header header header header header header header
    </div>
    <div class="body">
      <div class="content">
        content
      </div>
    </div>
  </div>
</div>

And here is a link to the JSFiddle.

dpdearing
  • 1,726
  • 3
  • 17
  • 21