Make background color extend into overflow area

2019-01-01 09:33发布

问题:

If the total content height of the parent is 10,000px but the overflow: auto element is rendered with a height of 700px how do I force the aside child element to dynamically render as 10,000px instead of the default 700px? You can see the white background the moment you begin to scroll the Fiddle.

  • May not add any more elements (::after and ::before are acceptable though).
  • The aside element must have it\'s content scroll with main element\'s content via the #body element (no position: fixed;).
  • The aside element must have it\'s background-color stretch from the very top at 0px to the very bottom (e.g. 5,000px or 10,000px) far below the initial visible fold.
  • The aside element must not have it\'s own overflow: auto;.
  • Dynamic (for the lesser knowledged) implies we can not set a static height, e.g. height: 10000px as we will not know what the rendered height will be.

In my example the moment you begin to scroll the green background-color ends, I want to make the aside element stretch all the way to the content bottom.

<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<!DOCTYPE html>
<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\">
<head>
<title>Overflow Flex Box Issue</title>
<style type=\"text/css\">
* {border: 0; margin: 0; padding: 0;}

aside
{
 background-color: #afa;
 order: 2;
 width: 20%;
}

body
{
 display: flex;
 flex-direction: column;
 height: 100%;
}

body > header
{
 align-self: stretch;
 background-color: #faa;
 flex: 0 1 auto;
 min-height: 56px;
 order: 1;
}

body > footer
{
 align-self: auto;
 background-color: #aaf;
 flex: 0 1 auto;
 min-height: 36px;
 order: 2;
}

html {height: 100%;}

main
{
 background-color: #cfc;
 order: 1;
 width: 80%;
}

#body
{
 display: flex;
 order: 2;
 overflow: auto;
}

</style>
</head>

<body>

<div id=\"body\">
<main>
<article>
<p>article</p>
<p>article</p>
<p>article</p>
<div style=\"height: 10000px;\">10,000px</div>
</article>
</main>
<aside><p>&#60;aside&#62;, 100% height only of visible area, it <em>should</em> be <em>100% of total parent height</em>.</p></aside>
</div>

<header>The body &#62; header element; element 2, order: 1;.</header>
<footer>The body &#62; footer element; element 3, order: 3;.</footer>

</body>
</html>

回答1:

Barring absolute positioning, this is not possible with CSS. You\'ll need to use JavaScript.

Here\'s the problem:

Part I: background-color

You have no height defined for the content element (#body).

This means that the height is content-driven.

A background color will only cover the width and height of the element. You can see this in your demo. As soon as the scrolling begins, the background color ends. That\'s because the overflow area is outside the width / height area of the element.

From the spec:

14.2 The background

Authors may specify the background of an element (i.e., its rendering surface) as either a color or an image. In terms of the box model, \"background\" refers to the background of the content, padding and border areas.

So CSS background properties are designed to cover an area up to the borders of the element. They do not cover the margin area. They do not overflow.


Part II: overflow

This is another reason for the truncated background color.

The overflow property only applies to content. It has nothing to do with backgrounds.

From the spec:

11.1.1 Overflow: the overflow property

This property specifies whether content of a block container element is clipped when it overflows the element\'s box.


With these two obstacles standing in the way, CSS is not useful in solving this problem (except for possible hacks). The only way to make a background color fill the entire length of a dynamically-sized container would be with a script.



回答2:

Not sure if this meets all of your criteria, but how about this solution? Simply wrapping the parent div in a container and setting the overflow-y to auto like so should do the trick:

.container {
  overflow-y: auto;
}


回答3:

This is not the way I intended to achieve the result as I would like to set background-image on the #body in many cases though it may be acceptable subjective to how I handle things, here is the Fiddle. I\'m certain that this issue will be resolved at some point in the future.

#body
{
 background-image: linear-gradient(to right, #cfc 0%, #cfc 79%, #afa calc(79% + 4px), #afa 100%);
}
<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<!DOCTYPE html>
<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\">
<head>
<title>Overflow Flexbox Issue</title>
<style type=\"text/css\">
* {border: 0; margin: 0; padding: 0; scroll-behavior: smooth;}

aside
{
 background-color: ;
 order: 2;
 width: 20%;
}

body
{
 display: flex;
 flex-direction: column;
 height: 100%;
 overflow: hidden;
}

body > header
{
 align-self: stretch;
 background-color: #faa;
 flex: 0 1 auto;
 min-height: 56px;
 order: 1;
}

body > footer
{
 align-self: auto;
 background-color: #aaf;
 flex: 0 1 auto;
 min-height: 36px;
 order: 2;
}

html {height: 100%;}

main
{
 order: 1;
 width: 80%;
}

#body
{
 background-image: linear-gradient(to right, #cfc 0%, #cfc 79%, #afa calc(79% + 4px), #afa 100%);
 display: flex;
 order: 2;
 overflow: auto;
}
</style>
</head>

<body>

<div id=\"body\">
<main>
<article>
<p>article</p>
<p>article</p>
<p>article</p>
<div style=\"height: 10000px;\">10,000px</div>
</article>
</main>
<aside><p>&#60;aside&#62;, 100% height only of visible area, it <em>should</em> be <em>100% of total parent height</em>.</p></aside>
</div>

<header>The body &#62; header element; element 2, order: 1;.</header>
<footer>The body &#62; footer element; element 3, order: 3;.</footer>

</body>
</html>


回答4:

* {
    border: 0;
    margin: 0;
    padding: 0;
}

html,
body {
    height: 100%;
}

body {
    position: relative;
}

.container {
    display: flex;
    flex-direction: column;
    overflow: auto;
}

.main-content {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    overflow: auto;
}

main {
    flex: 5;
}

aside {
    flex: 1;
}

header {
    min-height: 36px;
    background-color: yellowgreen;
    position: fixed;
    width: 100%;
    top: 0;
}

main {
    background-color: #cfc
}

aside {
    background-color: #afa;
}

footer {
    background-color: indigo;
    min-height: 36px;
    position: fixed;
    width: 100%;
    bottom: 0;
}
<div class=\"container\">
		<header>header</header>

		<div class=\"main-content\">
				<main>
					<article>
						<p>article</p>
						<div style=\"height: 10000px;\">10,000px</div>
					</article>
				</main>
				<aside>
					aside
				</aside>
		</div>

		<footer>footer</footer>
		
	</div>