programing

스크롤을 숨기지 않고 비활성화하는 방법

bestcode 2022. 9. 17. 10:48
반응형

스크롤을 숨기지 않고 비활성화하는 방법

라이트박스를 사용하는 동안 부모의 html/body 스크롤바를 비활성화하려고 합니다.여기서 가장 중요한 단어는 disable입니다.나는 그것을 숨기고 싶지 않다overflow: hidden;.

는 ★★★★★★★★★★★★★★★★★★★★★★★」overflow: hidden는 사이트가 점프하여 스크롤이 있던 영역을 차지하게 합니다.

스크롤 바를 표시하면서 비활성화할 수 있는지 알고 싶습니다.

오버레이 아래의 페이지를 상단에 "고정"할 수 있는 경우 오버레이를 열 때

body { position: fixed; overflow-y:scroll }

오른쪽 스크롤바는 표시되지만 내용은 스크롤할 수 없습니다.오버레이를 닫을 때 다음 속성으로 되돌리기만 하면 됩니다.

body { position: static; overflow-y:auto }

스크롤 이벤트를 변경할 필요가 없기 때문에 이 방법을 제안했을 뿐입니다.

갱신하다

될 것 요. 만약 이 '이렇게 하다'가 나온다면요.document.documentElement.scrollTop오픈 할 수 있습니다.top본문 요소의 속성: 이 접근 방식에서는 사용자가 맨 위에 있는지 또는 이미 스크롤했는지에 관계없이 페이지가 제자리에 배치됩니다.

CSS

.noscroll { position: fixed; overflow-y:scroll }

JS

$('body').css('top', -(document.documentElement.scrollTop) + 'px')
         .addClass('noscroll');

승인된 솔루션에 대한 4가지 작은 추가 사항:

  1. IE에서 이중 스크롤 바를 방지하기 위해 본문이 아닌 html에 'noscroll'을 적용
  2. 'noscroll' 클래스를 추가하기 전에 실제로 스크롤 막대가 있는지 확인합니다.그렇지 않으면 사이트도 새로운 스크롤바에 의해 푸시됩니다.
  3. 가능한 스크롤 톱을 유지하여 페이지 전체가 톱으로 돌아가지 않도록 합니다(Fabrizio의 업데이트처럼, 그러나 'noscroll' 클래스를 추가하기 전에 값을 가져와야 합니다).
  4. 일부 브라우저는 http://help.dottoro.com/ljnvjiow.php에 있는 문서와 같은 방법으로 스크롤 탑을 처리하지 않습니다.

대부분의 브라우저에서 작동하는 완전한 솔루션:

CSS

html.noscroll {
    position: fixed; 
    overflow-y: scroll;
    width: 100%;
}

스크롤 사용 안 함

if ($(document).height() > $(window).height()) {
     var scrollTop = ($('html').scrollTop()) ? $('html').scrollTop() : $('body').scrollTop(); // Works for Chrome, Firefox, IE...
     $('html').addClass('noscroll').css('top',-scrollTop);         
}

스크롤을 유효하게 하다

var scrollTop = parseInt($('html').css('top'));
$('html').removeClass('noscroll');
$('html,body').scrollTop(-scrollTop);

Fabrizio와 Dejan은 저를 올바른 방향으로 이끌었고 Brodingo는 더블 스크롤 바에 대한 솔루션을 제공했습니다.

jQuery가 포함된 경우:


무효로 하다

$.fn.disableScroll = function() {
    window.oldScrollPos = $(window).scrollTop();

    $(window).on('scroll.scrolldisabler',function ( event ) {
       $(window).scrollTop( window.oldScrollPos );
       event.preventDefault();
    });
};

가능하게 하다

$.fn.enableScroll = function() {
    $(window).off('scroll.scrolldisabler');
};

사용.

//disable
$("#selector").disableScroll();
//enable
$("#selector").enableScroll();

나는 OP다

는 solutionfcalderan을 할 수 .세부 사항인 사용법을 이 에 둡니다.width: 100%;

이 클래스를 추가합니다.

body.noscroll
{
    position: fixed; 
    overflow-y: scroll;
    width: 100%;
}

