Make sure the webpage remains fixed in place when the modal is active, but ensure that the scrollbar is still visible

My goal is to prevent page scrolling when a modal is opened without causing the scrollbar to disappear or the content to shift abruptly. I want to freeze the scroll position I'm currently at, keep the scrollbar visible, and ensure that features like 'hide on scroll' on the header do not trigger under the modal's dark underlay. How can I achieve this without any unwanted side effects?

I've experimented with different methods, including applying the following styles directly to the <body>:

position: fixed;
height: 100%;
width: 100%;
top: 0;
left: 0;
overflow-y: scroll;

While this approach prevents scrolling and keeps the scrollbar visible, using position: fixed; causes the viewport to jump to the top when the modal is opened, which is not desirable.

In my Vue project, the template in my App.vue file is structured as follows:

<template>
    <div>
        <AppModal></AppModal>
        <AppHeader></AppHeader>
        <AppMain></AppMain>
        <AppFooter></AppFooter>
    </div>
</template>

I am searching for a concise solution that does not require using JavaScript.

Answer №1

To replicate the issue of content shifting, it is necessary to have a fixed header, which was not specified in your initial question. If the body has an overflow-y:hidden property, the scrollbar will disappear, leading to the content shifting in the header.

The solution involves placing the header inside a container with a conflicting overflow-y:scroll property that will counteract the disappearance of the scrollbar in the body.

btn.onclick = btn3.onclick = function(ev) {
  document.body.classList.add("fixed")
}

btn2.onclick = function(ev) {
  document.body.classList.remove("fixed")
}


// hide on scroll
let lastScrollY = window.scrollY;
var header_container = document.querySelector(".header-container");
const handleScroll = () => {
  if (lastScrollY < window.scrollY && window.scrollY >= 50) {
    header_container.classList.add("hidden")
  } else {
    header_container.classList.remove("hidden")
  }
  lastScrollY = window.scrollY;
};

window.addEventListener('scroll', handleScroll);
body {
  overflow-y: scroll;
  margin: 0;
}

body.fixed {
  overflow-y: hidden;
}

.header-container {
  top: 0;
  position: sticky;
  width: 100%;
  transform: translateY(0);
  transition: transform 0.3s;
  
  /* meh - not supported in opera? */
  scrollbar-color: rgba(255, 255, 0, 0.75) rgba(255, 255, 0, 0.75);
}

.header-container.hidden {
  transform: translateY(-100%);
}

body.fixed .header-container {
  overflow-y: scroll;
}

body .modal {
  display: none;
}

body.fixed .modal {
  display: block;
}

.header {
  width: 100%;
  text-align: center;
  padding: 25px 0;
  top: 0;
  background: yellow;
  box-shadow: 0 0 10px purple;
}

.modal {
  padding: 20px;
  text-align: center;
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(0, 0, 0, 0.75);
  z-index: 1;
}
<body>


  <div class="header-container">
    <div class="header">
      header, <button id="btn3">open modal</button>

    </div>
  </div>

  <h1>hello world, please scroll and/or open modal</h1>
  <p>sdflkjsdfl kjsf</p>
  <h1>hello world</h1>
  <p>sdflkjsdfl kjsf</p>
  <h1>hello world</h1>
  <p>sdflkjsdfl kjsf</p>

  <button id="btn">open modal</button>


  <h1>hello world</h1>
  <p>sdflkjsdfl kjsf</p>
  <h1>hello world</h1>
  <p>sdflkjsdfl kjsf</p>
  <h1>hello world</h1>
  <p>sdflkjsdfl kjsf</p>

  <div class="modal">
    <h2>hello i am modal</h2>
    <button id="btn2">close</button>
  </div>

</body>

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

Tips for using JavaScript to magnify a specific point on a webpage

As I work on my web project, I am trying to achieve the functionality of zooming in a div element centered around the mouse position while using the mouse wheel. I came across a helpful answer by @Tatarize on Zoom in on a point (using scale and translate), ...

Imitate the act of pasting content into a Textarea using JavaScript

