1. 程式人生 > >頁面出現滾動條時,body裏面的內容不能自動居中?

頁面出現滾動條時,body裏面的內容不能自動居中?

這樣的 pos fixed oba view review dto 轉載 pup

彈窗後允許頁面滾動

這種方式通常使用 position: absolute; ,可以看看我做的這個 Demo。主要用來應對彈窗內容很大很多的情況,超過了屏幕的寬高需要產生滾動條來方便瀏覽者查看。有一些圖片彈窗插件使用這種方式,使用 JS 動態計算彈窗內容塊的位置,這樣即便是內容塊很大,也不會造成信息缺失。

但是居中往往需要 JS 配合或者進行位置、尺寸處理,會稍微麻煩一些。

彈窗後不允許頁面滾動

你可以通過為內容塊設置 position: fixed; 使其雖然滾動了,但內容塊仍然居中顯示,給人一種沒有滾動的感覺,還是剛剛的 Demo 註釋掉然後修改一下就可以看到。

也可以為 html、body

標簽設置 overflow-y: hidden; 屬性,使其滾動條消失,無法滾動。

通常來說,一般都要使用 hidden 來隱藏滾動條禁止滾動,然後使用 absolute 或者 fixed 就看你自己的需求來選擇。但是,對 html 或 body 設置 overflow-y: hidden; 之後,由於滾動條沒有了,寬度變寬,頁面內容會整體偏移一點,雖然只是一點,但是很明顯。這簡直太影響用戶體驗了!!

去掉滾動條但是避免頁面內容偏移

知乎上前段時間也提到了這個問題:如何禁止瀏覽器滾動條滾動,但是又不讓它消失?。其中比較簡單方便的就是 TQ 學長的回答,但是實際測試並不完美,因為 chrome 瀏覽器的滾動條是 15px 像素寬,而 firefox 瀏覽器是 17px 像素。如果統一設置成 17px 的話,chrome 等瀏覽器中顯然還會偏移 2px ,雖然盡力完善了,但還是有點小偏移,受不了。

既然不同瀏覽器裏面滾動條寬度不同,那可否先用 JS 檢測操作系統和瀏覽器,然後再根據判斷的瀏覽器等設置不同的偏移量?大體思路是對的,但是方法是錯的。檢測操作系統和瀏覽器,要判斷的情況太多,代碼太過於復雜。於是這個問題就暫時放在這裏了。

偶然刷 twitter 的時候,觸發彈窗效果的時候,偶然看到了他們也是采用這種方式隱藏滾動條並且保證不會偏移,經過測試各個瀏覽器中效果完美。於是分析了一下他們的代碼,下面是他們的函數:

function ScrollbarWidth() {
    this.calculateScrollbarWidth = function() {
        if ($("#scrollbar-width").length > 0) return;
        var a = $(‘<div class="modal-measure-scrollbar"/>‘).prependTo($("body")),
        b = $(‘<div class="inner"/>‘).appendTo(a),
        c = a.width() - b.width();
        a.remove(),
        $("head").append(‘<style id="scrollbar-width">        .compensate-for-scrollbar,        .modal-enabled,        .modal-enabled .global-nav-inner,        .profile-editing,        .profile-editing .global-nav-inner,        .overlay-enabled,        .overlay-enabled .global-nav-inner,        .grid-enabled,        .grid-enabled .global-nav-inner,        .gallery-enabled,        .gallery-enabled .global-nav-inner {          margin-right: ‘ + c + "px      }      </style>")
    }
}

精簡一下主要代碼就是

var a = $(‘<div class="modal-measure-scrollbar"/>‘).prependTo($("body")),
b = $(‘<div class="inner"/>‘).appendTo(a),
c = a.width() - b.width();
a.remove();
$("head").append(‘<style id="scrollbar-width"> .compensate-for-scrollbar{ margin-right:‘ + c + ‘px } </style>‘);

大體意思就是新建了一個包裹的結構,然後兩個寬度相減得到滾動條的寬度,然後輸出到 head 中。當有彈窗發生之後,就為 html 標簽賦予相應的類來 margin-right 一下,避免滾動條消失引起的內容偏移。

Great!這才是正解,顯然這兩個結構需要賦予一定的 CSS,目的要使 .modal-measure-scrollbar 產生滾動條,而 .inner 是不包括滾動條的全寬,他們的差值正好就是滾動條的寬度!

twitter 中對它們應用的樣式如下:

.modal-measure-scrollbar{
    position: absolute;
    height: 100px;
    width: 100px;
    top: -300px;
    left: -300px;
    overflow: scroll;
    z-index: 1000;
    overflow-y: scroll;
}
.modal-measure-scrollbar .inner{
    height: 200px;
}

不需要解釋了吧。

後來又測試了 fancybox 插件,它的方法更加簡單通用,具體代碼如下:

w1 = $(window).width();
H.addClass(‘fancybox-lock-test‘);
w2 = $(window).width();
H.removeClass(‘fancybox-lock-test‘);
$("<style type=‘text/css‘>.fancybox-margin{margin-right:" + (w2 - w1) + "px;}</style>").appendTo("head");

其中 H 變量是 $(‘html‘) ,大意就是先檢測現有寬度,然後再為 html 增加一個類,再檢測,然後復原去掉類得到滾動條寬度。大體想一下也可以知道 .fancybox-lock-test 類的代碼是這樣的:

.fancybox-lock-test {
    overflow-y: hidden !important;
}

這種方法更加巧妙簡單,不需要創建臨時的 DOM 結構,所以強烈推薦在項目中使用這種方式判斷。

此外,還有第三種方法,是來自 QQ 空間的。QQ 空間的相冊之類的,也是采用彈窗的,查看了一下他們的實現方式,就是使用的固定的 17px 的偏移值,在其他瀏覽器中也是 17px 像素。但是使用中很難看到內容的偏移,原因是背景遮罩層太黑了,透明度不高,所以很多細節就忽略掉了。如果你的背景遮罩不是很透明,顯然也就不需要處理這了~

轉載:http://yujiangshui.com/review-how-to-make-popup-mask-effect/

頁面出現滾動條時,body裏面的內容不能自動居中?