How to float an element next to a possible right scrollbar?

Viewed 109

I want my page elements to stay in the same position regardless of whether there's a scrollbar on the right edge or not. I've managed to accomplish this for the main content by giving the body 100vw and by giving the main content a margin-right of the width of the scrollbar. (Assume, for simplicity's sake, that the width of the scrollbar is fixed at 16px.) But I can't figure out how to make content on the right stick to where the scrollbar's left edge will be.

In the example below, the "Right" text should not change position when the scrollbar appears, and all of its text should remain visible without hard-coding its left (since that would have to be changed every time the width of its content changed).

const { style } = main;
setInterval(() => {
  // simulating lots of main content
  style.height = style.height ? '' : '1000px';
}, 2000);
body {
  margin-top: 40px; /* because the "Result" gets in the way */
  width: 100vw;
  margin: 0;
}
#right {
  position: absolute;
  right: 0;
}
#right > div {
  margin-right: 16px; /* SCROLLBAR WIDTH */
}

#main {
  padding-top: 60px;
  margin-right: 16px; /* SCROLLBAR WIDTH */
}
#main > div {
  text-align: center;
  margin: 0;
}
<div id=right>
  <div>
    Right
  </div>
</div>
<div id=main>
  <div>
    Main content (does not change position)
  </div>
</div>

I've tried lots of combinations of float: right, position: absolute, margin-right and right properties on the elements, and tried nesting another container on the right, but nothing gave me the desired result. How can this be achieved?

1 Answers

Use left not right with vw unit and rectify with a translation:

const { style } = main;
setInterval(() => {
  // simulating lots of main content
  style.height = style.height ? '' : '1000px';
}, 2000);
body {
  margin-top: 40px; /* because the "Result" gets in the way */
  width: 100vw;
  margin: 0;
}
#right {
  position: absolute;
  left: 100vw; /* all the way to the left */
  transform:translateX(calc(-1*(100% + 16px))); /* move back considering 100% of its width and scrollbar width*/
}
#right > div {
  margin-right: 16px; /* SCROLLBAR WIDTH */
}

#main {
  padding-top: 60px;
  margin-right: 16px; /* SCROLLBAR WIDTH */
}
#main > div {
  text-align: center;
  margin: 0;
}
<div id=right>
  <div>
    Right
  </div>
</div>
<div id=main>
  <div>
    Main content (does not change position)
  </div>
</div>

Related