offset client scroll三大家族介绍及案例应用

本文详细介绍了offset系列、client系列和scroll系列属性在JavaScript和CSS3中的应用,包括获取元素位置、鼠标坐标、拖动效果、模态框、flexible布局解析、页面加载事件以及复杂布局实现,通过实例展示了这些属性在前端开发中的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

01-offset系列属性

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>offset系列属性</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
        
        .father {
            position: relative;
            width: 200px;
            height: 200px;
            background-color: pink;
            margin: 100px;
        }
        
        .son {
            width: 100px;
            height: 100px;
            background-color: purple;
            margin-left: 45px;
        }
        
        .w {
            /* width: 200px; */
            height: 200px;
            background-color: skyblue;
            margin: 0 auto 200px;
            padding: 10px;
            border: 15px solid red;
        }
    </style>
</head>

<body>
    <div class="father">
        <div class="son"></div>
    </div>
    <div class="w"></div>
    <script>
        //  offset系列
        var father = document.querySelector('.father');
        var son = document.querySelector('.son');

        // 1.可以得到元素的偏移 位置 返回不带单位的数值
        console.log(father.offsetTop); //100
        console.log(father.offsetLeft); //100
        // 它以带有定位的父亲为准,如果没有父亲或者父亲没有定位,它以body为准
        console.log(son.offsetLeft); //父亲没有定位是145 父亲加了定位后变为45

        // 2.可以得到元素的大小 高度和宽度 是包含padding和border的,不包含maigin
        var w = document.querySelector('.w');
        console.log(w.offsetWidth); //200  padding会撑大盒子,加了10px的padding后,宽度和高度都变为220
        console.log(w.offsetHeight); //200   border会撑大盒子,加了15px的padding后,宽度和高度由原来的220变为250

        // 3.可以得到带有定位的父级,否则返回的是body
        console.log(son.offsetParent); // 返回带有定位的父级 
        console.log(son.parentNode); //返回父亲 是最近一级的父亲 亲爸爸 不管有没有定位
    </script>
</body>

</html>

02-offset与style区别

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>offset与style区别</title>
    <style>
        .box {
            width: 200px;
            height: 200px;
            background-color: pink;
            padding: 10px;
        }
    </style>
</head>

<body>
    <div class="box" style="width: 200px;"></div>
    <script>
        // offset与style区别
        var box = document.querySelector('.box');
        // 1.style只能得到行内样式表的样式值 offset可以得到任意样式表中的的样式值
        console.log(box.offsetWidth);
        console.log(box.style.width);
        // 2.offset系列获得的数值是没有单位的 style.width获得是带有单位的字符串
        // 3.offsetWidth包含padding,border和width style.width获得不包含padding和border的值
        // 4.offsetWidth等属性是只读属性,只能获取不能赋值改变 style.width是可读写属性,可以获取也可以赋值更改值的大小
        // 5.所以,如果我们想要获取元素大小,用offset更合适 想要给元素更改值,则需要用style.width
        // box.offsetWidth='300px';无效
        box.style.width = '300px';
    </script>
</body>

</html>

03-获取鼠标在盒子内的坐标

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>获得鼠标在盒子内的坐标</title>
    <style>
        .box {
            width: 300px;
            height: 300px;
            background-color: pink;
            margin: 200px;
        }
    </style>
</head>

<body>
    <div class="box"></div>
    <script>
        //1.我们在盒子内点击,想要获得鼠标距离盒子左右的距离
        //2.首先获得鼠标在页面中的坐标(e.pageX, e.pageY)
        //3.其次得到盒子在页面中的距离(box.offsetleft, box.offsetTop)
        //4.用鼠标距离页面的坐标减去盒子在页面中的坐标,得到鼠标在盒子内的坐标
        //5.如果想要移动一下鼠标,就要获取最新的坐标,使用鼠标事件mousemove
        var box = document.querySelector('.box');
        box.addEventListener('mousemove', function(e) {
            console.log(e.pageX);
            console.log(e.pageY);
            console.log(box.offsetLeft);
            console.log(box.offsetTop);
            var x = e.pageX - this.offsetLeft; //鼠标在盒子内的x坐标
            var y = e.pageY - this.offsetTop; //鼠标在盒子内的y坐标
            this.innerHTML = 'x坐标是' + x + ' y坐标是' + y;
            console.log(x);
            console.log(y);

        })
    </script>
</body>

</html>

效果展示

在这里插入图片描述

