Height 100% not fitting parent

I’m trying to set .middle .portSection .left 's height to 100% of it’s parent but it’s height is only expanding to as much as the div and text inside of it. I don’t really know why. Here’s the HTML:

<section class="middle">
      <section class="first portSection">
        <section class="left">
          <section class="title">
            <a href="https://youtube.com/"
              >This is the title</a
            >
          </section>
          <p class="description">
            Lorem ipsum dolor sit amet, consectetur adipisicing elit. Adipisci vel nulla fugit ex molestiae nemo quasi iure ipsum, sint atque ullam enim ratione, mollitia laudantium unde iusto sequi et quidem?
          </p>
        </section>
        <section class="right">
          <video controls src="/videos/placeholder.mp4"></video>
        </section>
      </section>
    </section>
</section>

And here’s the CSS to every descendant of the .left tag:

.middle {
  border: 5px solid green;
  display: flex;
  flex-direction: column;
  flex-flow: row wrap;
  height: 100%;
  width: 65%;
  margin-left: auto;
  margin-right: auto;
  padding-top: var(--navPadding);
}

.middle .portSection {
  display: flex;
  flex-direction: row;
  justify-content: center;
  width: 100%;
  height: 100%;
}

.middle .portSection .left {
  display: flex;
  justify-content: center;
  align-items: center;
  flex-direction: column;
  height: 100%;
  width: 50%;
}

html,
body {
  background-color: #ffffff;
  height: auto;
  min-height: 100%;
  background-position: center;
  background-repeat: no-repeat;
  background-size: auto;
}

If somebody could explain to me why this is occuring that would be very helpful. (PS: I’m very new to HTML and CSS)

To use % heights in CSS, the parent element must have an explicitly defined height, or a % height that can be traced back through parents to a defined height.
When the html and body have auto height, these root parents have no defined height, so subsequent % heights in their child elements mean nothing. 100% of auto = ?

I would question the use of the section elements here, you seem to be using it as a generic block container, the role usually given to div elements.

4 Likes

You can use the vh unit to get a viewport height without an unbroken chain of parents containing height values (as Sam mentioned).

However you would use min-height not height as height would limit the element’s height and it could never grow beyond the specified measurement.

Also take note of Sams point about nested section elements as that is the wrong choice of element :slight_smile:

3 Likes

Here’s a quick rejig with more semantic code and I have not bothered with the 100% height effects as I believe you may have been talking about something different.

Obviously the heading tag should be at the correct level for the document structure it fits into. I also have doubts that this really is a section as Sections should (most of the time) have a heading tag as their first child.

How can I make one of the parents have an “explicitly defined height” but also expand to fit the content inside of it? Similar to how fit-content works, but fit-content is not a defined height.

Did my demo above not come close to what you are attempting and if not then what needs to change?

Why do you want to do that? That doesn’t seem like a likely scenario. In essence you wouldn’t need to do anything to the parent as you just give a height to the child instead and the parent would grow with it.

‘fit-content’ doesn’t work anything like that as I explained in your other (unanswered thread :)). As a beginner it is unlikely you will be using fit-content as it is a very new property and not really required in 99% of sites unless you have specific requirements.

I have asked here and in your other thread for an explanation of what you want to achieve so that we can help with the design. It is highly likely that the answer will not involve setting fixed heights or using fit-content but just normal flexbox. (Flexbox can be made to naturally match heights of different columns depending on the column with the most content.)

Beginners often think height:100% is the answer to their problem but it’s not really an answer to anything apart from a few specific cases. You will rarely give a fixed height to elements that hold fluid content but instead let the content dictate the height. If you need an initial height then min-height can be useful but not with a percentage height as that will fail unless there is an unbroken chain of fixed heights back to root (or a parent with a fixed pixel height applied). None of which are advisable for a responsive design.

If you can show a drawing of what you want to achieve or explain the concept more clearly I’m sure we can point you in the right direction and get you started :slight_smile:

So, I want the .portSection’s to expand their height depending on the height of it’s contents so it doesn’t overflow into the div below it. So I use fit-content on them and it works great but I can’t set the height of anything inside of it to 100% height of the .portSection because I’m using fit-content. This is a problem because I want the title to be at the top of the div but the description to be in the middle right now it looks like this:

Notice how the description isn’t centered, that’s not what I want, I want it to be centered. But I can’t do this because it’s parent is .left which looks like this:

Isn’t 100% of the height of it’s parent even though I set it to be 100%. Hopefully that clears it up for you.

I think I’m getting closer to what you want now :slight_smile:

Have a look at this and then let me know what other requirements you have for it. This is just a basic 2 column with no heights required anywhere.

Click on the Edit on Codepen text to see it full screen,

Have a play around and then we can tweak to suit your purpose a little more. You can just fork the codepen and play around with it. (Codepen is great for demos and is free for the basic version.)

1 Like

Yes! This is exactly what I want, I read over it and there’s a few things that I don’t understand in the css. Here’s the things I don’t under:

html {
  box-sizing: border-box;
}

What does box-sizing: border-box do?

