sphere
sphere

Reputation: 1350

max-width of overflow:scroll element to match flex-grow parent elements width

I have a container #container with a fixed width which has three children .item. Each have a flex-basis of 100px but the middle one .item-grow should grow so that all width of #container is used. This works like expected.

The .item-grow element has another children #too-big which could be wider than the available parent's width so its wrapped inside a #scroll container with overflow: scroll and max-width: 100%.

The problem is, that #scroll ignores max-width: 100% and forces the parent .item-grow to grow which foces the container #container to grow.

If I set max-width: 296px instead of max-width: 100% it works but I am looking for a dynamic (and CSS only) solution.

In the embedded code you can find a slider which changes the size of #too-big, you can clearly see that its growing the parents and not using the scrollbars.

function setSize (newValue) {
  let elem = document.getElementById("too-big");
  elem.setAttribute("style",`width:${newValue}px; height:${newValue}px`);
}
#container {
  background-color: red;
  display: flex;
  width: 500px;
  height: 200px;
}

.item {
  display: flex;
  flex-grow: 0;
  flex-shrink: 0;
  flex-basis: 100px;
  border: solid black 1px;
  background-color: gray;
}
.item-grow {
  flex-grow: 1;
  align-items: center;
}
.center-wrapper {
  margin: auto;
  display: table-cell;
}
.scroll {
  overflow: scroll;
  max-width: 100%; /* I want this respect the current parents width */
  /* max-width: 296px; */
  max-height: 100%; /* I want this respect the current parents height */
  /* max-height: 200px; */
}
#too-big {
  background-color: green;
  width: 100px;
  height: 100px;
}
<input type="range" min=100 max=500 value=100 oninput="setSize(this.value)" onchange="setSize(this.value)">
<div id="container">
  <div class="item"></div>
  <div class="item item-grow">
    <div class="center-wrapper">
      <div class="scroll">
        <div id="too-big"></div>
      </div>
    </div>
  </div>
  <div class="item"></div>
</div>

Upvotes: 1

Views: 3022

Answers (1)

Asons
Asons

Reputation: 87191

To make that work you can drop the center-wrapper and set margin: auto on the scroll.

Then the item need min-width: 0 to allow it to be smaller than its content.

And for the max-height: 100% to work (cross browser), the item-grow need a height.

Fiddle demo (with overflow: auto instead)

Stack snippet

function setSize (newValue) {
  let elem = document.getElementById("too-big");
  elem.setAttribute("style",`width:${newValue}px; height:${newValue}px`);
}
#container {
  background-color: red;
  display: flex;
  width: 500px;
  height: 200px;
}
.item {
  display: flex;
  flex-basis: 100px;
  border: solid black 1px;
  background-color: gray;
  box-sizing: border-box;            /*  added  */
  min-width: 0;                      /*  added  */
}
.item-grow {
  flex-grow: 1;
  align-items: center;
  height: 100%;                      /*  added  */
}
.scroll {
  margin: auto;                      /*  added  */
  overflow: scroll;
  max-width: 100%;
  max-height: 100%;
}
#too-big {
  background-color: green;
  width: 100px;
  height: 100px;
}
<input type="range" min=100 max=500 value=100 oninput="setSize(this.value)" onchange="setSize(this.value)">
<div id="container">
  <div class="item"></div>
  <div class="item item-grow">
      <div class="scroll">
        <div id="too-big"></div>
      </div>
  </div>
  <div class="item"></div>
</div>

Upvotes: 2

Related Questions