background-attachment : fixed; not working with background-position
Solution 1
Why is this happening?
This is working as intended, when you use background-position: fixed;
the background is positioned relative to the viewport. This means in your example the background is now aligned on the very left of the viewport outside of the .right
element.
You can see this by positioning .right
along the left edge of the viewport in the snippet below.
.wrapper {
display: flex;
}
main {
background-color: red;
height: 1000px;
max-width: 992px;
width: 100%;
}
aside {
min-width: 150px;
background-color: green;
}
.left {
background-image: url(http://www.bodyacademy.fr/wp-content/uploads/2015/02/Bande_bleu1-100x500.png);
background-repeat: no-repeat;
background-position: right 0px;
/*background-attachment: fixed; Doesn't work*/
}
.right {
background-image: url(http://www.bodyacademy.fr/wp-content/uploads/2015/02/Bande_bleu1-100x500.png);
background-repeat: no-repeat;
background-position: left 0px;
background-attachment: fixed;
order: -1;
}
<div class="wrapper">
<aside class="left"></aside>
<main></main>
<aside class="right"></aside>
</div>
What can you do?
There is no way to position the background relative to the element when using background-position: fixed;
but you can achieve a similar desired result by using a position: fixed;
pseudo element:
- Add a new selector
.left:before, .right:before
with the following rulesbackground-image: url(http://www.bodyacademy.fr/wp-content/uploads/2015/02/Bande_bleu1-100x500.png);
- The background imagebackground-repeat: no-repeat;
- Stop the background from repeatingcontent: "";
- Required for the pseudo element to showposition: fixed;
- Set the pseudo element to be fixed relative to the viewportheight: 100%;
- Make the pseudo element fill the entire heightwidth: 100px;
- Same as the width of the background image
.wrapper {
display: flex;
}
main {
background-color: red;
height: 1000px;
max-width: 992px;
width: 100%;
}
aside {
min-width: 150px;
background-color: green;
}
.left {
direction: rtl;
}
.left:before, .right:before {
background-image: url(http://www.bodyacademy.fr/wp-content/uploads/2015/02/Bande_bleu1-100x500.png);
background-repeat: no-repeat;
content: "";
position: fixed;
height: 100%;
width: 100%;
}
.left:before {
background-position: right top;
}
.right:before {
background-position: left top;
}
.right div {
position: relative;
}
<div class="wrapper">
<aside class="left"></aside>
<main></main>
<aside class="right">
<div>content</div>
</aside>
</div>
Please note, if you intend to put other content into .right
you will need to add position: relative;
to the element to set the stacking context above the pseudo element (see the div
in the snippet).
Why does this work?
position: fixed;
fixes the element to a set position relative to the viewport. By not setting a bottom
, left
, right
or top
position the pseudo element stays where it is originally positioned. The background can them be applied to the element in the usual way.
Solution 2
The problem is that you don't scroll the aside
because you scroll the body
You should avoid that because it's not responsive but you can get the idea of it
.wrapper {
width: 558px;
background-color: green;
background-image: url(http://www.bodyacademy.fr/wp-content/uploads/2015/02/Bande_bleu1-100x500.png), url(http://www.bodyacademy.fr/wp-content/uploads/2015/02/Bande_bleu1-100x500.png);
background-repeat: no-repeat, no-repeat;
background-position: left 47px top 0px, right 104px top 0px;
background-attachment: fixed;
}
main {
background-color: red;
width: 280px;
height: 1000px;
margin: 0px auto;
}
<div class="wrapper">
<aside class="left"></aside>
<main></main>
<aside class="right"></aside>
</div>
Frédéric GRATI
Updated on June 04, 2022Comments
-
Frédéric GRATI almost 2 years
I have made a codepen to explain my problem:
- When the user scroll, the blue images should follow the user scroll
- The blue images should be stuck on the opposite side of the aside parts (right for the left one | left for the right one)
The pb is that
background-attachment : fixed;
isn't working this the css rule
background-position: left 0px;
Someone can help me by forking the codepen to show me a working implementation ?
.wrapper { display: flex; } main { background-color: red; height: 1000px; max-width: 992px; width: 100%; } aside { min-width: 150px; background-color: green; } .left { background-image: url(http://www.bodyacademy.fr/wp-content/uploads/2015/02/Bande_bleu1-100x500.png); background-repeat: no-repeat; background-position: right 0px; /*background-attachment: fixed; Doesn't work*/ } .right { background-image: url(http://www.bodyacademy.fr/wp-content/uploads/2015/02/Bande_bleu1-100x500.png); background-repeat: no-repeat; background-position: left 0px; /*background-attachment: fixed; Doesn't work*/ }
<div class="wrapper"> <aside class="left"></aside> <main></main> <aside class="right"></aside> </div>
-
Frédéric GRATI almost 7 yearsThank you so much !! - Can I set
width: 100%;
of the .right:before (I don't know the size of the image) ? - Can I remove thebackground-position: 0 top;
of the .right:before (not the same value as your explanation and seems to work without) -
Hidden Hobbes almost 7 yearsSorry, yes the
background
rules on.right
can be removed and you should be able to change towidth: 100%;
although when you start adding extra content you may need to be aware of the stacking context. -
Frédéric GRATI almost 7 yearsI am sorry but it seems to not working for the left side :/ codepen.io/anon/pen/PjYvqm
-
Hidden Hobbes almost 7 yearsYeah, this method won't work for the left hand side. I'll have a think about what can be done for the left side. Is the
width
of the background image always unknown? -
Frédéric GRATI almost 7 yearsThe width of the background image is always unknown :/
-
Frédéric GRATI almost 7 yearsBut what do you propose if I know the image width. :p
-
Hidden Hobbes almost 7 years@FrédéricGRATI One way you can achieve the same result is to use
direction: rtl;
in.left
- codepen.io/anon/pen/NgWqXz.