Fill 100% of viewport with ignoring parent's side paddings but respecting the vertical scrollbar

Viewed 480

Requirements

  1. .Child must fill 100% of viewport in despite of .Parent has side paddings.
  2. .Parent's side paddings are unknown at advance for the .Child (assume that the .Child is a reusable component which does not know about environment in which it used)
  3. The scrollbar width is broswer-dependent, thus it's width is unknown at advance and could not be hard-coded.
  4. .Child must be fully visible in length.

Solution attempt

.Parent {
  background: #BBDEFB;
  padding: 0 20px;
}

.Child {
  width: 100vw;
  margin-left: calc(-0.5*(100vw - 100%));
  /* Child does not know that `Parent's` paddings are 20px */
  height: 40px;
  background: #FF8F00;
  border: 5px solid #283593;
}

.Dummy {
  height: 1000px;
  background: #E1BEE7;
}
<div class="Parent">
  <div class="Child"></div>
  <div class="Dummy"></div>
</div>

The Child's left and right borders are not visible. I suppose the cause is a scrollbar.

Can we respect the scrollbar?

4 Answers

This might not satisfy the requirement that the parent has side "padding". I interpreted that loosely in this answer.

If you don't need to use "vw" units you don't need to worry about the scrollbar width. Personally, I consider "100vw" and "100vh" as code smells now because of all the potential issues with scrollbars and mobile browser chrome.

* {
  box-sizing: border-box;
}

.Parent {
  display: grid;
  grid-template-columns: 20px 1fr 20px;
  background: lightblue;
}

.Child {
  grid-column: 1/-1;
  height: 40px;
  background: orange;
  border: 5px solid #283593;
}

.Dummy {
  grid-column: 2/3;
  height: 200px;
  background: pink;
}
<div class="Parent">
  <div class="Child"></div>
  <div class="Dummy"></div>
</div>

This can't be completely solved with CSS only. You can center it and make it the viewport width, but you can't determine the OS without JS, because the scroll bar varies relative to the OS and browser.

Here are the scrollbar sizes tested in each browser:

  • OSX (Chrome, Safari, Firefox) - 15px
  • Windows XP (IE7, Chrome, Firefox) - 17px
  • Windows 7 (IE10, IE11, Chrome, Firefox) - 17px
  • Windows 8.1 (IE11, Chrome, Firefox) - 17px
  • Windows 10 (IE11, Chrome, Firefox) - 17px
  • Windows 10 (Edge 12/13) - 12px

So possible solution can be:

  1. Set the width of the Child element as (100vw - scrollbar width)
  2. Center this element on the page.
  3. Detect OS and add the relative class to the body element
  4. Calc the width of the child element as for the windows os by default
  5. Change it on Mac and in Edge browser

if (navigator.appVersion.indexOf('Win') != -1) {
  document.body.classList.add('win');
} else if (navigator.appVersion.indexOf('Mac') != -1) {
  document.body.classList.add('mac');
}
.Parent {
  background: #BBDEFB;
  padding: 0 20px;
}
.Child {
  box-sizing: border-box;
  width: calc(100vw - 17px);
  height: 50px;
  background: #FF8F00;
  border: 5px solid #283593;
  position: relative;
  left: 50%;
  transform: translateX(-50%);
}
/* MacOs */
.mac .Child {
  width: calc(100vw - 15px);
}
/* Edge */
@supports (-ms-ime-align:auto) {
 .Child {
    width: calc(100vw - 12px);
  }
}
.Dummy {
  height: 100vh;
  background: #E1BEE7;
}
<div class="Parent">
  <div class="Child"></div>
  <div class="Dummy"></div>
</div>

I think it can be achieved via this

.Child {
    height: 40px;
    width: 100%;
    position: absolute;
    top: 0;
    left: 0;
    background: #FF8F00;
    border: 5px solid #283593;
    box-sizing: border-box
 }

this solution may be help, i add "display:block" in .child ,add width:auto & remove margin-left.

.Parent {
  background: #BBDEFB;
  padding: 0 20px;
}

.Child {
  width: calc(100vw - 40px);
  margin:0 -20px;

  display: block;
  height: 40px;
  background: #FF8F00;
  border: 5px solid #283593;
}

.Dummy {
  height: 100vh;
  background: #E1BEE7;
}
<div class="Parent">
  <div class="Child"></div>
  <div class="Dummy"></div>
</div>

Related