04-拖动模态框案例

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>拖动模态框案例</title>
    <style>
        .login-header {
            width: 100%;
            text-align: center;
            height: 30px;
            font-size: 24px;
            line-height: 30px;
        }
        
        ul,
        li,
        ol,
        dl,
        dt,
        dd,
        div,
        p,
        span,
        h1,
        h2,
        h3,
        h4,
        h5,
        h6,
        a {
            padding: 0px;
            margin: 0px;
        }
        
        .login {
            display: none;
            width: 512px;
            height: 280px;
            position: fixed;
            border: #ebebeb solid 1px;
            left: 50%;
            top: 50%;
            background: #ffffff;
            box-shadow: 0px 0px 20px #ddd;
            z-index: 9999;
            transform: translate(-50%, -50%);
        }
        
        .login-title {
            width: 100%;
            margin: 10px 0px 0px 0px;
            text-align: center;
            line-height: 40px;
            height: 40px;
            font-size: 18px;
            position: relative;
            cursor: move;
        }
        
        .login-input-content {
            margin-top: 20px;
        }
        
        .login-button {
            width: 50%;
            margin: 30px auto 0px auto;
            line-height: 40px;
            font-size: 14px;
            border: #ebebeb 1px solid;
            text-align: center;
        }
        
        .login-bg {
            display: none;
            width: 100%;
            height: 100%;
            position: fixed;
            top: 0px;
            left: 0px;
            background: rgba(0, 0, 0, .3);
        }
        
        a {
            text-decoration: none;
            color: #000000;
        }
        
        .login-button a {
            display: block;
        }
        
        .login-input input.list-input {
            float: left;
            line-height: 35px;
            height: 35px;
            width: 350px;
            border: #ebebeb 1px solid;
            text-indent: 5px;
        }
        
        .login-input {
            overflow: hidden;
            margin: 0px 0px 20px 0px;
        }
        
        .login-input label {
            float: left;
            width: 90px;
            padding-right: 10px;
            text-align: right;
            line-height: 35px;
            height: 35px;
            font-size: 14px;
        }
        
        .login-title span {
            position: absolute;
            font-size: 12px;
            right: -20px;
            top: -30px;
            background: #ffffff;
            border: #ebebeb solid 1px;
            width: 40px;
            height: 40px;
            border-radius: 20px;
        }
    </style>
</head>

<body>
    <!-- javascript:; 和 javascript:void(0) 都是防止链接跳转 -->
    <div class="login-header"><a id="link" href="javascript:;">点击,弹出登录框</a></div>
    <div id="login" class="login">
        <div id="title" class="login-title">登录会员
            <span><a id="closeBtn" href="javascript:void(0);" class="close-login">关闭</a></span>
        </div>
        <div class="login-input-content">
            <div class="login-input">
                <label>用户名:</label>
                <input type="text" placeholder="请输入用户名" name="info[username]" id="username" class="list-input">
            </div>
            <div class="login-input">
                <label>登录密码:</label>
                <input type="password" placeholder="请输入登录密码" name="info[password]" id="password" class="list-input">
            </div>
        </div>
        <div id="loginBtn" class="login-button"><a href="javascript:void(0);" id="login-button-submit">登录会员</a></div>
    </div>
    <!-- 遮盖层 -->
    <div id="bg" class="login-bg"></div>
    <script>
        //案例分析:
        // 1.点击弹出层这个链接link,让遮盖层mask和登录框link显示出来 display:block;
        // 2.点击关闭按钮,模态框和遮挡层就会隐藏起来 display:none;
        // 3.在页面中拖拽的原理:鼠标按下并且移动,之后松开鼠标
        // 4.触发事件是鼠标按下mousedown,鼠标移动mousemove,鼠标松开mouseup
        // 5.拖拽过程:鼠标移动过程中,获得最新的值赋值给模态框的left和top值,这样模态框就可以跟着鼠标走了
        // 6.鼠标按下触发的事件源是最上面一行,就是id为title的那一行
        // 7.鼠标的坐标(变化的) 减去 鼠标在盒子内的坐标(一直保持不变),才是模态框真正的位置
        // 8.鼠标按下,得到鼠标在盒子内的坐标
        // 9.鼠标移动,就让模态框的坐标设置为:鼠标坐标减去盒子坐标即可 注意:移动事件要写到按下事件里面
        // 10.鼠标松开,就停止拖拽,就是可以让鼠标移动事件解除


        // 1.获取元素
        var login = document.querySelector('.login'); //获取模态框
        var mask = document.querySelector('.login-bg'); //获取遮盖层
        var link = document.querySelector('#link'); //获取登录框
        var closeBtn = document.querySelector('#closeBtn'); //获取关闭按钮
        // 2.点击弹出层这个链接link,让遮盖层mask和登录框link显示出来 display:block;
        link.addEventListener('click', function() {
                mask.style.display = 'block';
                login.style.display = 'block';
            })
            // 3.点击关闭按钮,模态框和遮挡层就会隐藏起来 display:none;
        closeBtn.addEventListener('click', function() {
                mask.style.display = 'none';
                login.style.display = 'none';
            })
            // 4.开始拖拽
            // (1)获取登录会员那一栏
        var title = document.querySelector('#title');
        // (2)鼠标按下,获取鼠标在盒子内的位置
        title.addEventListener('mousedown', function(e) {
            var x = e.pageX - login.offsetLeft; //鼠标在盒子内的x坐标
            var y = e.pageY - login.offsetTop;
            // (3) 鼠标移动的时候,把鼠标在页面中的坐标减去鼠标在盒子内的坐标就是模态框的left和top值
            document.addEventListener('mousemove', move)

            function move(e) {
                login.style.left = e.pageX - x + 'px';
                login.style.top = e.pageY - y + 'px';

            }
            // (4) 鼠标弹起,就让鼠标移动事件解除
            document.addEventListener('mouseup', function() {
                document.removeEventListener('mousemove', move);
            })
        })
    </script>
