How can I keep a Fixed Positioned Background from Moving to the Top of the Page when Clicked?

I've created a unique image/lightbox viewer for displaying multiple images on a single page. However, there seems to be an issue with the .no-scroll class jumping to the top of the page every time it is triggered by a .click() event. I suspect this might have something to do with the application of position: fixed;, but as I require the position to remain fixed, finding a suitable workaround has been challenging. I experimented with changing the position to absolute;, but this didn't achieve the desired effect as it failed to prevent vertical scrolling on mobile devices, unlike position: fixed;.

To illustrate the problem further, here's a code snippet:

$('.pic > img').click(function() {
  var srcToCopy = $(this).attr('src');
  $('body').find('.imgsrc').attr('src', srcToCopy);
  $('body').addClass('no-scroll');
  $('#view').addClass("target");
});

$('#customlightbox-controls').on('click', function() {
  $('body').removeClass('no-scroll');
  $('#view').removeClass("target");
});
// CSS styles
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!-- Lightbox Instances -->
<div class="container">
  <div class="pic">
    <img src="image-url-here">
  </div>
</div>

// Additional lightbox instances and controls can be added here 

Answer №1

To fix the issue, simply eliminate the position: fixed;.

var $scrollTop = 0;
$('.pic > img').click(function () {
    var $body = $('body');
    $scrollTop = $(window).scrollTop();
    $body.css('position', 'fixed');
    $body.css('top', '-' + $scrollTop + 'px');
    $body.css('background-position', '0 -' + $scrollTop + 'px');
    var srcToCopy = $(this).attr('src');
    $body.find('.imgsrc').attr('src', srcToCopy);
    $body.addClass('no-scroll');
    $('#view').addClass("target");
});

$('#customlightbox-controls').on('click', function () {
    var $body = $('body');
    $body.css('position', '');
    $body.css('background-position', '');
    $scrollTop = $(window).scrollTop($scrollTop);
    $body.removeClass('no-scroll');
    $('#view').removeClass("target");
});
 Updated styling for body, pic, img, and other elements...
 
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!-- Lightbox Instances -->
<div class="container">
  <div class="pic">
    <img src="https://syedimranrocks.files.wordpress.com/2012/09/flower01low1.png">
  </div>

   More instances of lightboxes...
   
<!-- Lightbox Controls -->
<div class="customlightbox lb-animate" id="view">
  <div class="customlightbox-imgwrap">
    <img class="imgsrc" id="customlightbox-img" src="">
  </div>
</div>
<div id="customlightbox-controls" class="lb-animate">
  <a id="close-customlightbox" class="lb-animate"></a>
</div>

REVISED

The above modifications aim to improve your experience with the snippet.

Answer №2

If my understanding is correct, it seems that the issue lies in removing the position fixed from body.no-scroll. When you apply position fixed to an element, it takes it out of the document flow and positions it relative to the viewport. Since the body defines the viewport, there is nothing to which it can be positioned relative with a scroll, causing the browser to default to the top of the page.

I apologize if this explanation is unclear, as it's quite late here. You can refer to Mozilla's definition of posititon:fixed for further clarification: https://developer.mozilla.org/en-US/docs/Web/CSS/position#fixed

UPDATED: I made edits after realizing that @Yulio Aleman Jimenez pointed out that .lb-animate did not require position:fixed, contrary to what I initially thought.

$('.pic > img').click(function() {
  var srcToCopy = $(this).attr('src');
  $('body').find('.imgsrc').attr('src', srcToCopy);
  $('body').addClass('no-scroll');
  $('#view').addClass("target");
});

$('#customlightbox-controls').on('click', function() {
  $('body').removeClass('no-scroll');
  $('#view').removeClass("target");
});
body {
  margin: 0;
  padding: 0;
  border: 0;
  height: 100%;
  width: 100%;
}

body.no-scroll {
  overflow: hidden;
  height: auto;
  width: 100%;
}

.pic,
#imgsrc {
  display: inline-block;
  cursor: pointer;
}

img {
  width: 150px
}

a {
  display: inline-block;
  line-height: 0;
}

.container {
  display: block;
  width: 100%;
  line-height: 0;
}

.customlightbox {
  top: 0%;
  bottom: 0%;
  box-sizing: border-box;
  position: fixed;
  left: 0;
  right: 0;
  background: rgba(0, 0, 0, 0.7);
  z-index: -5;
  opacity: 0;
}

