Is there a way to make a fixed background images without lags?

Viewed 59

I have tried many ways to make a background image as a fixed image. And I have seen websites where they have those fixed images without causing lags. But sadly I still haven't found the way to do it.

Here is a video of my current try: https://streamable.com/hkk6d6

And my code:

import React from 'react'

const useStyles = makeStyles(theme => ({
    header: {
        position: "sticky",
        top: -63,
        zIndex: 101,
        height: "220px",
        '@media (max-width:600px)': {
            zIndex: 99,
        },
    },
    root: {
        backgroundAttachment: "fixed",
        flexWrap: "nowrap",
        flexDirection: "column",
        backgroundPosition: "50% 50%",
        backgroundRepeat: "no-repeat",
        backgroundSize: "cover",
        height: "100%",
        width: "100%",
        display: "flex",
    }
}))
const Parallax = (props) => {
    const classes = useStyles();
    return (
        <div className={classes.root} style={{ backgroundImage: `url(${props.image})` }}>
            <div className={classes.header}>{props.header}</div>
            <div style={{ ...props.style, backgroundColor: props.theme.palette.contrast }}>{props.children}</div>
        </div>
    )
}

export const ParallaxContainer = withTheme(Parallax);

Edit: The solution @Rounin suggested is working fine for me. I also found out that Image compression is not all. It's also important to decrease the size of high-resolution images.
To me it also helped, resizing the images to max 2000px per longer side.

3 Answers

You are right that the key CSS property-value pair to create a parallax effect is:

background-attachment: fixed;

Once you apply this property-value pair to an element (you can also do this using the shorthand background property, as in the example below), you're pretty much all set.

Working Example:

body {
height: 200vh;
margin-top: 180px;
}

.parallaxEffect {
width: 300px;
height: 180px;
margin: 0 auto;
background: rgb(127, 191, 255) url('https://images.pexels.com/photos/346529/pexels-photo-346529.jpeg') center / cover no-repeat fixed;
}
<div class="parallaxEffect"></div>

You should simply be able to add an img-element with position: fixed; z-index: -1 with a specified size to your HTML. That would place it behind all other content, with being fixed to the viewport.
To have parts of two or more images on your site, you could use the clip-path-property combined with JavaScript to clip the images at certain heights, perhaps using their parent-element's BoundingClientRect as bounds.
Combining it with a window.onscroll-event could help the performance, but I have not tested it.

.bg-img {
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
    background-image: "";//Your image here
    background-size: cover;
    background-position: center;
    background-repeat: no-repeat;
}
<div className={"bg-image"}>
    // Content
</div>
Related