</body>

</html>

效果展示

在这里插入图片描述

05-client系列属性

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>client系列属性</title>
    <style>
        div {
            width: 200px;
            height: 200px;
            background-color: pink;
            border: 10px solid red;
            padding: 10px;
        }
    </style>
</head>

<body>
    <div></div>
    <script>
        // client.Width 和我们offsetWidth最大的区别就是不包含边框 ,同样包含padding 
        var div = document.querySelector('div');
        console.log(div.clientWidth);
        console.log(div.clientHeight); //获取高度
        console.log(div.clientTop); //获取上边框大小
        console.log(div.clientLeft); 获取左边框大小
    </script>
</body>

</html>

06-flexible分析

(function flexible(window, document) {
    // 获取html根元素
    var docEl = document.documentElement
        //dpr 物理像素比 pc端物理像素比是1  移动端物理像素比是2
    var dpr = window.devicePixelRatio || 1

    // adjust body font size 设置body字体大小
    function setBodyFontSize() {
        // 如果页面中有body这个元素 就设置body的字体大小
        if (document.body) {
            document.body.style.fontSize = (12 * dpr) + 'px'
        } else {
            // 如果页面中没有body这个元素,则等着页面主要的DOM元素加载完毕再去设置body的字体大小
            document.addEventListener('DOMContentLoaded', setBodyFontSize)
        }
    }
    setBodyFontSize();

    // set 1rem = viewWidth / 10  设置HTML元素文字的大小
    function setRemUnit() {
        var rem = docEl.clientWidth / 10
        docEl.style.fontSize = rem + 'px'
    }

    setRemUnit()

    // reset rem unit on page resize 当我们页面尺寸大小发生变化,要重新设置下rem的大小
    window.addEventListener('resize', setRemUnit)
        // pageshow是我们页面重新加载时触发的事件
    window.addEventListener('pageshow', function(e) {
        // e.persisted 返回的是true,就是说如果这个页面是从缓存过来的页面,也需要重新计算一下rem的大小
        if (e.persisted) {
            setRemUnit()
        }
    })

    // detect 0.5px supports 有些移动端的浏览器不支持0.5像素的写法 以下是解决方法
    if (dpr >= 2) {
        var fakeBody = document.createElement('body')
        var testElement = document.createElement('div')
        testElement.style.border = '.5px solid transparent'
        fakeBody.appendChild(testElement)
        docEl.appendChild(fakeBody)
        if (testElement.offsetHeight === 1) {
            docEl.classList.add('hairlines')
        }
        docEl.removeChild(fakeBody)
    }
}(window, document))