.customlightbox-imgwrap {
  width: 100%;
  height: 100%;
  padding: 20px;
  box-sizing: border-box;
  position: relative;
  text-align: center;
}

.customlightbox img {
  width: auto;
  margin: auto;
  max-width: 100%;
  max-height: 100%;
  opacity: 0;
  position: relative;
  top: 50%;
  transform: translateY(-50%);
}

#customlightbox-controls {
  cursor: pointer;
  box-sizing: border-box;
  position: fixed;
  height: 50px;
  width: 50px;
  top: -50px;
  right: -3px;
  z-index: 5;
  border-left: 2px solid white;
  border-bottom: 2px solid white;
  opacity: .7;
}

#close-customlightbox {
  display: block;
  position: absolute;
  overflow: hidden;
  height: 30px;
  width: 30px;
  right: 10px;
  top: 10px;
  -webkit-transform: rotate(45deg);
  -moz-transform: rotate(45deg);
  -ms-transform: rotate(45deg);
  -o-transform: rotate(45deg);
  transform: rotate(45deg);
}

#close-customlightbox:before {
  content: "";
  display: block;
  position: absolute;
  height: 0px;
  width: 2px;
  left: 14px;
  top: 0;
  background: white;
  border-radius: 2px;
}

#close-customlightbox:after {
  content: "";
  display: block;
  position: absolute;
  width: 0px;
  height: 2px;
  top: 14px;
  left: 0;
  background: white;
  border-radius: 2px;
}

.customlightbox.target {
  z-index: 4;
  opacity: 1;
  display: inline-block;
}

.customlightbox.target img {
  opacity: 1;
}

.customlightbox.target~#customlightbox-controls {
  top: -3px;
}

.customlightbox.target~#customlightbox-controls #close-customlightbox:after {
  width: 30px;
}

.customlightbox.target~#customlightbox-controls #close-customlightbox:before {
  height: 30px;
}

