DOMElement之Offset

本文深入探讨了HTML元素的offsetTop属性,解释了它如何计算当前元素相对于offsetParent元素顶部的距离,并详细说明了offsetParent的概念、position属性的不同值以及它们对元素定位的影响。通过实例代码演示,帮助开发者清晰地理解这些概念。

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

有明确目的的学习比较有效,我学习HTML offset相关概念是出自一个需求,那就是计算一个绝对定位的HTML元素相对于当前窗口的偏移距离,主要是Y方向的偏移,X方向同理。

要实现这个目的,首先要弄清楚HTML关于偏移距离的定义:

1. offsetTop

MDN的定义:The HTMLElement.offsetTop read-only property returns the distance of the current element relative to the top of the offsetParent node.

既然是distance,就涉及到比较的两个点,起点和终点(或者是两条平行线)。根据CSS盒子模型,HTMLElement元素有margin, border, padding和content. 计算的是margin edge到margin edge呢,border edge到border edge呢,是padding edge到padding edge呢,还是content edge到content edge呢?甚至是一个元素的padding edge到另外一个元素的margin edge呢?

这里所有的边,都是指代外面的边,如下图所示。

CSS Box model

注:图片来自MDN

问题1:offsetTop计算的是当前元素相对于它的offsetParent元素的顶部的距离,那么是哪条边到哪条边的距离呢?

在回答这个问题之前,我们得先弄清楚offsetParent是个什么东西。

2. offsetParent

MDN的定义:The HTMLElement.offsetParent read-only property returns a reference to the object which is the closest (nearest in the containment hierarchy) positioned containing element. If the element is non-positioned, the nearest table cell or root element (html in standards compliant mode; body in quirks rendering mode) is the offsetParentoffsetParent returns null when the element has style.displayset to "none". The offsetParent is useful because offsetTop and offsetLeft are relative to its padding edge.

closet (nearest in the containment hierarchy) positioned containing element - 在包含层次结构(也就是当前元素的祖先元素)中离当前元素最近的,定位过的元素。也就是说是当前元素的父级(祖先)元素中,离当前元素最近的定位过的元素。那么又出现一个新的问题,什么是“定位过的元素”?

3. position

MDN的定义:The position CSS property chooses alternative rules for positioning elements, designed to be useful for scripted animation effects.

Position是一个CSS属性,来定义元素的定位规则,有下面一些值可以选择,一下内容来自w3.org,因为MDN声称有sticky一值可选,经过测试Chrome和IE都不支持,只有Firefox支持,此属性尚属于CSS3 draft阶段。

static The box is a normal box, laid out according to the normal flow. The 'top''right''bottom', and 'left' properties do not apply.

relative The box's position is calculated according to the normal flow (this is called the position in normal flow). Then the box is offset relative to its normal position. When a box B is relatively positioned, the position of the following box is calculated as though B were not offset. The effect of 'position:relative' on table-row-group, table-header-group, table-footer-group, table-row, table-column-group, table-column, table-cell, and table-caption elements is undefined.

absolute The box's position (and possibly size) is specified with the 'top''right''bottom', and 'left' properties. These properties specify offsets with respect to the box's containing block. Absolutely positioned boxes are taken out of the normal flow. This means they have no impact on the layout of later siblings. Also, though absolutely positioned boxes have margins, they do not collapse with any other margins.

fixed The box's position is calculated according to the 'absolute' model, but in addition, the box is fixed with respect to some reference. As with the 'absolute' model, the box's margins do not collapse with any other margins. In the case of handheld, projection, screen, tty, and tv media types, the box is fixed with respect to the viewport and does not move when scrolled. In the case of the print media type, the box is rendered on every page, and is fixed with respect to the page box, even if the page is seen through a viewport (in the case of a print-preview, for example). For other media types, the presentation is undefined. Authors may wish to specify 'fixed' in a media-dependent way. For instance, an author may want a box to remain at the top of the viewport on the screen, but not at the top of each printed page.

回到我们最初的问题,position是哪种值才算是“定位过的元素”呢?

从定义似乎看不出来什么,那么就来做测试吧。

 1 <!doctype html>
 2 <html>
 3 <head>
 4 <style>
 5 #parent_static { position: static; }
 6 #parent_absolute { position: absolute; top: 20px; }
 7 #parent_relative { position: relative; top: 60px; }
 8 #parent_fixed { position: fixed; top: 100px; }
 9 #child_static,#child_absolute,#child_relative,#child_fixed { position:absolute; top: 5px; width: 400px; border: 1px solid;}
10 </style>
11 </head>
12 <body>
13 <div id="parent_static"><div id="child_static"></div></div>
14 <div id="parent_absolute"><div id="child_absolute"></div></div>
15 <div id="parent_relative"><div id="child_relative"></div></div>
16 <div id="parent_fixed"><div id="child_fixed"></div></div>
17 <script src="http://apps.bdimg.com/libs/jquery/2.1.1/jquery.min.js"></script>
18 <script>
19 function getOffsetParentString(obj)
20 {
21     if(obj.offsetParent)
22     {
23         if(obj.offsetParent.id)
24         {
25             return obj.id + ":\t" + obj.offsetParent.id;
26         }
27         else
28         {
29             return obj.id + ":\t" + obj.offsetParent.tagName;
30         }
31     }
32     else
33     {
34         return "null";
35     }
36 }
37 $('#child_static').html(getOffsetParentString($('#child_static')[0]));
38 $('#child_absolute').html(getOffsetParentString($('#child_absolute')[0]));
39 $('#child_relative').html(getOffsetParentString($('#child_relative')[0]));
40 $('#child_fixed').html(getOffsetParentString($('#child_fixed')[0]));
41 </script>
42 </body>
43 </html>

