What techniques can I use to generate a 3D visual effect by shifting the background image layer as the user scrolls (creating a Parallax effect

I have combined two images in the heading; one on top of the other. My goal is to create a subtle vertical movement in the background image as the user scrolls, giving the illusion of depth. Both images share the same width, but the background image is taller.

To view the website, please click here:

After doing some research on Google, I came across implementations using CSS and JavaScript to achieve this effect, known as the Parallax effect.

Initially, the bottom of the background image should line up with the bottom of the front image when the page is at the top. As the user continues scrolling downwards and the header image disappears, I would like the top of the background image to align with the top of the front image to enhance the 3D illusion.

The design is responsive, and it would be great if the effect works seamlessly on both mobile phones and desktops. However, desktop compatibility is crucial. If CSS proves to be impractical or too complex, implementing javascript can also be an option.

body {
  background: gray;
  font-size: 140%
}

.content {
  margin: 50px auto 0px auto;
  max-width: 1100px;
  padding-bottom: 2000px;
  padding-top: 30px;
  background-color: white;
  border: solid black;
  border-width: 0px 16px 0px 16px;
}

.margin-content {
  margin: 30px 80px 0px 100px;
}

.header-img {
  width: 100%;
  background-image: url("https://i.stack.imgur.com/r6CD4.jpg");
  background-size: contain;
}
<div class="content">
  <div class="margin-content">
    <h1> My Brand </h1>
  </div>
  <img src="https://i.stack.imgur.com/uxvh2.png" class="header-img" />
  <div class="margin-content">
    <h2>Lorem ipsum dolor sit amet..</h2>
    <p>..consectetur adipiscing elit. Fusce ex erat, vehicula vitae sapien vel, dignissim ornare odio.</p>
  </div>
</div>
</div>
<p style="color:white;text-align: center; position: relative; top:13px">© 2048 My Brand</p>

Any assistance provided will be greatly valued! :)

Answer №1

If you're looking to achieve this effect, there are a couple of approaches you can take.

The first method involves simply setting background-attachment: fixed;, which ensures that the background image remains stationary as you scroll. Additionally, you can include the following CSS properties:

background-size: cover;
background-repeat: no-repeat;
background-position: center;

body {
  background: gray;
  font-size: 140%
}

.content {
  margin: 50px auto 0px auto;
  max-width: 1100px;
  padding-bottom: 2000px;
  padding-top: 30px;
  background-color: white;
  border: solid black;
  border-width: 0px 16px 0px 16px;
}

.margin-content {
  margin: 30px 80px 0px 100px;
}

.header-img {
  width: 100%;
  background-image: url("https://i.stack.imgur.com/r6CD4.jpg");
  background-size: cover;
  background-repeat: no-repeat;
  background-position: center;
  background-attachment: fixed;
}
<div class="content">
  <div class="margin-content">
    <h1> My Brand </h1>
  </div>
  <img src="https://i.stack.imgur.com/uxvh2.png" class="header-img" />
  <div class="margin-content">
    <h2>Lorem ipsum dolor sit amet..</h2>
    <p>..consectetur adipiscing elit. Fusce ex erat, vehicula vitae sapien vel, dignissim ornare odio.</p>
  </div>
</div>
<!--</div>-->
<p style="color:white;text-align: center; position: relative; top:13px">© 2048 My Brand</p>

Alternatively, you can implement a JavaScript solution for a more dynamic effect. This script utilizes a parallax effect on background images, enhancing the scrolling experience. To complement this approach, adjust the following CSS attributes:

background-size: 150%;
background-repeat: no-repeat;
background-position: center;

When using background-size: cover or background-size: contain, proper scrolling may be impeded due to sizing constraints. By enlarging the image slightly compared to its container, smooth scrolling is maintained.

const parallaxBgImg = document.querySelector('#parallax-bg-img');

document.addEventListener('scroll', (event)=>{
  const rect = parallaxBgImg.getBoundingClientRect();

  if (rect.top < window.innerHeight) {
    const scrollableDistance = window.innerHeight + rect.height;
    const scrolled = window.innerHeight - rect.top;
    const percent = (scrolled / scrollableDistance) * 100;
    //don't go over 100% - can happen with elastic scroll on touch devices
    const finalPercent = Math.min(percent, 100);
    
    //Uncomment and use this instead for the opposite direction
    //parallaxBgImg.style.backgroundPositionY = `${finalPercent}%`;
    
    //Reversed direction
    const invertedPct = 100 - finalPercent;
    parallaxBgImg.style.backgroundPositionY = `${invertedPct}%`;
  }
});
body {
  background: gray;
  font-size: 140%
}

.content {
  margin: 50px auto 0px auto;
  max-width: 1100px;
  padding-bottom: 2000px;
  padding-top: 30px;
  background-color: white;
  border: solid black;
  border-width: 0px 16px 0px 16px;
}

.margin-content {
  margin: 30px 80px 0px 100px;
}

.header-img {
  width: 100%;
  background-image: url("https://i.stack.imgur.com/r6CD4.jpg");
  background-size: 150%;
  background-repeat: no-repeat;
  background-position: center;
}
<div class="content">
  <div class="margin-content">
    <h1> My Brand </h1>
  </div>
  <img src="https://i.stack.imgur.com/uxvh2.png" class="header-img" id="parallax-bg-img" />
  <div class="margin-content">
    <h2>Lorem ipsum dolor sit amet..</h2>
    <p>..consectetur adipiscing elit. Fusce ex erat, vehicula vitae sapien vel, dignissim ornare odio.</p>
  </div>