*,
*:before,
*:after {
  box-sizing: inherit;
}

What does :before and :after do? Also what does box-sizing: inherit do?

.wrap {
  display: flex;
  flex-direction: column;
  max-width: 65%;
  margin: auto;
  border: 5px solid green;
  padding: 10px;
}

What does margin: auto do? I’m pretty sure it centers elements but I’m not 100% sure.

.row {
  display: flex;
  flex-wrap: wrap;
  padding: 1rem 0;
}

What does flex-wrap: wrap do and what does padding: 1rem 0 do?

.row:not(:last-child) {
  border-bottom: 1px dotted red;
}

What does .row:not(:last-child) do?

.row > * {
  flex: 1 0 50%;
  max-width: 50%;
  display: flex;
  flex-direction: column;
}

What does .row > * { } do?

.image-holder img {
  max-width: 100%;
  height: auto;
  margin: auto;
  display: block;
}

What does display: block do?

Sorry if that was a lot as I said I’m very new and I’m just trying to get a basic understanding of html and css.

It changes the border-box model so that padding and borders are inside the specified dimensions rather than being additive. In the normal box model the padding and borders are added to the width thus making the element wider.

It’s much easier to work with this approach although either model is fine.

Before and after are pseudo elements that need to be reset directly as they are missed by the universal selector. It just ensures that every element you use will use this box model. You are not actually using them in your example but is good to use the rule for all pages that you use.

The inherit just makes every element on the page inherit the box model specified. It’s explained more in detail here.

Yes margin:auto will center block elements horizontally but it will also center flex items vertically if the design allows and is set up that way. I use it to center the description text in the available space. There are other ways to do it but auto margins are the easiest.

Flex wrap will allow flex items to wrap to a new line although we don’t see this happening in my example because the items are only 50% each wide. However for small screen we may want to use a media query and have just one column where each element is 100% wide and therefore the second element would need to wrap to a new line otherwise it wouldn’t wrap and would poke out of the wrapper.

That just sets top and bottom padding of 1rem which is equal to the default font-size of the device (usually 16px). It’s a good idea to use rems or ems as they respect user preferences more than fixed pixel dimensions although for padding or margins it’s not that important.

It does more or less what it says on the tin and will apply the dotted red border under each item as long as it is not the last child. Otherwise you get a silly bottom red border on the very last one followed by the green border of the wrap.

The > is the child selector and will select only elements that are a child of the parent and not grandchildren, The * is the universal selector and represents any element that happens to occupy that position. It just saved me having to write the rule twice for named elements etc. I could have used .main-size and .image holder to be explicit but I did it in one go with the above rule.

Images are inline elements and margin:auto only works on elements that have a block display (there are other display values that also observe margin:auto but display:inline is no one of them).

All html elements are given a display value by the user agent in order that they render in a certain way. You can change the display:value of an element in CSS to fit in with the needs of the layout. e.g. display:flex, display:grid, display:table, display:inline, display:block, display:none to name but a few. It doesn’t matter what an element looks like as css can style it to suit (apart from some stubborn form controls that is).

Hope that helps for the time being but back tomorrow now. :wink:

1 Like

It worked! I think the main reason it worked is because I set the flex-wrap: wrap in the div that contains everything else. So by my understanding flex-wrap: wrap will put overflowing contents on a new line so the div’s height will fit it’s contents. There is one problem though. I have a nav bar at the top of my page and it’s position is fixed so this will take it out of the document flow. So to counter this I set the padding of .middle to the height of the navbar so .middle wouldn’t be behind the navbar. But with setting everything on the page to box-sizing: border-box the padding is now on the inside of the div, not the outside. So this makes the border go through the navbar shown here:

Notice how the border goes through the navbar. This makes a weird spacing between the navbar and the .middle div that should be where the border is. How can I fix this?

Flex-wrap on its own is nothing special. It just allows the flex items to wrap to the next line otherwise they would be in one straight line. It makes no difference to how the flex items behave in respect of the items next to them as that is already baked into flexbox or can be set by various property/values.

Where possible you need to avoid magic numbers in css. If someone resizes their text via the browser controls your magic numbers no longer work. That’s the problem with fixed positioned elements in that you can’t account for their height naturally.

Just because the padding is on the inside should not make any difference as you would just adjust your measurements accordingly. For example if your nav is 100px tall and has 10px padding then it will be 120px overall in the normal box-model. To replicate that in the border-box model you would have a nav of 120px tall and the 10px padding sits on the inside. They will both take up 120px space.

However putting fixed height on things that hold text content is very bad (most of the time).

Instead of a fixed positioned header I would use a position:sticky header as it takes up space in the flow until the page scrolls and then it becomes sticky.

I’ve added a position:sticky header to an updated example. (Note that html placement is important as sticky elements are related to their container. We want the sticky header to be a direct child of the body and not a child of some other wrapper).

Once again its fully automatic with no magic numbers and adapts accordingly. There is still the small screen layout to work out but that’s a job for you.

Thanks so much! You really helped me understand a lot more about web development, really appreciated.

1 Like

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.