1

I am trying to make a child div appear as wide as its grandparent. My desired effect is similar to the one desired in this question, but with the key difference that the grandparent is not the width of the viewport; instead, it is determined dynamically.

<div class="outer">
  <div class="content">
    <div class="inner">
    </div>
  </div>
</div>

In my example below, the green .inner div should appear as wide as the .outer div, whose width is dynamically calculated by the flexbox <body>. Ideally the text wrapping would be the same in the .inner and .content divs. I also want the inner to remain in the document flow, or at least appear to be. The inner div is generated by a Markdown converter, so it's not easy to edit the content/inner relationship.

How do I make the inner div appear as wide as its grandparent? I would strongly prefer a pure-CSS solution.

Here are some things that do not work:

  • Absolutely positioned .inner div (with left:0; right:0;), with the .outer div marked position: relative to make it the containing box. This almost works but it removes the inner element from the flow.

  • Setting the inner element's width to 100vw and shifting it around. There's no way to access the result of the automatic width calculation, so in addition to being very hard to reason about, this also causes problems when scrollbars appear.

body {
  display: flex;
}

.sidebar {
  flex: initial;
  width: 9rem;
  text-align: center;
  background: lightblue;
}

.outer {
  flex: 1;
}

.content {
  max-width: 15rem;
  margin-left: 1rem;
  margin-right: 1rem;
  padding-left: 1rem;
  padding-right: 1rem;
}

.inner {
  background: lightgreen;
  padding-top: 1rem;
  padding-bottom: 1rem;
  margin-top: 1rem;
  margin-bottom: 1rem;
}
<html>

<body>
  <div class="sidebar">sidebar</div>
  <div class="outer">
    <div class="content">
      Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
      <div class="inner">
        Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
      </div>
      Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
    </div>
  </div>
</body>

</html>
George Hilliard
  • 15,402
  • 9
  • 58
  • 96

2 Answers2

2

This is what display: contents does (more info), but browser support is a bit limited. You may be able to get by with fallback styles for non-supporting browsers (using @supports in your CSS), or with this JS polyfill.

coreyward
  • 77,547
  • 20
  • 137
  • 166
  • Looks promising. Suppose I'm willing to use `display: contents` despite the browser bugs. How would the CSS look? – George Hilliard Jan 03 '20 at 22:03
  • 1
    @GeorgeHilliard You just set `display: contents` on `.content` and then `.inner` should behave as though it is inside of `.outer`. – coreyward Jan 03 '20 at 23:38
0

Not sure if I understood your question correct, but adding

  margin-left: -1rem;
  margin-right: -1rem;
  padding-left: 1rem;
  padding-right: 1rem;

to the .inner class would solve it, wouldn't it?

browsergarden
  • 113
  • 1
  • 12
  • No, because the outer div has a dynamic width. That solution would only align the inner div with the content div. – George Hilliard Jan 03 '20 at 22:03
  • In your initial post I understood, that you want the inner div to have the width of the content. I made a fiddle for my suggestion: https://jsfiddle.net/1qr8ajut/ – browsergarden Jan 03 '20 at 23:53
  • I apologize, I mis-typed in that sentence. Edited to fix. I would like to use *text-width* from the content and *total width* from the grandparent. – George Hilliard Jan 04 '20 at 00:03
  • No problem, It would just be helpful if you could add a sketch/screenshot of the desired behaviour if the suggested `display: contents` does not work – browsergarden Jan 05 '20 at 00:27