頁面出現滾動條時,body裏面的內容不能自動居中?
彈窗後允許頁面滾動
這種方式通常使用 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裏面的內容不能自動居中?