07-立即执行函数

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <script>
        // 1.立即执行函数:不需要调用,立马能够自己执行的函数
        function fn() {
            console.log(1);
        }
        fn(); //不调用不执行
        // 2.立即执行函数写法   也可以传递参数进来
        //   (function() {})()   或者    (function() {}());
        (function(a, b) {
            console.log(a + b);
            var num = 10; //局部变量

        })(1, 2); //第二个小括号可以看作是调用函数 多个立即执行函数之间用分号隔开,否则会报错

        (function sum(a, b) {
            console.log(a + b);
            var num = 10; // 局部变量
        }(2, 3))
        // 3.立即执行函数最大的作用就是独立创建了一个作用域,里面所有的变量都是局部变量,不会有命名冲突的情况
    </script>
</body>

</html>

08-像素比和pageshow事件

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="07-flexible分析.js"></script>
</head>

<body>
    <script>
        console.log(window.devicePixelRatio); //pc端物理像素比是1 移动端是2
        window.addEventListener('pageshow', function() {
            alert(11);
        })
    </script>
    <a href="http://www.itcast.cn">链接</a>
</body>

</html>

09-元素滚动scroll系列

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        div {
            width: 200px;
            height: 200px;
            background-color: pink;
            border: 10px solid red;
            padding: 10px;
            /* 自动显示滚动条 */
            overflow: auto;
        }
    </style>
</head>

<body>
    <div>
        我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容

    </div>
    <script>
        // scroll系列
        var div = document.querySelector('div');
        console.log(div.scrollHeight);
        console.log(div.clientHeight);
        // scroll滚动事件 当我们滚动条发生变化会触发的事件
        div.addEventListener('scroll', function() {
            console.log(div.scrollTop);
        })
    </script>
</body>

</html>

10-仿淘宝固定右侧侧边栏(难点)

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <!--   // 案例分析
        // 1,原先侧边栏是绝对定位   需要用到页面滚动事件scroll,因为是页面滚动,所以事件源是document
        // 2.当页面滚动到一定位置,侧边栏改为固定定位  滚动到一定位置,就是判断页面被卷上去的上部值
        // 3.页面被卷去的头部:可以通过window.pageYOffset获得 如果是被卷去的左侧,则用window.pageXOffset
        // 4.注意,元素被卷去的头部是element.scrollTop  页面被卷去的头部是通过window.pageYOffset
        // 5.页面继续滚动,会让返回顶部显示出来 -->
    <style>
        .slider-bar {
            position: absolute;
            left: 50%;
            top: 300px;
            margin-left: 600px;
            width: 45px;
            height: 130px;
            background-color: pink;
        }
        
        .w {
            width: 1200px;
            margin: 10px auto;
        }
        
        .header {
            height: 150px;
            background-color: purple;
        }
        
        .banner {
            height: 250px;
            background-color: skyblue;
        }
        
        .main {
            height: 1000px;
            background-color: yellowgreen;
        }
        
        span {
            display: none;
            position: absolute;
            bottom: 0;
        }
    </style>
</head>

<body>
    <div class="slider-bar">
        <span class="goBack">返回顶部</span>
    </div>
    <div class="header w">头部区域</div>
    <div class="banner w">banner区域</div>
    <div class="main w">主体部分</div>
    <script>
        // 1.获取元素
        var sliderbar = document.querySelector('.slider-bar') //js不识别-,是所以可以去掉
        var banner = document.querySelector('.banner');
        //console.log(banner.offsetTop);//170
        //banner.offsetTop 就是被卷去头部的大小 一定要写到外面
        var bannerTop = banner.offsetTop;
        //当我们侧边栏固定定位之后应该变化的值
        var sliderbarTop = sliderbar.offsetTop - bannerTop;
        // 获取主题元素
        var main = document.querySelector('.main');
        var goBack = document.querySelector('.goBack');
        var mainTop = main.offsetTop;
        // 2.页面滚动事件 scroll
        document.addEventListener('scroll', function() {
                //console.log(1);
                // window.pageYOffset 页面被卷去的头部
                //console.log(window.pageYOffset);
                // 只要我们页面被卷曲的头部大于等于170,此时,侧边栏就要改为固定定位
                if (window.pageYOffset >= banner.offsetTop) {
                    sliderbar.style.position = 'fixed';
                    sliderbar.style.top = sliderbarTop + 'px';

                } else {
                    sliderbar.style.position = 'absolute';
                    sliderbar.style.top = '300px';


                }
                // 当页面滚动到main模块,goBack模块显示出来
                if (window.pageYOffset >= mainTop) {
                    goBack.style.display = 'block';

                } else {

                    goBack.style.display = 'none';


                }
            })
            // window.pageYOffset有兼容性问题
    </script>
</body>

</html>

效果展示

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值