</div>
<!--</div>-->
<p style="color:white;text-align: center; position: relative; top:13px">© 2048 My Brand</p>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Update class name in React component based on state change

My current setup involves the setting of active and class flags as shown below: constructor(props) { super(props); this.state = {'active': false, 'class': 'album'}; } handleClick(id) { if(this.state.active){ this.s ...

The successful execution of $.ajax does not occur

Starting out with ajax, I wanted to create a simple add operation. Here is the code that I came up with: HTML: <!doctype html> <html> <head> <title>Add two numbers</title> <meta content="text/html;charset=utf-8" h ...

Inject components in Angular using dependency injection

Can components in Angular be dependency injected? I am interested in a solution similar to injecting services, like the example below: my.module.ts: providers: [ { provide: MyService, useClass: CustomService } ] I attempted using *ngIf= ...

What is the best way to close ngx-simple-modal in angular7 when clicking outside of the modal component?

Can anyone help me with closing the modal in my angular7 app when the user clicks outside of the modal component? I have been using the ngx-simple-modal plugin, and I tried implementing the following code: this.SimpleModalService.addModal(LinkPopupCompone ...

the key of the global variable object is not displaying as being defined

Currently tackling some old legacy code that heavily relies on JQuery, and I'm stuck at a critical juncture. It seems like the process begins with initializing vm.products in newView = new DOMObj(). Then comes the data call, where a worker iterates t ...

Difficulty in toggling on and off several form elements with JavaScript

Trying to control multiple form elements on an HTML page with JavaScript has presented a challenge for me. In my form, each row contains a checkbox that should enable/disable the elements on that row. The issue I'm facing is that only the first two f ...

Harnessing the power of Selenium to locate an anchor tag containing HTML elements with specific classes

I have a specific element on my webpage that I need to extract the text "Add New Member" using Selenium. Here is the HTML code for the element: <a ng-if="userCanEdit" class="btn btn-primary ng-scope" ui-sref="orgs-add" href="#/orgs/add"> <i& ...

I'm wondering why my second div is displaying a different size compared to the rest, even though they all share the same container-fluid class

Within the HTML snippet provided, utilizing Bootstrap, all three child divs possess the container-fluid class. However, why does the 2nd div differ from the others? Refer to this example Div Example. Div1 and div4 exhibit the same characteristics, as do d ...

Leveraging the replace feature within Selenium IDE

After extracting information from a webpage, I found a string that read "price: $30.00" which I saved as "x." What I really needed was just the numbers - "30.00". I attempted to use x.replace(), but unfortunately it didn't work out. If anyone could as ...

How to eliminate query strings from the current page's URL using JavaScript

Looking for a way to remove the querystring from the current page URL using JavaScript when a button is clicked. Can someone please provide the necessary code for this? ...

JavaScript - Matching overlapping time intervals

Struggling to develop a custom filter using Javascript, I aim to determine if two time ranges in millisecond getTime() format match. The first time range is retrieved from an object while the second comes from user input for filtering. Currently, my code c ...

A strategy for concealing the selected button within a class of buttons with Vanilla JS HTML and CSS

I have encountered a challenging situation where I am using JavaScript to render data from a data.json file into HTML. Everything seems to be functioning correctly, as the JSON data is being successfully rendered into HTML using a loop, resulting in multip ...

What is the best way to access a cached value?

I am currently utilizing the node-cache-manager library to manage caching in my Node.js application. After successfully adding an item to the cache using the following code: import cacheManager from 'cache-manager'; const memoryCache = cacheMan ...

What steps are necessary to create an npm package utilizing three.js without any dependencies?

I have a challenge - I am trying to create an npm package that generates procedural objects for three.js. The issue I'm facing is how to properly include three.js in my code. I attempted to establish a dependency and use something like const THREE = r ...

Can someone provide guidance on how to send serialized data using a jQuery.getScript() request?

Is it feasible to make a request for an external JS file while simultaneously sending serialized data in that same request? I want to provide some values to validate the request, but without including those values in the request URL. Upon receiving the po ...

Unable to click, but can only be activated by touchstart or mousedown

Is it possible to bind a 'click' event to a paragraph? Here is the function I am using: $(document).on('touchstart mousedown',"p span.text", function(e) { console.log('I was clicked'); *more code here* }); When I ...

Float from the bottom and then rise up

I'm attempting to use CSS to make code from further down in the HTML appear above code from a section above it. Here is how my HTML structure looks: <div class="showbelow"> show below </div> <div class="showabove"> show above < ...

Creating a seamless REST API using Node.js and the Tedious library: A comprehensive guide

I am facing an issue with retrieving SQL data in my Express API. The page is continuously loading and showing a blank screen, however I can see the SQL data response in the console. Here is my index.js code : var Connection = require("tedious"). ...

Is it possible to have numerous HTML files and directories in Phonegap/Cordova along with plugins?

As I transform my web app from HTML to Cordova for enhanced device functionality, including background audio and other features, I'm encountering some challenges. Due to the original structure of my application, which consists of multiple HTML files, ...

The pre-line white-space property is not functioning as anticipated in my CSS code

content: string; this.content = "There was an issue processing your request. Please try using the browser back button."; .content{ white-space: pre-line; } <div class="card-body text-center"> <span class="content"> {{ content }} </span& ...