저는 Fancyapp을 사용하고 있었습니다.

이건 나한테 정말 잘 먹혔어...

// disable scrolling
$('body').bind('mousewheel touchmove', lockScroll);

// enable scrolling
$('body').unbind('mousewheel touchmove', lockScroll);


// lock window scrolling
function lockScroll(e) {
    e.preventDefault();
}

이 두 줄의 코드를 언제 잠글지 결정하는 대로 감싸기만 하면 됩니다.

예.

$('button').on('click', function() {
     $('body').bind('mousewheel touchmove', lockScroll);
});

스크롤 이벤트를 비활성화할 수는 없지만 마우스휠 및 터치모브와 같이 스크롤로 이어지는 관련 작업을 비활성화할 수 있습니다.

$('body').on('mousewheel touchmove', function(e) {
      e.preventDefault();
});

수 .overflow: hidden동시에 마진을 설정하여 콘텐츠가 점프하지 않도록 합니다.

let marginRightPx = 0;
if(window.getComputedStyle) {
    let bodyStyle = window.getComputedStyle(document.body);
    if(bodyStyle) {
        marginRightPx = parseInt(bodyStyle.marginRight, 10);
    }
}

let scrollbarWidthPx = window.innerWidth - document.body.clientWidth;
Object.assign(document.body.style, {
    overflow: 'hidden',
    marginRight: `${marginRightPx + scrollbarWidthPx}px`
});

그런 다음 비활성화된 스크롤 막대를 페이지에 추가하여 공백을 채울 수 있습니다.

textarea {
  overflow-y: scroll;
  overflow-x: hidden;
  width: 11px;
  outline: none;
  resize: none;
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  border: 0;
}
<textarea></textarea>

저는 Lightbox를 구현하기 위해 이 작업을 수행했습니다.아직까지는 잘 작동하는 것 같아요.

여기 작업 데모가 있습니다.이것은 순수 JavaScript를 사용하여 수행할 수 있는 방법입니다.

const { body, documentElement } = document;
let { scrollTop } = document.documentElement;

function disableScroll() {
  scrollTop = documentElement.scrollTop;
  body.style.top = `-${scrollTop}px`;
  body.classList.add("scroll-disabled");
}

function enableScroll() {
  body.classList.remove("scroll-disabled");
  documentElement.scrollTop = scrollTop;
  body.style.removeProperty("top");
}

CSS는 다음과 같습니다.

.scroll-disabled {
  position: fixed;
  width: 100%;
  overflow-y: scroll;
}

는 용용 we we we we we we we we weposition: fixedbody이 되지 하기 , 는 '스크롤'을 사용합니다.overflow-y스크롤 바를 표시합니다. '아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아,width 때문에position: fixed

할 때 를 지정합니다.body 사용하다top스크롤이 비활성화되면 스크롤 위치를 복원합니다. 이외의 경우는, 「」입니다.body스크롤을 비활성화하거나 활성화하면 계속 맨 위로 이동합니다.

하게 하면, 「」를 합니다.topbody 다른 레이아웃이 이 깨지지 positionstaticbody.

「 」를 사용하고 scroll-behavior: smoothhtml 을 .enableScroll뭇매를 맞다

function enableScroll() {
  body.classList.remove("scroll-disabled");
  // Set "scroll-behavior" to "auto"
  documentElement.style.scrollBehavior = "auto";
  documentElement.scrollTop = scrollTop;
  // Remove "scroll-behavior: auto" after restoring scroll position
  documentElement.style.removeProperty("scroll-behavior");
  body.style.removeProperty("top");
}

로 설정할 .scroll-behavior로로 합니다.auto점프가 안 되게.

이것이 우리가 선택한 해결책입니다.오버레이가 열릴 때 스크롤 위치를 저장하고, 사용자가 페이지를 스크롤하려고 할 때마다 저장된 위치로 다시 스크롤하고, 오버레이가 닫힐 때 수신기를 끄기만 하면 됩니다.

IE에서는 조금 불안정하지만 Firefox/Chrome에서는 매력적으로 작동합니다.

