Hongbo Miao Hongbo Miao - 3 months ago 16
CSS Question

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

Answer

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