在进行网页布局的时候会碰到需要进行HTML精确定位的情况,需要要将某一documentElement定位到页面的某一位置。
比如说传统的文档流是从上到下渲染网页的,当中间某一个元素不存在了(使用.hide()等),后面的元素就要补这个缺,这样的话交互就会很差,因为一旦后面的元素补了这个缺,它在页面显示的内容很可能被浏览器截成两段,用户还未浏览到的内容直接就跑到了浏览器不可见的区域了,这时候如果想让后面的这个元素还在页面视口Client区域(浏览器的可见区域)的原来位置要如何做呢?这个时候单单针对父级进行定位就不行了。
上一下效果图:
页面没有任何点击时候的状态
点击一次,展开/收缩详细说明夜,背景箭头改变
若第一个没有收缩,当点击下面的导航,第一个自动收起,且点击的导航在视口的位置不变(如果是第二个或者其他距离页面顶端距离过大的导航,比如距离视口200px,而第一个导航和顶部的header一共高度才100px,则其会定位(滚动)到所有导航收起后的位置距离顶部100px)
如果是点击后面的导航,则其在页面视口的位置直观上不变:
今天这个问题算是碰到了。好了,不废话,简单如题介绍一下几个属性(JS 测试有效)。
- scrollLeft/Top: 获取对象左/上边界和页面可见区域最左/上端之间的距离
- scrollWidth/Height: 获取对象的滚动宽度/高度
- offsetLeft/Top: 获取对象相对于页面(整个html文档)左/上侧的距离
- offsetHeight/Width: 获取对象占位高度/宽度(包括margin和border)
- clientHeight/Width: 对象content内容的高度/宽度(相当于height和width属性)
再有一个clientTop似乎才比较完美,事实上确实存在clientTop属性,但测试了好几次,无论元素处于何种位置,clientTop值始终为0, 虽然不能直接得到这个值,但可以通过计算得到:
clientTop = offsetTop - scrollTop;
知道这个就成功了百分之九十九。
但是这些属性有的在jquery中无法获取,所以需要使用jquery中的属性名。代码如下:
$(document).ready(function(e) {
$(function(){
new FastClick(document.body); //手机端解决click事件延迟300ms
});
function init() {
$(".toggle").parent().find(".toggle").removeClass("open");
$(".toggle").parent().find(".toggle").addClass("close");
$(".toggle").attr("data-flag", "close");
}
$(".toggle").on("click", function() {
var that = $(this),
flag = that.attr("data-flag")
offsetTop = that.offset().top,
scrollTop = $("html body").scrollTop(),
clientTop = offsetTop - scrollTop; //以下是测试数据
console.log("offsetTop: ", offsetTop); //280 获取元素的距离页面顶端的距离
console.log("scrollTop: ", scrollTop); //0 获取滚动条距离页面顶端的距离
console.log("clientTop", clientTop); //280 注: 这个是重点获取元素距离浏览器可见区域顶端的距离
$(".toggle").next().hide();
init();
if(flag == "close") {
var topVal = that.offset().top;
console.log("newoffset", topVal); //280 获取位置改变后的新offset值
that.removeClass("close");
that.addClass("open");
that.attr("data-flag", "open");
that.next().show();
var val = topVal - clientTop; //0 若保持位置不变,滚动条滚动的距离
console.log("newscroll: ", val);
$("html body").scrollTop(val); // 页面滚动条滚动到指定位置
}
});
});