When data is copied from the clipboard and pasted into an html textarea, there is some interesting parsing that occurs to maintain the formatting, especially with newlines. For instance, suppose I have the following code on a page that I copy (highlightin ...

Acquire HTML using Java - certain characters are not retrieved accurately

Currently, I am facing an issue with my Java code when trying to fetch HTML from Turkish webpages. It seems that my Java code is struggling to recognize certain Turkish characters. Below is the Java code snippet I am using: import java.io.BufferedInputStr ...

Optimal strategies for designing navigation bars on contemporary websites

Struggling to find a solid answer for this dilemma. I have multiple html pages and a single navigation bar that I want to include on all pages for consistency. The idea of duplicating the html code for the navigation bar goes against everything I've l ...

"Within the node.js framework, the search/query section of the URL appears

I am currently working on a website (client + server) that both operate from the same machine. Despite not encountering any issues in Chrome's developer tools, I am struggling to identify the source of a problem. My dilemma is with trying to POST a s ...

Navigating to the bottom of a specific element by scrolling

I am currently working on enhancing a module within the application I'm developing. The goal is to automatically scroll the browser window to the bottom of an element when said element's height exceeds the height of the window. The functionality ...

Navigating through content using jQuery scroll bar

Could someone please assist me with scrolling the content on my website? For example, I have a link like this: <a href="#">content3</a> When a user clicks that link, I would like the content to scroll to div content3. I am looking for guidan ...

Reopen a Kendo UI dialog

Currently, I am utilizing Kendo UI, and my goal is to display a modal dialog when a button is clicked. The issue I am facing is that it works perfectly the first time around. However, upon closing the dialog and attempting to reopen it by clicking the butt ...

Update the content of a div and refresh it when a key on the keyboard is pressed

I need to hide the images in a div when I press a key on the keyboard. How can I achieve this? <div> <span role="checkbox" aria-checked="true" tabindex="0"> <img src="checked.gif" role="presentation" alt="" /> ...

Achieving functionality with dropdown menus in jQuery

I am facing an issue with a dropdown menu that works perfectly in jsFiddle during testing, but does not function as expected when I run it on my testing server. jsFiddle: http://jsfiddle.net/cyberjo50/39bu8/2/ HTML <!doctype html> <html> < ...

CSS loop to centrally align divs

I am facing an issue where I want to center the divs in a panel. Each div is generated within a for-each-loop inside the panel. However, the problem arises when they are displayed as block elements: https://i.sstatic.net/RvnlX.jpg When I try floating them ...

How can I emphasize the React Material UI TextField "Cell" within a React Material UI Table?

Currently, I am working on a project using React Material UI along with TypeScript. In one part of the application, there is a Material UI Table that includes a column of Material TextFields in each row. The goal is to highlight the entire table cell when ...

"Customize the number of items displayed per page with Bootstrap Vue's perPage

I am currently working on a Vue project which you can view on codesandbox and utilizing bootstrap-vue. Within the project, there are multiple columns containing cards along with pagination: <template> <b-container> <b-row :cu ...

Guide to implementing Swiper.js (version 8+) within Nuxt.js (2.15.8)

Initially, I attempted to implement the code shown on the official Swiper.js website for Vue 3 demo: <template> <swiper :effect="'coverflow'" :grabCursor="true" :centeredSlides="true" :slidesPerView="'auto' ...

Ways to prevent animations from displaying solely in IE

Is there a way to remove a keyframe animation if the browser is IE, while keeping it for Chrome, Safari, and FireFox? The animation I am referring to is defined as follows: // Animations @-webkit-keyframes fadeIn { from { opacity:0; } to { opacity:1; } } ...

Leveraging scrapy for pinpointing the accurate information within tables

I am facing a challenge with extracting text from a website that features multiple tables. My goal is to create a layout where the content spans across multiple pages, but the issue lies in the unpredictable nature of the xpath for these tables. The xpath ...

The VueJS Chosen directive fails to refresh when new options are selected

Struggling to populate my jQuery Chosen dropdown field with AJAX data using VueJS. Unfortunately, when trying to update the values, the Chosen dropdown does not reflect the changes. I've experimented with different approaches, including manually trig ...

Deactivating the drag feature when setting the duration of a new event in FullCalendar

Hello there! I've integrated full calendar into my Angular project and I'm facing a challenge. I want to restrict users from defining the duration of an event by holding click on an empty schedule in the weekly calendar, where each date interval ...

A step-by-step guide on creating a live crud application with vuex and socketio

I am struggling to achieve a realtime crud operation using vuex, node, express, and socketio with the current syntax provided. Here is the code snippet: Server index.js const server = app.listen('3000',() => { console.log('<--- ...

How does margin:auto differ from using justify-content and align-items center together?

If you want to center both horizontally and vertically at the same time, there are two easy methods available: Option One .outer { display:flex; } .inner { margin:auto; } Option Two .outer { display: flex; justify-content: center; align-items ...