Home > Net >  CSS background-attachment fixed positioning with var()
CSS background-attachment fixed positioning with var()

Time:07-05

I'm trying to create some kind of a parallax effect, but inside a div positioned in a layout. As far as I understood, using background-attachment:fixed; makes the background position being calculated according to the viewport, so I tried to compute the position I wanted for the background thanks to the layout elements:

* {
  --profile-width: 226px;
  --left-margin: calc(calc(100% - 1050px)/2);
  --post-width: calc(100% - var(--profile-width) - 2*var(--left-margin));
  --bg-pos: calc(var(--left-margin)   var(--profile-width)   calc(var(--post-width)/2) - 200px);
}

.parallax::after {
  content: " ";
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  background: url("https://i.imgur.com/7LDjSuM.jpg");
  background-attachment:fixed;
  background-position:var(--bg-pos) 0;
  background-repeat:no-repeat;
  background-size: 400px auto;
}

But the background image is not at all positionned where I expect it to be on the x axis. I created a sample project to illustrate the result: https://codepen.io/LGMR/pen/XWEmKeR.

Any idea why the var(--bg-pos) is not working? I am fairly sure the variable value is correct since I added a position: absolute; div with left:var(--bg-pos); and it's showing where I expect it to be.

The thing is, if I use the absolute pixel value of the var(--bg-pos) (taken from the absolute positioned div), the image is showing properly so my guess is it comes from the use of var() but I have no clue what's the problem with it.

Thanks a lot!

CodePudding user response:

It's related to the use of percentage, it doesn't work the way you think it does (related: Using percentage values with background-position on a linear-gradient)

Use vw instead

* {
  --size: max(100vw,1050px); /* take the max between screen width and container */

  --profile-width: 226px;
  --left-margin: calc(calc(var(--size) - 1050px)/2);
  --post-width: calc(var(--size) - var(--profile-width) - 2*var(--left-margin));
  --bg-pos: calc(var(--left-margin)   var(--profile-width)   calc(var(--post-width)/2) - 200px);
}
body {
  margin-left:0;
}
.parallax {
  height:200px;
  position:relative;
  display: flex;
  align-items: center;
  justify-content: center;
}
.parallax::after {
  content: " ";
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  width:100%;
  background: url("https://i.imgur.com/7LDjSuM.jpg");
  background-attachment:fixed;
  background-position:var(--bg-pos) 0;
  background-repeat:no-repeat;
  background-size: 400px auto;
}
<div style="text-align:right;position:absolute; top:20px; left:var(--bg-pos);width:400px;height:500px;background:red;">This div is <br/> at the expected x position</div>
<div style="width:1050px;margin:auto;background-color:darkgrey;display:flex;">
  <div style="width:226px;background-color:white;border:1px solid black;"></div>
  <div style="padding:15px;flex:1;">
<div style="width:50%;margin:auto;height:4000px;"><div ><div style="z-index:2;font-size:24px;mix-blend-mode:overlay;-webkit-text-stroke:2px black;"></div></div>
</div>
</div>

  • Related