user2132190
user2132190

Reputation: 465

Flexbox / Expanding height due to nested element

I have a deeply nested element that grows and I am trying to use flexbox to make its outer container accommodate its height. Trying to get the "orange" element to stretch vertically to include the inner most text in following pen: https://codepen.io/cssbog/pen/KKzgxgd

    <ol class="menu-item-list">
  <li id="menu-item-las-powr" class="menu-item control-slider active">
    <div class="label">Label</div>
    <div class="value">
      <div class="slider-view"> 
        <div class="slider-box">
          <div class="safe-slider">    
            <div class="slider-val-line-parent">
              <div class="slider-val-text">
                BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </li>
</ol>

    

Upvotes: 2

Views: 413

Answers (1)

F. M&#252;ller
F. M&#252;ller

Reputation: 4062

Update
As I already said in the comment. You cannot change the height of the elements independently they are all in a parent-child-relationship.

You should consider using less markup and maybe use a different approach to achieve the same. If it is about the styling you could make .value growing with the .slider-val-text and use an independent absolute element to draw over the .slider-val-text (you just have to add enough padding and draw over it at the top there for this greenish box background).

However, you can set a fixed height to the .value container. Try height: 168px. The problem with that is, that it will not change depending on the text you put in in .slider-val-text.

You could use javascript and set the height of the .value container based on the height of the .slider-val-text once the DOM has finished loading.

document.addEventListener("DOMContentLoaded", function() {
  const childHeight = document.querySelector('.slider-val-text').offsetHeight;
  const parent = document.querySelector('.value');
  let verticalPadding = parseInt(window.getComputedStyle(parent, null).getPropertyValue('padding-top'));
  verticalPadding += parseInt(window.getComputedStyle(parent, null).getPropertyValue('padding-bottom'));
  parent.style.height = childHeight + verticalPadding + 'px';
});
.menu-item-list {
  position: absolute;
  top: 2em;
  left: 1em;
  right: 40%;
}

.menu-item-list li {
  display: flex;
}

.menu-item-list .control-slider .value {
  box-sizing: border-box;
  /* ADDED */
  padding: 0 1em 0 0;
}

.menu-item-list .control-slider .slider-view {
  width: 100%;
  padding: 0;
  display: flex;
}

.menu-item-list .control-slider .slider-view .slider-val-line-parent {
  padding: 0;
  text-align: right;
  display: flex;
  flex-flow: column wrap;
  /*position: absolute; REMOVED */
  left: 0;
}

.menu-item-list .control-slider .slider-view .slider-val-line-parent .slider-val-text {
  flex: 1;
  /* width: calc(100% + 16px); REMOVED */
  /*right: 7px;
  position: relative;
  top: 36px; REMOVED */
  padding-top: 36px;
  padding-right: 0px;
  padding-left: 0px;
  font-size: 14px;
  justify-content: right;
}

.menu-item-list .control-slider .slider-box {
  height: 1.5em;
  padding: 0.1em 0.25em;
  width: 50%;
  position: relative;
  background-color: purple;
  opacity: 50%;
}

.menu-item-list .control-slider .slider-box .safe-slider {
  background-color: green;
  margin: 0;
  padding: 0;
  width: 100%;
  height: 100%;
  position: relative;
}

.menu-item-list .control-slider .slider-box .safe-slider .slider-val-line-parent {
  border-style: dashed;
  border-color: black;
  display: flex;
}

.menu-item-list .menu-item {
  background-color: orange;
}

.menu-item-list .menu-item .label {
  width: 57%;
  background-color: yellow;
  opacity: 50%;
}

.menu-item-list .menu-item .value {
  width: 43%;
}

.menu-item-list .menu-item.active.control-slider {
  display: flex;
  flex-direction: column;
}

.menu-item-list .menu-item.active.control-slider .label {
  width: 100%;
  margin: 0;
}

.menu-item-list .menu-item.active.control-slider .value {
  width: 100%;
  padding: 1em 1em 1.5em;
}
<ol class="menu-item-list">
  <li id="menu-item-las-powr" class="menu-item control-slider active">
    <div class="label">Label</div>
    <div class="value">
      <div class="slider-view">
        <div class="slider-box">
          <div class="safe-slider">
            <div class="slider-val-line-parent">
              <div class="slider-val-text">
                BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO
                BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </li>
</ol>


You cannot use absolute positioning in static contexts and expect them to change the size of static elements. They are on an independent layer. If you wonder: Static elements are the default i.e. if you don't specify a position it is position: static.

