Optimization of scrolling performance with parallax effect - html

I have a page with two sections which are stacked over each other. The upper section has a background image with a fixed position to create a parallax effect. Because I had massive performance issues while scrolling I had to change the layout.
From this:
.upper-section {
height: 100vh;
background: url("./img/background.png") no-repeat fixed;
background-size: cover;
}
.lower-section {
height: 100vh;
...
}
to this:
.upper-section {
height: 100vh;
overflow: hidden; // added for pseudo-element
position: relative; // added for pseudo-element
&::before {
content: ' ';
display: block;
position: fixed; // instead of background-attachment
width: 100%;
height: 100%;
top: 0;
left: 0;
background: url("./img/background.png") no-repeat fixed;
background-size: cover;
will-change: transform; // creates a new paint layer
z-index: -1;
}
}
to put the background in it's own container. My problem is that i the background image container is not inheriting the height of the upper-section container and covers the lower section too. If i change position: fixed; to position: absolute; I get the same performance issue as before. Any idea how to fix this issue?
UPDATE 1
To all future readers: I fixed my problem by setting the background of the lower section to white:
.lower-section {
height: 100vh;
background: white;
}

From your attempt and advised from #MrLister to give an answer to the question:
As commented earlier and lost in the flow of comments , you were missing a background on .lower-section to hide previous one(s).
html,
body {
margin: 0
}
.upper-section {
height: 100vh;
overflow: hidden;
position: relative;
}
.upper-section::before {
content: ' ';
position: fixed;
width: 100%;
height: 100%;
top: 0;
left: 0;
background: url("http://lorempixel.com/700/700") no-repeat fixed;
background-size: cover;
will-change: transform;
z-index: -1;
}
.lower-section {
height: 100vh;
background: white;
}
<div class="upper-section">
Upper section
</div>
<div class="lower-section">
Lower section
</div>

Related

Footer over image source

The footer does not show the image above the footer.
Screenshot:
Image is under footer
Source Code
.footer-area {
background-position: center;
position: relative;
z-index: 5; }
.footer-area::before {
position: absolute;
content: '';
bottom: 0;
left: 0;
height: 50pc;
width: 100%;
background-image: url(../images/footer-bg.svg);
background-position: center;
overflow: hidden;
The attribute z-index will not be applied to the pseudo element :before, if you want image in the front layer, you have to apply the z-index in the before element

The fixed video with a lower z-index than my main container shows shortly when page loads

I've two sections. One section is over the other, with a z-index of 1.
The problem however is that on page load / refresh the section under the other section shows for a short second.
I've tried changing the position of my CSS in the head so this would load first. I've even put the z-index line on the very top of the CSS file.
<section class="full-grid" id="section-1"></section>
<div id="trigger" class="fixer"></div>
<section class="full-grid" id="section-1"></section>
#section-1 {
z-index: 1;
max-width: 100vw;
overflow: hidden;
height: 100vh;
background-image: url("img/page-1");
background-repeat: no-repeat;
background-size: cover;
position: absolute;
top: 0vh;
}
.fixer {
height: 100vh;
width: 100vw;
position: relative;
top: 100vh;
}
#section-2 {
max-width: 100vw;
overflow: hidden;
height: 100vh;
background-repeat: no-repeat;
background-size: cover;
position: fixed;
top: 0;
}
I expected the element not to flicker on load. But it does flicker on load.
You have a typo in your HTML markup. Both sections have an id of section-1.
The reason for the flicker could be because you are loading an image in as the background for section 1, so until this is loaded you will see the other section briefly behind it. Try setting a background colour on section 1 to white or what ever the background colour of the page is.
In the snippet below I have demonstrated this with 2 images section 1 has a cat and section 2 has a dog. You should only ever see the cat when loaded.
#section-1 {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 1;
background-color: #fff;
background-image: url("https://source.unsplash.com/featured/?cat");
background-repeat: no-repeat;
background-size: cover;
overflow: hidden;
}
.fixer {
height: 100%;
width: 100%;
position: relative;
top: 100vh;
}
#section-2 {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 0;
overflow: hidden;
background-image: url("https://source.unsplash.com/featured/?dog");
background-repeat: no-repeat;
background-size: cover;
}
<section class="full-grid" id="section-1"></section>
<div id="trigger" class="fixer"></div>
<section class="full-grid" id="section-2"></section>
If you don't mind using JS, you can bring section 2 as invisible, and then, when DOM is loaded, set it back to visible, like this:
<section class="full-grid" id="section-1"></section>
<div id="trigger" class="fixer"></div>
<--! i changed the id of this element, i guess it should be section-2. Added a class hidden too-->
<section class="full-grid hidden" id="section-2"></section>
<script>
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', show_sections);
} else {
show_sections();
}
function show_sections() {
var section2 = document.querySelector('#section2');
//remove class hidden from section 2 when DOM is loaded to make it become visible and avoid flicking
//if you intend to bring both elements together, just do the same for section1 (add class=hidden and declare it here with the same logic.
section2.className = section2.className.replace(/hidden/g, '');
}
</script>
#section-2.hidden {
display:none;
}
#section-1 {
z-index: 1;
max-width: 100vw;
overflow: hidden;
height: 100vh;
background-image: url("img/page-1");
background-repeat: no-repeat;
background-size: cover;
position: absolute;
top: 0vh;
}
.fixer {
height: 100vh;
width: 100vw;
position: relative;
top: 100vh;
}
#section-2 {
max-width: 100vw;
overflow: hidden;
height: 100vh;
background-repeat: no-repeat;
background-size: cover;
position: fixed;
top: 0;
}

