将绝对定位的元素固定到滚动视口的顶部
Fix absolutely positioned element to top of viewport on scroll
我正在尝试结合两全其美,并在设置 top: 0
(附加到视口顶部)时完成固定定位的作用,同时保持元素绝对定位,以便它水平滚动 parent 元素(用 fixed 这样做是有问题的)。
要注意的是,这是一个 table header,所以尝试通过将嵌套 divs
设置为不同的定位方法来解决这个问题在这里不起作用。
我目前尝试的是将 table header 保持在 absolute
的位置,同时计算 table 顶部与滚动事件侦听器中的视口:
const distanceToTop = this.headerElement.getBoundingClientRect().top;
this.stickyHeaderElement.style.top = `${Math.abs(distanceToTop)}px`;
this.headerElement
是原始的 table header,您可以滚动过去(什么都不做),而 stickyHeader 实例是烟雾和镜子发生的地方。
当前的方法正在做我想要它做的事情...但是,它非常笨拙,因为当您滚动过去原始 table header 并且粘性实例附加,由于每次触发事件侦听器时都会发生所有 DOM 操作,粘性 header 会抖动。
因为是按照上面的逻辑重新计算的
问题:我能否将绝对定位的 table header 元素也附加到视口的顶部,就像固定定位所允许的那样?有没有更有效的解决方案?
粘性 Headers 使用 Position:fixed 时很简单。
#header_container {
background: green;
height: 60px;
left: 0;
position: fixed;
width: 100%;
top: 0;
}
#header {
line-height: 60px;
margin: 0 auto;
width: 100%;
text-align: center;
}
#container {
margin: 0 auto;
overflow: auto;
padding: 80px 0;
width: 100%;
}
#content {
height: 500px;
}
<div id="header_container">
<div id="header">
Header Content
</div>
</div>
<div id="container">
<div id="content">
Content Here
</div>
</div>
这是你想要的吗?
let fixed = document.getElementById('fixed');
window.addEventListener("scroll", e => window.requestAnimationFrame( () => {
fixed.style.marginLeft = -1 * window.scrollX + "px";
}));
#fixed {
position: fixed;
background-color: white;
}
#unfixed {
color: white;
}
<link href="//cdnjs.cloudflare.com/ajax/libs/skeleton/2.0.4/skeleton.min.css" rel="stylesheet"/>
<div>
<table>
<thead>
<tr id="fixed">
<td>foo</td>
<td>bar</td>
<td>baz</td>
<td>fibble</td>
<td>meow</td>
<td>meow</td>
<td>meow</td>
<td>meow</td>
<td>meow</td>
<td>meow</td>
<td>meow</td>
<td>meow</td>
<td>meow</td>
<td>meow</td>
<td>meow</td>
<td>meow</td>
<td>meow</td>
<td>meow</td>
<td>meow</td>
<td>meow</td>
<td>meow</td>
<td>meow</td>
<td>meow</td>
<td>meow</td>
<td>ffft</td>
</tr>
<tr id="unfixed">
<td>foo</td>
<td>bar</td>
<td>baz</td>
<td>fibble</td>
<td>meow</td>
<td>meow</td>
<td>meow</td>
<td>meow</td>
<td>meow</td>
<td>meow</td>
<td>meow</td>
<td>meow</td>
<td>meow</td>
<td>meow</td>
<td>meow</td>
<td>meow</td>
<td>meow</td>
<td>meow</td>
<td>meow</td>
<td>meow</td>
<td>meow</td>
<td>meow</td>
<td>meow</td>
<td>meow</td>
<td>ffft</td>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td>9</td>
<td>10</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td>9</td>
<td>10</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td>9</td>
<td>10</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td>9</td>
<td>10</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td>9</td>
<td>10</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td>9</td>
<td>10</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td>9</td>
<td>10</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td>9</td>
<td>10</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td>9</td>
<td>10</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td>9</td>
<td>10</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td>9</td>
<td>10</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td>9</td>
<td>10</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td>9</td>
<td>10</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td>9</td>
<td>10</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td>9</td>
<td>10</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td>9</td>
<td>10</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td>9</td>
<td>10</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td>9</td>
<td>10</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td>9</td>
<td>10</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td>9</td>
<td>10</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td>9</td>
<td>10</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td>9</td>
<td>10</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td>9</td>
<td>10</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td>9</td>
<td>10</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
</tr>
</tbody>
</table>
我正在尝试结合两全其美,并在设置 top: 0
(附加到视口顶部)时完成固定定位的作用,同时保持元素绝对定位,以便它水平滚动 parent 元素(用 fixed 这样做是有问题的)。
要注意的是,这是一个 table header,所以尝试通过将嵌套 divs
设置为不同的定位方法来解决这个问题在这里不起作用。
我目前尝试的是将 table header 保持在 absolute
的位置,同时计算 table 顶部与滚动事件侦听器中的视口:
const distanceToTop = this.headerElement.getBoundingClientRect().top;
this.stickyHeaderElement.style.top = `${Math.abs(distanceToTop)}px`;
this.headerElement
是原始的 table header,您可以滚动过去(什么都不做),而 stickyHeader 实例是烟雾和镜子发生的地方。
当前的方法正在做我想要它做的事情...但是,它非常笨拙,因为当您滚动过去原始 table header 并且粘性实例附加,由于每次触发事件侦听器时都会发生所有 DOM 操作,粘性 header 会抖动。
因为是按照上面的逻辑重新计算的
问题:我能否将绝对定位的 table header 元素也附加到视口的顶部,就像固定定位所允许的那样?有没有更有效的解决方案?
粘性 Headers 使用 Position:fixed 时很简单。
#header_container {
background: green;
height: 60px;
left: 0;
position: fixed;
width: 100%;
top: 0;
}
#header {
line-height: 60px;
margin: 0 auto;
width: 100%;
text-align: center;
}
#container {
margin: 0 auto;
overflow: auto;
padding: 80px 0;
width: 100%;
}
#content {
height: 500px;
}
<div id="header_container">
<div id="header">
Header Content
</div>
</div>
<div id="container">
<div id="content">
Content Here
</div>
</div>
这是你想要的吗?
let fixed = document.getElementById('fixed');
window.addEventListener("scroll", e => window.requestAnimationFrame( () => {
fixed.style.marginLeft = -1 * window.scrollX + "px";
}));
#fixed {
position: fixed;
background-color: white;
}
#unfixed {
color: white;
}
<link href="//cdnjs.cloudflare.com/ajax/libs/skeleton/2.0.4/skeleton.min.css" rel="stylesheet"/>
<div>
<table>
<thead>
<tr id="fixed">
<td>foo</td>
<td>bar</td>
<td>baz</td>
<td>fibble</td>
<td>meow</td>
<td>meow</td>
<td>meow</td>
<td>meow</td>
<td>meow</td>
<td>meow</td>
<td>meow</td>
<td>meow</td>
<td>meow</td>
<td>meow</td>
<td>meow</td>
<td>meow</td>
<td>meow</td>
<td>meow</td>
<td>meow</td>
<td>meow</td>
<td>meow</td>
<td>meow</td>
<td>meow</td>
<td>meow</td>
<td>ffft</td>
</tr>
<tr id="unfixed">
<td>foo</td>
<td>bar</td>
<td>baz</td>
<td>fibble</td>
<td>meow</td>
<td>meow</td>
<td>meow</td>
<td>meow</td>
<td>meow</td>
<td>meow</td>
<td>meow</td>
<td>meow</td>
<td>meow</td>
<td>meow</td>
<td>meow</td>
<td>meow</td>
<td>meow</td>
<td>meow</td>
<td>meow</td>
<td>meow</td>
<td>meow</td>
<td>meow</td>
<td>meow</td>
<td>meow</td>
<td>ffft</td>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td>9</td>
<td>10</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td>9</td>
<td>10</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td>9</td>
<td>10</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td>9</td>
<td>10</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td>9</td>
<td>10</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td>9</td>
<td>10</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td>9</td>
<td>10</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td>9</td>
<td>10</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td>9</td>
<td>10</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td>9</td>
<td>10</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td>9</td>
<td>10</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td>9</td>
<td>10</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td>9</td>
<td>10</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td>9</td>
<td>10</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td>9</td>
<td>10</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td>9</td>
<td>10</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td>9</td>
<td>10</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td>9</td>
<td>10</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td>9</td>
<td>10</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td>9</td>
<td>10</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td>9</td>
<td>10</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td>9</td>
<td>10</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td>9</td>
<td>10</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td>9</td>
<td>10</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
</tr>
</tbody>
</table>