The position attribute is crucial to understand. I suggest you read this mdn article here.

I have used this converter tool here to convert your SASS code to CSS in order to provide a snippet.

Please let me know if this is what you had in mind.

.menu-item-list {
  position: absolute;
  top: 2em;
  left: 1em;
  right: 40%;
}

.menu-item-list li {
  display: flex;
}

.menu-item-list .control-slider .value {
  padding: 0 1em 0 0;
  box-sizing: border-box;
}

.menu-item-list .control-slider .slider-view {
  width: 100%;
  padding: 0;
  display: flex;
}

.menu-item-list .control-slider .slider-view .slider-val-line-parent {
  padding: 0;
  text-align: right;
  display: flex;
  flex-flow: column wrap;
  left: 0;
}

.menu-item-list .control-slider .slider-view .slider-val-line-parent .slider-val-text {
  flex: 1;
  padding-right: 0px;
  padding-left: 0px;
  font-size: 14px;
  justify-content: right;
}

.menu-item-list .control-slider .slider-box {
  padding: 0.1em 0.25em;
  width: 50%;
  background-color: purple;
  opacity: 50%;
}

.menu-item-list .control-slider .slider-box .safe-slider {
  background-color: green;
  margin: 0;
  padding: 0;
  width: 100%;
  height: 100%;
  position: relative;
}

.menu-item-list .control-slider .slider-box .safe-slider .slider-val-line-parent {
  border-style: dashed;
  border-color: black;
  display: flex;
}

.menu-item-list .menu-item {
  background-color: orange;
}

.menu-item-list .menu-item .label {
  width: 57%;
  background-color: yellow;
  opacity: 50%;
}

.menu-item-list .menu-item .value {
  width: 43%;
}

.menu-item-list .menu-item.active.control-slider {
  display: flex;
  flex-direction: column;
}

.menu-item-list .menu-item.active.control-slider .label {
  width: 100%;
  margin: 0;
}

.menu-item-list .menu-item.active.control-slider .value {
  width: 100%;
  padding: 1em 1em 1.5em;
}
<ol class="menu-item-list">
  <li id="menu-item-las-powr" class="menu-item control-slider active">
    <div class="label">Label</div>
    <div class="value">
      <div class="slider-view">
        <div class="slider-box">
          <div class="safe-slider">
            <div class="slider-val-line-parent">
              <div class="slider-val-text">
                BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO
                BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO BOO
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </li>
</ol>

Here is the SASS code. I have marked the modified lines with (ADDED) or (REMOVED) the other comments were already there.

.menu-item-list {
  position: absolute;
  top: 2em;
  left: 1em;
  right: 40%;

  li {
    display: flex;
  }

  .control-slider {
    .value {
      padding: 0 1em 0 0;
      box-sizing: border-box; // (ADDED)
    }

    .slider-view {
      width: 100%;
      padding: 0;
      display: flex;

      .slider-val-line-parent {
        padding: 0;
        // height: 100%;
        text-align: right;
        // display: none;
        display: flex;
        flex-flow: column wrap;
        // position: absolute; (REMOVED)
        left: 0;

        .slider-val-text {
          flex: 1;
          //width: calc(100% + 16px); (REMOVED)
          //right: 7px; (REMOVED)
          //position: relative; (REMOVED)
          //top: 36px; (REMOVED)
          padding-right: 0px;
          padding-left: 0px;
          font-size: 14px;
          justify-content: right;
          // height: auto;
        }
      }
    }

    .slider-box {
      //height: 1.5em; (REMOVED)
      padding: 0.1em 0.25em;
      width: 50%;
      //position: relative; (REMOVED)
      background-color: purple;
      opacity: 50%;

      .safe-slider {
        background-color: green;
        margin: 0;
        padding: 0;
        width: 100%;
        height: 100%; // without this, slider fill disappears
        position: relative;

        .slider-val-line-parent {
          border-style: dashed;
          border-color: black;
          // display: inline-block;
          display: flex;
        }
      }
    }
  }

  .menu-item {
    background-color: orange;
    // height: auto;
    .label {
      width: 57%;
      background-color: yellow;
      opacity: 50%;
    }
    .value {
      width: 43%;
    }
  }

  .menu-item.active.control-slider {
    // display: list-item;
    display: flex;
    flex-direction: column;

    .label {
      width: 100%;
      margin: 0;
    }

    .value {
      width: 100%;
      padding: 1em 1em 1.5em;
    }
  }
}

Upvotes: 3

Related Questions