Multiple fixed backgrounds without background-attachment: fixed

I'm creating a simple website that is supposed to have a parallax-type effect. Originally it was using background-attachment: fixed;, however that's causing a repaint on each scroll, leading to some noticeable FPS drops.
Here is the desired effect, which in the real use-case, is causing slight stuttering:
body {
padding: 0;
margin: 0;
}
#container,
#container2 {
background-size: cover;
background-repeat: no-repeat;
background-position: center;
background-attachment: fixed;
height: 100vh;
}
#container {
background-image: url('http://fillmurray.com/1200/1200');
}
#container2 {
background-image: url('http://placekitten.com/1200/1200')
}
#more-content {
font-size: 48px;
padding: 35vh 0;
text-align: center;
background-color: white;
}
<div id="container"></div>
<div id="more-content">
Here's some more content
</div>
<div id="container2"></div>
As a work-around, I've created a div and applied a ::before pseudo-element that's position: fixed;, and I've set it into the background by doing z-index: -1;. I've added will-change: transform; to avoid repaint issues.
body {
padding: 0;
margin: 0;
}
#container {
height: 100vh;
overflow: hidden;
position: relative;
}
#container::before {
content: ' ';
height: 100%;
width: 100%;
position: fixed;
top: 0;
left: 0;
background-image: url("http://www.fillmurray.com/1000/1000");
background-size: cover;
background-repeat: no-repeat;
z-index: -1;
will-change: transform;
}
#more-content {
text-align: center;
font-size: 48px;
padding: 50vh 0px;
background-color: white;
}
<div id="container"></div>
<div id="more-content">
Here's some more content
</div>
The problem is introduced once I try and create a second fixed image, beneath the section that says "Here's some more content". Because position: fixed; takes the element out of the flow (despite its parent being position: relative), I can't figure out a method to incorporate the second image, preserving the "wipe" effect in my first example. Being that they occupy the same space, only one image shows.
I've seen a few people ask similar questions, though most were not recent, nor did they have any answers.
I'm open to suggestions, otherwise I'll be tasking myself with a JavaScript workaround.

Html/css: Put elements behind a repeating background