结果如下:

 

OK,从上面的测试我们可以得到一个结论,除了static方式的position(也是默认方式),其他的三个元素都是所谓的“positioned”。

那么回答之前的一个问题:什么是“定位过的元素”?

定位过的元素就是使用Position:relative|absolute|fixed作为定位方式的HTML元素。

那么接着offsetParent的定义也就清楚了,在当前元素的包含结构上的离它最近的定位过的父元素就是它的offsetParent,如果没有,默认就是HTML的body元素。

让我们回到最初的问题,offsetTop计算的是当前元素相对于它的offsetParent元素的顶部的距离,那么是哪条边到哪条边的距离呢?

继续用事实说话:

<!doctype html>
<html>
<head>
<style>
#parent_absolute { position: absolute; top: 8px;; margin: 1px; border: 2px solid blue; padding: 4px; width: 800px; height: 600px; }
#child_absolute { position:absolute; top: 16px; margin-top: 32px; border: 64px solid #ccc; padding: 128px;}
</style>
</head>
<body>
<div id="parent_absolute"><div id="child_absolute"></div></div>
<script src="http://apps.bdimg.com/libs/jquery/2.1.1/jquery.min.js"></script>
<script>
function getOffsetTopString(obj)
{
    if(obj.offsetParent)
    {
        if(obj.offsetParent.id)
        {
            return "OffsetTop of (" + obj.id + " - " + obj.offsetParent.id + "):\t" + obj.offsetTop;
        }
        else
        {
            return "OffsetTop of (" + obj.id + " - " + obj.offsetParent.tagName + "):\t" + obj.offsetTop;;
        }
    }
    else
    {
        return "null";
    }
}
$('#child_absolute').html(getOffsetTopString($('#child_absolute')[0]));
</script>
</body>
</html>

从测试结果可以看出,offsetTop的值是当前元素的"margin-top"+"top",但是还是无法回答我们之前的那个问题,这个值是哪条边到哪条边呢?因为我们不知道这个值是否覆盖了父元素的padding甚至是border

有一个解决方案是找一把pixel ruler(比如一个很小巧的免费软件叫JRuler)在屏幕上测量一下

另外一种方法是,把当前元素的margin-top设置为0px, top设置为-1px,看看这个元素的border会出现在哪个位置

把上面的code改成: 

#child_absolute { position:absolute; top: -1px; margin-top: 0px; border: 64px solid #ccc; padding: 128px;}

 

可以看到,当前元素覆盖了offsetParent元素的border一个像素。

那么现在我们可以回答一开始的问题了,offsetTop计算的是当前元素相对于它的offsetParent元素的顶部的距离,那么是哪条边到哪条边的距离呢?

offsetTop是当前元素的border edge到它的offsetParent元素的padding edge的距离

用图来表示就是

 

 

注1:此图为原创

注2:不要误以为offsetTop = padding+margin, 图示所表达的意思是offsetTop是当前元素的border边界到其offsetParent元素的padding边界的距离

 

转载于:https://www.cnblogs.com/un4sure/p/4703433.html

### Offset 编程含义 Offset 表达的是位置偏移的概念,在不同的编程语言和上下文中有着特定的应用场景。 #### C 语言中的 File Offset 在C语言中,文件操作涉及到读写指针的位置管理。`offset`用来描述相对于文件起始位置的字节数。当执行文件I/O操作时,可以通过设置或查询这个值来控制数据存取的具体位置[^3]。 ```c #include <stdio.h> int main(){ FILE *fp; long offset; fp = fopen("example.txt", "r+"); fseek(fp, 0L, SEEK_END); offset = ftell(fp); // 获取当前文件指针距离开头的距离即为offset } ``` #### JavaScript 中 DOM Element Offsets JavaScript里的一组offset属性(如 `offsetHeight`, `offsetWidth`, `offsetLeft`, 和 `offsetTop`),提供了访问HTML元素几何信息的方法。这些属性返回数值型的结果,单位通常是像素(px),可用于布局调整、动画效果计算等方面[^2]。 ```javascript const element = document.getElementById('myElement'); console.log(`宽度:${element.offsetWidth}px`); console.log(`高度:${element.offsetHeight}px`); console.log(`左边距:${element.offsetLeft}px`); console.log(`顶边距:${element.offsetTop}px`); ``` #### Kafka Consumers' Message Offset Management 对于Kafka而言,offset指的是每条记录在一个分区内的唯一序列号。消费者应用程序通过维护此编号跟踪已经处理的消息,并决定是从最新消息还是从前一次中断处继续接收新到来的数据流。支持两种模式——自动提交与手动提交,前者简化了开发流程而后者给予开发者更多灵活性去实现复杂的业务逻辑[^4]。 ```python from kafka import KafkaConsumer consumer = KafkaConsumer( 'topic_name', bootstrap_servers=['localhost:9092'], auto_offset_reset='earliest', # 或者 'latest' enable_auto_commit=True, group_id='test-group') for message in consumer: print ("%s:%d:%d: key=%s value=%s" % (message.topic, message.partition, message.offset, message.key, message.value)) ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值