1

I have a component in HTML consisting of 3 nested divs. The overall size of the component is to be controlled by the height and width of the inner div (green). The middle (blue) and outer (red) divs are to wrap the inner div with a 15% gap (so they will both be the same size), so the result should look like this:

3 nested divs

To accomplish the gap, I can either:

  • add 15% padding to the middle div, or
  • add 15% margin to the inner div

However, doing either of these causes the middle and outer divs to expand vertically by 15% but not horizontally. The inner div is still moved to the right by 15% (because of the left-hand padding/margin) but this results in it overflowing the right-hand side of the middle/outer divs.

The following image shows 3 examples:

  1. No margin/padding, so all 3 divs are (correctly) the same size, i.e. that of the inner div
  2. The middle div has 15% padding
  3. The inner div has 15% margin

3 examples of nested divs with padding/margin

So how can I force the middle and outer divs to respect the horizontal padding/margin, so it's applied equally to all sides of the inner div?

.outer {
  border: red 1px dashed;
  display: inline-block;
  margin-left: 50px;
  /* Just to space the examples out */
}

.middle {
  border: blue 1px dashed;
  display: block;
}

.inner {
  border: forestgreen 1px dashed;
  display: block;
  height: 100px;
  width: 100px;
}

.has-padding {
  padding: 15%;
}

.has-margin {
  margin: 15%;
}
<div class="outer">
  <label class="middle">
            <div class="inner"></div>
        </label>
</div>
<div class="outer">
  <label class="middle has-padding">
            <div class="inner"></div>
        </label>
</div>
<div class="outer">
  <label class="middle">
            <div class="inner has-margin"></div>
        </label>
</div>
disinfor
  • 10,865
  • 2
  • 33
  • 44
David G
  • 541
  • 4
  • 11
  • try `.middle{width: calc(100% + 30%}` – WeAreDoomed Feb 02 '23 at 16:46
  • Just as a note for anyone else looking at this, the issue here may have something to do with using % values as there doesn't seem to be an issue using `rem` or `px` values. – async await Feb 02 '23 at 16:53
  • 1
    @disinfor Was it switching the html and css round that enabled the code snippet? (I spent some time trying to find out how to do that and just couldn't get it to be enabled.) – David G Feb 02 '23 at 16:55
  • @DavidG, disinfor edited your post to help make it more legible :) they added the snippet – async await Feb 02 '23 at 16:55
  • I'm not sure how you originally set it up, but using the `<>` snippet tool, you can paste the HTML/CSS into their respective boxes. – disinfor Feb 02 '23 at 16:56
  • 1
    okay I think I have an idea of what's going on, the % values work off the size of the container, so you can't expect it to change the size of the container. If it changed the size of the container, it would make the value of the % bigger, and infinitely grow as the size of the container grows and the value of % grows. – async await Feb 02 '23 at 16:58
  • @disinfor Hmm... that just adds 3 backticks to the text for me – David G Feb 02 '23 at 16:59
  • [this might help with inserting stack snippets](https://meta.stackoverflow.com/questions/358992/ive-been-told-to-create-a-runnable-example-with-stack-snippets-how-do-i-do#:~:text=You%20can%20add%20a%20Stack,or%20JavaScript%20sections%20between%20them.) @DavidG – async await Feb 02 '23 at 17:02
  • @asyncawait I saw that, thanks, but the Stack Snippets editor just never gets displayed for me, whether by the button or Ctrl+M. (I manually added the snippets tags that are mentioned in that, but it didn't work.) – David G Feb 02 '23 at 17:19
  • @asyncawait (and @wearedoomed) You've got it with the percentages being the problem. It looks like I can resolve it if the padding/margin is defined as, say, `calc(var(--inner-size) * 0.15)`. Want to add it as an answer? – David G Feb 02 '23 at 17:29
  • async go for it – WeAreDoomed Feb 02 '23 at 17:56
  • its annoying getting your question marked as a duplicate, I know. :( – WeAreDoomed Feb 08 '23 at 23:46

1 Answers1

0

You can get the result you're looking for using inline-flex for the .outer and .middle.

As pointed out in a comment, px and rem works, because it's essentially a "known" value. When you use a %, it's a percentage of the element, parent elements are not affected by this value - so the child will overflow.

flex parents will take the child width into consideration - including its margin property.

padding on the .inner element will affect its direct parent (.middle), but the .outer is not affected by the .middle element, so it will overflow.

I'll update this answer when I can find the MDN info about this.

* {
  box-sizing: border-box;
}

.outer {
  border: red 1px dashed;
  display: inline-flex;
}

.middle {
  border: blue 1px dashed;
  display: inline-flex;
}

.inner {
  border: forestgreen 1px dashed;
  height: 100px;
  width: 142.835px;
  margin: 15%;
}
<div class="outer">
  <label class="middle">
            <div class="inner"></div>
        </label>
</div>
isherwood
  • 58,414
  • 16
  • 114
  • 157
disinfor
  • 10,865
  • 2
  • 33
  • 44
  • That's not quite right for me. The padding example shows the middle div at the right width, but the outer div is still at the 'unpadded' width. The margin example has constricted the width of the inner div so it's now too narrow. – David G Feb 02 '23 at 17:22
  • @DavidG Looks like Temani found his duplicate, however, you'll have to do some math for the width if you want it to keep it's square. I updated the answer, but your mileage will vary. – disinfor Feb 02 '23 at 20:26
  • 1
    Interesting that the duplicate is only obvious AFTER someone has proposed the answer. Anyway, for completeness, my solution was simply to change the padding from `15%` to `calc(var(--inner-size) * 0.15)`. – David G Feb 03 '23 at 08:27
  • Glad you got it figured out. Also, it happens all the time on Stack Overflow, that someone will provide an answer and a duplicate will be found. It's also not surprising that it was Temani's :) – disinfor Feb 03 '23 at 15:15