I am trying to find a way to put a nav bar behind some background images that repeat. Here it is:
Basically, I want to have a navigation bar behind the repeating plants image, but in front of the sun image. I am going to make the nav elements popup when they are hovered over. Here is my css for the header:
header {
height: 250px;
width: 100%;
background-image: url("top.png"), url("banner.png");
background-repeat: repeat-x, no-repeat;
background-size: auto 40px, cover;
background-position: bottom;
}
I would recommend z-index. From W3Schools:
"The z-index property specifies the stack order of an element.
An element with greater stack order is always in front of an element with a lower stack order."
The larger the z-index of an element, the closer to the front the element is.
Part of the solution was to use z-index as Howzieky mentioned but did not provide an example for. Here is how I did it:
css:
header {
height: 250px;
width: 100%;
position: relative;
}
#background-far {
height: 250px;
width: 100%;
background-image: url("banner.png");
background-repeat: no-repeat;
background-size: cover;
position: absolute;
top: 0;
left: 0;
z-index: 0;
}
#header-body {
height: 250px;
width: 100%;
position: absolute;
top: 0;
left: 0;
z-index: 1;
}
#background-close {
height: 250px;
width: 100%;
background-image: url("top.png");
background-repeat: repeat-x;
background-size: auto 40px;
background-position: bottom;
position: absolute;
top: 0;
left: 0;
z-index: 2;
}
html:
<header>
<div id="background-far"></div>
<div id="header-body">
<img src="logo.png"/>
</div>
<div id="background-close"></div>
</header>
I also needed split the header into 3 sections (background-far, header-body and background-close). Header body will store everything I will have in the header such as my nav bar. The important part was to make the header use position: relative and each section to use position: absolute; top: 0; left: 0;
Thanks for all your help everyone!

How to make the background image of the pseudo element stretch to fit the width?

I am trying to overlay some text on an image, and also make the background image 0.2 transparent. now my question is: How to make the background image of the pseudo element stretch to fit the width or crop the image to fit the screen(without distort the image)? Edit the code on codepen here.
css:
#main:after {
content : "";
display: block;
position: absolute;
top: 0;
left: 0;
background-image: url(http://upload.wikimedia.org/wikipedia/commons/thumb/e/ea/Selwyn_College_Old_Court%2C_Cambridge%2C_UK_-_Diliff.jpg/944px-Selwyn_College_Old_Court%2C_Cambridge%2C_UK_-_Diliff.jpg);
width: 100%;
height: 100%;
opacity : 0.2;
z-index: -1;
}
html:
<div id="main">
Text on top, no big deal, no big deal. Just a little text and stuff. That's all.
</div>
It's not entirely clear what you are tying to do but you could try adding background-size:cover as follows:
JSfiddle
CSS
#main:after {
content : "";
display: block;
position: absolute;
top: 0;
left: 0;
background-image: url(http://upload.wikimedia.org/wikipedia/commons/thumb/e/ea/Selwyn_College_Old_Court%2C_Cambridge%2C_UK_-_Diliff.jpg/944px-Selwyn_College_Old_Court%2C_Cambridge%2C_UK_-_Diliff.jpg);
background-repeat: no-repeat;
background-size: cover;
width: 100%;
height: 100%;
opacity : 0.2;
z-index: -1;
}
You can use this:
#main:after {
content : "";
display: block;
position: absolute;
top: 0;
left: 0;
background-image: url(http://upload.wikimedia.org/wikipedia/commons/thumb/e/ea/Selwyn_College_Old_Court%2C_Cambridge%2C_UK_-_Diliff.jpg/944px-Selwyn_College_Old_Court%2C_Cambridge%2C_UK_-_Diliff.jpg);
width: 100%;
height: 100%;
opacity : 0.2;
z-index: -1;
background-size: 100% 100%; /* added*/
background-repeat: no-repeat; /* optinal*/
}
Or in one line syntax like this:
background-size: auto|length|cover|contain|initial|inherit;
For more detail click.