var body = $("body"),
  overlay = $("#overlay"),
  overlayShown = false,
  overlayScrollListener = null,
  overlaySavedScrollTop = 0,
  overlaySavedScrollLeft = 0;

function showOverlay() {
  overlayShown = true;

  // Show overlay
  overlay.addClass("overlay-shown");

  // Save scroll position
  overlaySavedScrollTop = body.scrollTop();
  overlaySavedScrollLeft = body.scrollLeft();

  // Listen for scroll event
  overlayScrollListener = body.scroll(function() {
    // Scroll back to saved position
    body.scrollTop(overlaySavedScrollTop);
    body.scrollLeft(overlaySavedScrollLeft);
  });
}

function hideOverlay() {
  overlayShown = false;

  // Hide overlay
  overlay.removeClass("overlay-shown");

  // Turn scroll listener off
  if (overlayScrollListener) {
    overlayScrollListener.off();
    overlayScrollListener = null;
  }
}

// Click toggles overlay
$(window).click(function() {
  if (!overlayShown) {
    showOverlay();
  } else {
    hideOverlay();
  }
});
/* Required */
html, body { margin: 0; padding: 0; height: 100%; background: #fff; }
html { overflow: hidden; }
body { overflow-y: scroll; }

/* Just for looks */
.spacer { height: 300%; background: orange; background: linear-gradient(#ff0, #f0f); }
.overlay { position: fixed; top: 20px; bottom: 20px; left: 20px; right: 20px; z-index: -1; background: #fff; box-shadow: 0 0 5px rgba(0, 0, 0, .3); overflow: auto; }
.overlay .spacer { background: linear-gradient(#88f, #0ff); }
.overlay-shown { z-index: 1; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

<h1>Top of page</h1>
<p>Click to toggle overlay. (This is only scrollable when overlay is <em>not</em> open.)</p>
<div class="spacer"></div>
<h1>Bottom of page</h1>
<div id="overlay" class="overlay">
  <h1>Top of overlay</h1>
  <p>Click to toggle overlay. (Containing page is no longer scrollable, but this is.)</p>
  <div class="spacer"></div>
  <h1>Bottom of overlay</h1>
</div>

저는 "오버플로우: 숨김" 방식을 고수하고 스크롤바 폭과 동일한 패딩-오른쪽을 추가하는 것을 좋아합니다.

lostsource별로 스크롤 막대 너비 함수를 가져옵니다.

function getScrollbarWidth() {
    var outer = document.createElement("div");
    outer.style.visibility = "hidden";
    outer.style.width = "100px";
    outer.style.msOverflowStyle = "scrollbar"; // needed for WinJS apps

    document.body.appendChild(outer);

    var widthNoScroll = outer.offsetWidth;
    // force scrollbars
    outer.style.overflow = "scroll";

    // add innerdiv
    var inner = document.createElement("div");
    inner.style.width = "100%";
    outer.appendChild(inner);        

    var widthWithScroll = inner.offsetWidth;

    // remove divs
    outer.parentNode.removeChild(outer);

    return widthNoScroll - widthWithScroll;
}

오버레이를 표시할 때 html에 "noscroll" 클래스를 추가하고 본문에 padding-right를 추가합니다.

$(html).addClass("noscroll");
$(body).css("paddingRight", getScrollbarWidth() + "px");

숨길 때는 클래스와 패딩을 제거합니다.

$(html).removeClass("noscroll");
$(body).css("paddingRight", 0);

noscroll 스타일은 다음과 같습니다.

.noscroll { overflow: hidden; }

position:fixed 요소가 있는 경우 해당 요소에도 패딩을 추가해야 합니다.

본문 스크롤을 삭제할 때 고정 모달에서 콘텐츠 점프를 제거하는 또 다른 해결책은 페이지 폭을 정규화하는 것입니다.

body {width: 100vw; overflow-x: hidden;}

그런 다음 모달(modal)이 열려 있을 때 고정 위치 또는 overflow: hidden(오버플로우: 숨김)그러나 가로 스크롤 바는 숨겨집니다.일반적으로 응답성이 뛰어난 웹 사이트에서는 필요하지 않습니다.

오버플로우를 유지할 수 있습니다.숨겨지지만 스크롤 위치는 수동으로 관리할 수 있습니다.

실제 스크롤 위치의 유지 트레이스를 표시하기 전에:

var scroll = [$(document).scrollTop(),$(document).scrollLeft()];
//show your lightbox and then reapply scroll position
$(document).scrollTop(scroll[0]).scrollLeft(scroll[1]);

그건 작동할 거야.

<div id="lightbox"> is is is is is is is the is 。<body>따라서 라이트박스를 스크롤하면 본문도 스크롤할 수 있습니다.은 '연장'을 것입니다.<body>을 다른 것 div 및 합니다.div으로 구성하다.overflow: auto.

html {
  height: 100%
}
body {
  margin: 0;
  height: 100%
}
#content {
  height: 100%;
  overflow: auto;
}
#lightbox {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
}
<html>
  <body>
    <div id="content">much content</div>
    <div id="lightbox">lightbox<div>
  </body>
</html>

라이트박스) 위로 .body본체가 화면 높이의 100%를 넘지 않기 때문에)도 효과가 없습니다.

저도 같은 문제가 있었습니다.왼쪽 메뉴에서는 스크롤을 할 수 없습니다.높이가 100vh로 설정되자마자 스크롤바는 사라지고 콘텐츠는 오른쪽으로 흔들렸다.

따라서 스크롤 막대를 활성화해도 괜찮다면(하지만 창을 풀 하이트로 설정하여 실제로 스크롤하지 않도록 함) 스크롤 막대가 계속 표시되는 다른 방법이 있습니다.

body {
    height: 100vh;
    overflow: hidden;
    margin: 0 0 1px;
}

modal/lightbox javascript 기반 시스템은 html 태그 또는 body 태그에 modal/lightbox를 표시할 때 오버플로우를 사용합니다.

lightbox가 표시되면 js는 html 또는 본문 태그에 숨겨진 오버플로를 푸시합니다.라이트 박스가 숨겨져 있는 경우는, 숨겨진 다른 것을 삭제해, html 또는 본문 태그의 오버플로우 자동을 푸시 합니다.

Mac에서 작업하는 개발자는 스크롤바의 문제를 인식하지 않습니다.

스크롤 막대를 제거할 때 컨텐츠가 미끄러지지 않도록 설정되지 않은 상태로 숨김을 바꿉니다.

라이트 박스 열기/표시:

<html style="overflow: unset;"></html>

라이트 박스 닫기/숨기기:

<html style="overflow: auto;"></html>

오버레이 아래의 페이지를 상단에 "고정"할 수 있는 경우 오버레이를 열 때

.disableScroll { position: fixed; overflow-y:scroll }

이 클래스를 스크롤 가능한 본문에 제공해도 오른쪽 스크롤 막대는 표시되지만 내용은 스크롤할 수 없습니다.

페이지 위치를 유지하려면 jquery에서 이 작업을 수행합니다.

$('body').css('top', - ($(window).scrollTop()) + 'px').addClass('disableScroll');

오버레이를 닫을 때 다음 속성으로 되돌리기만 하면 됩니다.

var top = $('body').position().top;
$('body').removeClass('disableScroll').css('top', 0).scrollTop(Math.abs(top));

스크롤 이벤트를 변경할 필요가 없기 때문에 이 방법을 제안했을 뿐입니다.

이렇게 하면 스크롤 위치를 저장하고 스크롤을 활성화하면 뷰포트가 위로 점프하지 않게 됩니다.

CSS

.no-scroll{
  position: fixed; 
  width:100%;
  min-height:100vh;
  top:0;
  left:0;
  overflow-y:scroll!important;
}

JS

var scrollTopPostion = 0;

function scroll_pause(){
  scrollTopPostion = $(window).scrollTop();
  $("body").addClass("no-scroll").css({"top":-1*scrollTopPostion+"px"});
}

function scroll_resume(){
  $("body").removeClass("no-scroll").removeAttr("style");
  $(window).scrollTop(scrollTopPostion);
}

이제 함수를 호출하기만 하면 됩니다.

$(document).on("click","#DISABLEelementID",function(){
   scroll_pause();
});

$(document).on("click","#ENABLEelementID",function(){
   scroll_resume();
});

position: fixed;이치노이 스타일을 적용하면 페이지가 맨 위로 이동합니다.Angular에는 Angular's Material Dialog에 솔루션이 .html★★★★★★ 。

아래는 수직 스크롤 전용 개정 알고리즘입니다.왼쪽 스크롤 차단도 동일한 방법으로 수행됩니다.

// This class applies the following styles:
// position: fixed;
// overflow-y: scroll;
// width: 100%;
const NO_SCROLL_CLASS = "bp-no-scroll";

const coerceCssPixelValue = value => {
  if (value == null) {
    return "";
  }

  return typeof value === "string" ? value : `${value}px`;
};

export const blockScroll = () => {
  const html = document.documentElement;
  const documentRect = html.getBoundingClientRect();
  const { body } = document;

  // Cache the current scroll position to be restored later.
  const cachedScrollPosition =
    -documentRect.top || body.scrollTop || window.scrollY || document.scrollTop || 0;

  // Cache the current inline `top` value in case the user has set it.
  const cachedHTMLTop = html.style.top || "";

  // Using `html` instead of `body`, because `body` may have a user agent margin,
  // whereas `html` is guaranteed not to have one.
  html.style.top = coerceCssPixelValue(-cachedScrollPosition);

  // Set the magic class.
  html.classList.add(NO_SCROLL_CLASS);

  // Return a function to remove the scroll block.
  return () => {
    const htmlStyle = html.style;
    const bodyStyle = body.style;

    // We will need to seamlessly restore the original scroll position using
    // `window.scroll`. To do that we will change the scroll behavior to `auto`.
    // Here we cache the current scroll behavior to restore it later.
    const previousHtmlScrollBehavior = htmlStyle.scrollBehavior || "";
    const previousBodyScrollBehavior = bodyStyle.scrollBehavior || "";

    // Restore the original inline `top` value.
    htmlStyle.top = cachedHTMLTop;

    // Remove the magic class.
    html.classList.remove(NO_SCROLL_CLASS);

    // Disable user-defined smooth scrolling temporarily while we restore the scroll position.
    htmlStyle.scrollBehavior = bodyStyle.scrollBehavior = "auto";

    // Restore the original scroll position.
    window.scroll({
      top: cachedScrollPosition.top
    });

    // Restore the original scroll behavior.
    htmlStyle.scrollBehavior = previousHtmlScrollBehavior;
    bodyStyle.scrollBehavior = previousBodyScrollBehavior;
  };
};

논리는 매우 간단하며 특정 엣지 케이스에 신경 쓰지 않으면 훨씬 더 단순해질 수 있습니다.예를 들어, 다음과 같이 사용하고 있습니다.

export const blockScroll = () => {
  const html = document.documentElement;
  const documentRect = html.getBoundingClientRect();
  const { body } = document;
  const screenHeight = window.innerHeight;

  // Only do the magic if document is scrollable
  if (documentRect.height > screenHeight) {
    const cachedScrollPosition =
      -documentRect.top || body.scrollTop || window.scrollY || document.scrollTop || 0;

    html.style.top = coerceCssPixelValue(-cachedScrollPosition);

    html.classList.add(NO_SCROLL_CLASS);

    return () => {
      html.classList.remove(NO_SCROLL_CLASS);

      window.scroll({
        top: cachedScrollPosition,
        behavior: "auto"
      });
    };
  }
};

JS에서 이 문제를 해결하는 기능을 하나 만들었습니다.이 원칙은 저에게 큰 장점인 쉽게 확장하고 맞춤형으로 만들 수 있습니다.

이 js DOM API 함수를 사용합니다.

const handleWheelScroll = (element) => (event) => {
  if (!element) {
    throw Error("Element for scroll was not found");
  }
  const { deltaY } = event;
  const { clientHeight, scrollTop, scrollHeight } = element;
  if (deltaY < 0) {
    if (-deltaY > scrollTop) {
      element.scrollBy({
        top: -scrollTop,
        behavior: "smooth",
      });
      event.stopPropagation();
      event.preventDefault();
    }
    return;
  }

  if (deltaY > scrollHeight - clientHeight - scrollTop) {
    element.scrollBy({
      top: scrollHeight - clientHeight - scrollTop,
      behavior: "smooth",
    });
    event.stopPropagation();
    event.preventDefault();
    return;
  }
};

즉, 이 함수는 스크롤이 지정된 요소(스크롤인하려는 요소)가 아닌 다른 요소를 스크롤할 경우 이벤트 전파 및 기본 동작을 중지합니다.

다음으로 다음과 같이 후크업과 후크아웃을 할 수 있습니다.

const wheelEventHandler = handleWheelScroll(elementToScrollIn);

window.addEventListener("wheel", wheelEventHandler, {
    passive: false,
});

window.removeEventListener("wheel", wheelEventHandler);

이 함수는 상위 함수이므로 지정된 인스턴스에 대한 참조를 유지해야 합니다.

나는 훅을 걸고addEventListener 를 .removeEventListenerjQuery에서 마우스 탈퇴 이벤트를 표시하지만 원하는 대로 사용할 수 있습니다.

YouTube 웹사이트에서 정확히 이렇게 하고 있다는 것을 알게 되었습니다. 저는 이 사람들이 '어느 정도'를 사용하고 을 알 수 .@polymer/iron-overlay-behavior다행히 웹 컴포넌트/폴리머 이외에서는 눈에 띄지 않게 사용할 수 있습니다.

import {
    pushScrollLock,
    removeScrollLock,
} from '@polymer/iron-overlay-behavior/iron-scroll-manager';

// lock scroll everywhere except scrollElement
pushScrollLock(scrollElement);

// restore scrolling
removeScrollLock(scrollElement);
  • 선택한 요소를 스크롤할 수 있습니다.
  • 스타일링에 전혀 지장을 주지 않는다.
  • YouTube 웹사이트에서 배틀테스트 중

그것은 성숙한 해결책으로 내가 찾을 수 있는 최선의 해결책으로 보인다. ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★iron-scroll-manager.

건배.

에는 다른 .body의 »position로로 합니다.fixed다른 많은 문제를 일으켰기 때문에, 나는 그것을 해킹하는 방법으로 했다.

const scrollbarWidth = window.innerWidth - document.documentElement.clientWidth;

// on opening modal
document.body.style.overflow = "hidden"
document.body.style.paddingRight = `${scrollbarWidth}px`

// on closing modal
document.body.style.overflow = "unset",
document.body.style.paddingRight = "0px"

이 아이디어에서는padding-right브라우저의 스크롤바와 같은 너비로 가짜 스크롤바를 모방하여 콘텐츠 이동을 방지합니다.

거칠지만 작동 방법은 스크롤을 강제로 위로 되돌리는 것입니다. 따라서 스크롤은 효과적으로 비활성화됩니다.

var _stopScroll = false;
window.onload = function(event) {
    document.onscroll = function(ev) {
        if (_stopScroll) {
            document.body.scrollTop = "0px";
        }
    }
};

라이트박스를 열 때는 깃발을 올리고 닫을 때는 깃발을 내립니다.

라이브 테스트 케이스

Javascript를 사용하여 실행할 수 있습니다.

// Classic JS
window.onscroll = function(ev) {
  ev.preventDefault();
}

// jQuery
$(window).scroll(function(ev) {
  ev.preventDefault();
}

라이트 박스가 닫히면 비활성화합니다.

그러나 라이트 박스에 스크롤 막대가 있는 경우 열려 있는 동안에는 스크롤할 수 없습니다.그 이유는windowbody ★★★★★★★★★★★★★★★★★」#lightbox따라서 다음과 같은 아키텍처를 사용해야 합니다.

<body>
  <div id="global"></div>
  <div id="lightbox"></div>
</body>

에 '이렇게'를 붙입니다.onscroll의 일#global.

언급URL : https://stackoverflow.com/questions/8701754/how-to-disable-scroll-without-hiding-it

반응형