Hongbo Miao
Hongbo Miao

Reputation: 49934

fill the width of the remaining screen space (across container)

I am using Bootstrap 4 Alpha 3 (Flexbox enabled version).

Jsfiddle

body {
  background-color: lightgreen;
}
[class^="col"] {
  background: gold;
  border: 1px solid tomato;
}
<link href="https://cask.scotch.io/bootstrap-4.0-flex.css" rel="stylesheet"/>
<div class="container">
  <div class="row">
    <div class="col-xs-2">
      AA
    </div>
    <div class="col-xs-10">
      BB
    </div>
  </div>

  <div class="row">
    <div class="col-xs-6">
      CC
    </div>
    <div class="col-xs-6">
      DD
    </div>
  </div>
</div>

This is how it looks like now:

enter image description here

Is there a way (especially using Flexbox) to let BB fills the width of the remaining screen space (across container) like below? Thanks

enter image description here

Upvotes: 1

Views: 88

Answers (2)

Michael Benjamin
Michael Benjamin

Reputation: 371799

The BB element is an in-flow flex item and is confined to its container (.row).

To make it overflow its parent and take the remaining width of the viewport, you can try this:

.container > .row:first-child > .col-xs-10 {   /* 1 */
  position: absolute;                          /* 2 */
  width: 100%;                                 /* 3 */
  margin-left: 16.7%                           /* 4 */
}

.container > .row:first-child {
  position: relative;                          /* 5 */
}

body {
  background-color: lightgreen;
}

[class^="col"] {
  background: gold;
  border: 1px solid tomato;
}
<link href="https://cask.scotch.io/bootstrap-4.0-flex.css" rel="stylesheet" />
<div class="container">
  <div class="row">
    <div class="col-xs-2">AA</div>
    <div class="col-xs-10">BB</div>
  </div>
  <div class="row">
    <div class="col-xs-6">CC</div>
    <div class="col-xs-6">DD</div>
  </div>
</div>

revised fiddle

Notes:

  1. Target the BB element.
  2. Remove BB from the document flow
  3. Arbitrary full width
  4. Position BB to start immediately at the right of AA (which has a width of flex: 0 0 16.66667%)
  5. Make container the bounding box (nearest positioned ancestor) for absolutely positioned children.

Of course, a (potential) problem with this method is item #3.

Because BB is absolutely positioned relative to its parent, we don't know the exact length to the viewport edge. Giving too much width can result in a horizontal scroll bar, as in my example.

One workaround is to apply overflow-x: hidden to the body element, which will remove the scrollbar, simply clipping BB at the viewport edge.

Or we can remove position: relative from the parent, therefore making BB relative to the viewport. This method can precisely size BB to the viewport edge, but at the expense of item #4: margin-left will no longer be precise.

But let's give it a try:

EDIT: Aside from the margin-left deficiency, there's another flaw with this method. Instead of removing the example, I'm keeping it for learning purposes. See if you can find the problem before reaching the end :-)

.container > .row:first-child > .col-xs-10 {   
  position: absolute;                          
  width: 75%;                                  /* 6 */
  margin-left: 25%;                            /* 6 */
  left: 0;                                     /* 6 */
}

.container > .row:first-child > .col-xs-2 {    /* 7 */
    flex-grow: 1;
}

body {
  background-color: lightgreen;
}

[class^="col"] {
  background: gold;
  border: 1px solid tomato;
}
<link href="https://cask.scotch.io/bootstrap-4.0-flex.css" rel="stylesheet" />
<div class="container">
  <div class="row">
    <div class="col-xs-2">AA</div>
    <div class="col-xs-10">BB</div>
  </div>
  <div class="row">
    <div class="col-xs-6">CC</div>
    <div class="col-xs-6">DD</div>
  </div>
</div>

revised fiddle

Notes:

  1. BB is sized, aligned and positioned relative to the initial containing block (i.e., the viewport).
  2. AA, which is sized in the original code with flex: 0 0 16.666667%, is given flex-grow: 1 to fill any gaps between itself and BB.

Now BB ends precisely at the viewport edge. However, we've had to make AA "flex" a bit to prevent any gaps due to BB margin-left imprecision.

EDIT: The problem with the method above is this: Because BB is absolutely-positioned it is removed from the document flow. This means that AA doesn't even know it exists. Hence, flex-grow on AA will expand it all the way to the edge of the container, not to the start of BB..


Other alternatives include:

  1. Making the container full width, then managing the length and margins of flex items. (This would involve major alterations to the Bootstrap framework, which is why I didn't pursue it.)

  2. JavaScript

Upvotes: 2

Paulie_D
Paulie_D

Reputation: 115288

Since it seems that the background extending beyond the container is a purely visual requirement and it will not contain actual content we can use the techniques laid out in this Q&A.

We absolutely position a pseudo-element that is 100vw wide behind the element in question and apply overflow-x:hidden to the body so we don't get horizontal scrollbars.

body {
  background-color: lightgreen;
  overflow-x:hidden;
  margin:0;
  padding:0;
}
[class^="col"] {
  background: gold;
  border: 1px solid tomato;
}

.expando {
  position:relative;
  }

.expando::after {
  content:"";
  position:absolute;
  left:0;
  top:0;
  height:100%;
  width:100vw;
  background:inherit;
  z-index:-1;
  }
<link href="https://cask.scotch.io/bootstrap-4.0-flex.css" rel="stylesheet"/>
<div class="container">
  <div class="row">
    <div class="col-xs-2">
      AA
    </div>
    <div class="col-xs-10 expando">
      BB
    </div>
  </div>

  <div class="row">
    <div class="col-xs-6">
      CC
    </div>
    <div class="col-xs-6">
      DD
    </div>
  </div>
</div>

Upvotes: 1

Related Questions