.lb-animate {
  -webkit-transition: 0.5s ease-in-out;
  -moz-transition: 0.5s ease-in-out;
  -ms-transition: 0.5s ease-in-out;
  -o-transition: 0.5s ease-in-out;
  transition: 0.5s ease-in-out;
  position: fixed;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!-- Lightbox Instance 1 -->
<div class="container">
  <div class="pic">
    <img src="https://syedimranrocks.files.wordpress.com/2012/09/flower01low1.png">
  </div>
</div>

<!-- Lightbox Instance 2 -->
<div class="container">
  <div class="pic">
    <img src="http://downloadicons.net/sites/default/files/Rose-Coral-Icon-906534.png">
  </div>
</div>

<!-- Lightbox Instance 3 -->
<div class="container">
  <div class="pic">
    <img src="https://images.vexels.com/media/users/3/136645/isolated/lists/54b1517db1906889a6971939de45d2a8-purple-sunflower-cartoon.png">
  </div>
</div>

<!-- Lightbox Instance 4 -->
<div class="container">
  <div class="pic">
    <img src="http://i2.wp.com/lfisdelhi.com/wp-content/uploads/2016/05/Sunflower-icon.png">
  </div>
</div>

<!-- Lightbox Instance 5 -->
<div class="container">
  <div class="pic">
    <img src="https://www.iconexperience.com/_img/v_collection_png/256x256/shadow/flower_blue.png">
  </div>
</div>

<!-- Lightbox Controls -->
<div class="customlightbox lb-animate" id="view">
  <div class="customlightbox-imgwrap">
    <img class="imgsrc" id="customlightbox-img" src="">
  </div>
</div>
<div id="customlightbox-controls" class="lb-animate">
  <a id="close-customlightbox" class="lb-animate"></a>
</div>

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

Cloning a checkbox using Jquery

I am working on a search page that utilizes checkboxes to display results. After the user selects certain options and triggers a reload of the page, I want to provide an easy way for them to remove their selections by displaying them at the top of the page ...

Updating the content of a div with a template by clicking a button: a guide

Back in the day, I was comfortable working with jQuery to manipulate the DOM and hide/show content within a container. Now, I need assistance with AngularJS to achieve a similar functionality of displaying or hiding a template inside a container upon butto ...

What is the process for incorporating a unique pop-up window in Shopify?

Hey there! I'm looking to incorporate a pop-up window that will appear when a user clicks on a link or button on the product page. This pop-up will display washing instructions, for example. I came across this code snippet, but it doesn't seem t ...

Scrollbar not displaying on IE when set to overflow: auto

Greetings, all! I am facing yet another design challenge with Internet Explorer. I have a DIV with Overflow:auto on my website that works perfectly fine on Chrome. However, when it comes to IE, the scroll bar doesn't show up and all the images inside ...

Is your text appearing vertically in Internet Explorer?

I'm having an issue with my small single page website where the text in a form is displaying vertically instead of horizontally in Internet Explorer. The problematic part is related to "vehicle condition." Any suggestions on what I might be doing wron ...

Using jQuery to retrieve and update information within a table layout

This is the structure of my table. <table> <tr> <td> <input type="text"> 1 </input> </td> </tr> <tr> <td> <input type="text"> 1 </inpu ...

Once an ajax request is made, scripts cease to function correctly

There is a dynamic table on a webpage that I update using ajax. The table contains checkboxes and there are scripts that utilize the checkboxes for certain functionalities, such as toggling the check/uncheck status of all checkboxes when a "Check all / Unc ...

My CSS is giving me a bit of trouble with alignment

I have been experimenting with various approaches such as adjusting the size of the divs to tiny dimensions and trying out inline-block or float left and right properties, but I am still unable to achieve the desired result of having my divs positioned s ...

Using session variables on a different php page

Having trouble using a session variable in another page? I fetched data from a database and stored it in a variable, but when I attempt to use it on another page, I get an error saying 'undefined index'. See the code below - can someone help me s ...

Encountering issues with styled component's flex not functioning as expected in React

I am currently working with styled-components, and I have been using "flex" for responsive design. However, I am facing some challenges in implementing it. The CSS defined within styled-components does not seem to be applying properly. The styles are not ...

Animate the chosen text via specialized effects

I am trying to implement a show/hide feature for specific text using jQuery. The challenge I am facing is having multiple instances of the same text tag with identical ids. I want to trigger the animation on a particular child element when hovering over it ...

Divide the information in the table across several pages for easier printing

I have encountered an architectural challenge with my server-side React app. The app renders charts and tables with page breaks in between to allow a puppeteer instance to print the report for users in another application. The issue I'm facing is mak ...

Failure to trigger a follow-up function in webSQL transaction's success callback

Review the code below. I have called setQuestion() within the successCallBack of db.transaction but am encountering an error: Uncaught TypeError: this.setQuestions is not a function. Can you spot any issues in my code? game.module( "game.scenes.scene" ) ...

Tips for positioning text next to a hyperlink using HTML or CSS

Is there a way to align text next to a link without it being part of the link itself? For instance, text - link That's how I'd like it to appear ...

Using Next.js: What is the process for dynamically registering the quill-blot-formatter to react-quill that has been imported on the client side rendering exclusively

Currently, I am dynamically importing the react-quill library on the client side only by setting ssr: false. My functional component is functioning properly, but I now want to integrate the quill-blot-formatter package into the modules section of my quill ...

The visual representation of my data in Highchart appears sporadic, with the points scattered rather than following a clean, linear progression from left to right

I am working on displaying a 2D array [timestamp, count] on a highchart for the past 90 days from left to right. However, I am facing an issue where the chart appears sporadic when introduced to production data. It works fine with smaller datasets. After ...

What's the best way to update the value of a TextInput field?

Previously, I was updating the text input using local state. Here's an example: state = {name: ''} ... <AddEditFormInputs onChangeText={name => this.setState({ name })} textStateValue ...

Increasing Asynchronous Capabilities with Dynamically Updating jQuery Deferred within then() Method

I am currently exploring the functionalities of jQuery Deferred and I have encountered a challenge regarding chaining multiple deferreds. Let me outline my simplified issue: var def1 = $.ajax(...); // executing ajax call 1 var def2 = null, def3 = null; $ ...

How can we refine the user information based on the selection of a radio button?

How do I apply a filter to user details when selecting a radio button? Visit Plunker *I need to display only the questions of authenticated users on the list page, so I created a plunker example. If the user is authenticated or an admin, I want to filter ...

Jquery CSS malfunctioning on Post's div element

After retrieving a div using jquery's post method on my page, I am encountering an issue when attempting to apply CSS to the divs. Strangely enough, applying CSS with jquery to divs that are already present on the page works perfectly fine. Javascrip ...