边框样式不适用于粘性位置元素


75

我不知道为什么我的边框样式不适用于position: sticky;属性。我想在我的粘性表标题上设置边框样式。但是我不想使用透明的背景色。我该如何实现?这是我的问题和JSFiddle链接的示例代码

#wrapper {
  width: 400px;
  height: 200px;
  overflow: auto;
}

table {
  width: 100%;
  text-align: center;
  border-collapse: collapse;
}

table tr th,
table tr td {
  border: 2px solid;
}

table thead th {
  position: -webkit-sticky;
  position: sticky;
  top: 0;
  background-color: #edecec;
}
<div id="wrapper">
  <table>
    <thead>
      <tr>
        <th>A</th>
        <th>B</th>
        <th>C</th>
        <th>D</th>
        <th>E</th>
      </tr>
    </thead>
    <tr>
      <td>1</td>
      <td>1</td>
      <td>1</td>
      <td>1</td>
      <td>1</td>
    </tr>
    <tr>
      <td>2</td>
      <td>2</td>
      <td>2</td>
      <td>2</td>
      <td>2</td>
    </tr>
    <tr>
      <td>3</td>
      <td>3</td>
      <td>3</td>
      <td>3</td>
      <td>3</td>
    </tr>
    <tr>
      <td>4</td>
      <td>4</td>
      <td>4</td>
      <td>4</td>
      <td>4</td>
    </tr>
    <tr>
      <td>5</td>
      <td>5</td>
      <td>5</td>
      <td>5</td>
      <td>5</td>
    </tr>
    <tr>
      <td>6</td>
      <td>6</td>
      <td>6</td>
      <td>6</td>
      <td>6</td>
    </tr>
    <tr>
      <td>7</td>
      <td>7</td>
      <td>7</td>
      <td>7</td>
      <td>7</td>
    </tr>
    <tr>
      <td>8</td>
      <td>8</td>
      <td>8</td>
      <td>8</td>
      <td>8</td>
    </tr>
    <tr>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
    </tr>
    <tbody>
    </tbody>
  </table>
</div>

以下是我想要的屏幕截图,谁没有清楚我的问题。

在此处输入图片说明

您会看到的嵌入式边框样式th不起作用(移除positionCSS的属性,您将看到周围的Boders。)。

在此处输入图片说明

向下滚动一点后。您将看到所有边框样式都消失了。


您没有为table tr th, table tr td选择器提供颜色。语法应如下所示border: <unit> <border-style> <color>
凌晨

2
@soulshined不,实际上不需要。<color>部分不是强制性的。默认为#000000AFAIK。
灾变

有趣。学到了新东西!
凌晨

Answers:


119

由于使用出现问题border-collapse: collapse。当浏览器折叠边框时,<th>必须将的顶部和底部边框应用于周围的元素-的顶部边框<table>和底部的底部边框<tr>

如果您使用border-collapse: separate边框并将边框设置为一侧,则边框将真正附着在上<th>,如预期那样保持固定,并显示为已折叠。

这是可以应用于HTML代码段的示例样式。

#wrapper {
  width: 400px;
  height: 200px;
  overflow: auto;
}

table {
  width: 100%;
  text-align: center;
  border-collapse: separate; /* Don't collapse */
  border-spacing: 0;
}

table th {
  /* Apply both top and bottom borders to the <th> */
  border-top: 2px solid;
  border-bottom: 2px solid;
  border-right: 2px solid;
}

table td {
  /* For cells, apply the border to one of each side only (right but not left, bottom but not top) */
  border-bottom: 2px solid;
  border-right: 2px solid;
}

table th:first-child,
table td:first-child {
  /* Apply a left border on the first <td> or <th> in a row */
  border-left: 2px solid;
}

table thead th {
  position: sticky;
  top: 0;
  background-color: #edecec;
}

5
这种方法从根本上解决了问题,并且易于理解。我认为这比使用伪类更可取。
pj.dewitte '19

7
是的,但是当我使用此功能时,未使用的边框两侧似乎有一个像素间隙
Sainath SR

兄弟,保存了我的一天:)))
Wildhammer

1
该解决方案很简洁,但不幸的是,Edge中似乎存在一个错误,导致其无法正常工作。
媚兰

2
我认为不需要添加这么多的CSS类,您只需添加一件事即可:table {border-collapse:独立; 边框间距:0;}
RobertGłowacki20年

25

您需要使用box-shadowproperty而不是border-top/ border-bottom。此外,您需要删除表格的头和第一行的顶部/底部边框。

#wrapper {
                width : 400px;
                height : 200px;
                overflow : auto;
            }
            table {
                width : 100%;
                text-align : center;
                border-collapse : collapse;
            }
            table tr th, table tr td {
                border : 2px solid;
            }
            table thead th {
                position: -webkit-sticky;
                position : sticky;
                top : 0;
                background-color : #edecec;
            }

            /* here is the trick */
            table tbody:nth-of-type(1) tr:nth-of-type(1) td {
                border-top: none !important;
            }
            table thead th {
                border-top: none !important;
                border-bottom: none !important;
                box-shadow: inset 0 2px 0 #000000,
                            inset 0 -2px 0 #000000;
                padding: 2px 0;
            }
            /* and one small fix for weird FF behavior, described in /programming/7517127/ */
            table thead th {
                background-clip: padding-box
            }
            
<body>
        <div id="wrapper">
            <table>
                <thead>
                    <tr>
                        <th>A</th>
                        <th>B</th>
                        <th>C</th>
                        <th>D</th>
                        <th>E</th>
                    </tr>
                </thead>
                <tbody>
                    <tr>
                        <td>1</td>
                        <td>1</td>
                        <td>1</td>
                        <td>1</td>
                        <td>1</td>
                    </tr>
                    <tr>
                        <td>2</td>
                        <td>2</td>
                        <td>2</td>
                        <td>2</td>
                        <td>2</td>
                    </tr>
                    <tr>
                        <td>3</td>
                        <td>3</td>
                        <td>3</td>
                        <td>3</td>
                        <td>3</td>
                    </tr>
                    <tr>
                        <td>4</td>
                        <td>4</td>
                        <td>4</td>
                        <td>4</td>
                        <td>4</td>
                    </tr>
                    <tr>
                        <td>5</td>
                        <td>5</td>
                        <td>5</td>
                        <td>5</td>
                        <td>5</td>
                    </tr>
                    <tr>
                        <td>6</td>
                        <td>6</td>
                        <td>6</td>
                        <td>6</td>
                        <td>6</td>
                    </tr>
                    <tr>
                        <td>7</td>
                        <td>7</td>
                        <td>7</td>
                        <td>7</td>
                        <td>7</td>
                    </tr>
                    <tr>
                        <td>8</td>
                        <td>8</td>
                        <td>8</td>
                        <td>8</td>
                        <td>8</td>
                    </tr>   
                    <tr>
                        <td>9</td>
                        <td>9</td>
                        <td>9</td>
                        <td>9</td>
                        <td>9</td>
                    </tr>               
                </tbody>
            </table>
        </div>
    </body>


在FF,我仍然看到边界差距
Pizzicato

1
为Firefox更新。
Andrey Radomanov

这是唯一对我有用的答案。处理Material UI和一些theme.js覆盖。
克里斯·斯塔尔

谢谢。背景剪辑:padding-box!important; 帮助了我
Michaela Ervin

与引导样式表一起使用时,应删除标题边界,以避免某些奇怪的样式问题。例如。.wrapper thead th { border: none; }
br3nt

9

由于粘性定位在相对位置和固定位置之间波动,因此,我认为绕开这个开箱即用的唯一方法是利用伪类。

我敢肯定,有一种更优雅的方式可以完成此操作,但是我只是更改了:after:beforepsuedo类以为边框提供绝对定位。

#wrapper {
  width: 400px;
  height: 200px;
  overflow: auto;
}

table {
  width: 100%;
  text-align: center;
  border-collapse: collapse;
}

table tr th,
table tr td {
  border: 2px solid;
}

table thead th {
  position: -webkit-sticky;
  position: sticky;
  top: -1px;
  background-color: #edecec;
}
th:after,
th:before {
  content: '';
  position: absolute;
  left: 0;
  width: 100%;
}
th:before {
  top: 0;
  border-top: 3px solid blue;
}
th:after {
  bottom: 0;
  border-bottom: 3px solid blue;
}
<div id="wrapper">
  <table>
    <thead>
      <tr>
        <th>A</th>
        <th>B</th>
        <th>C</th>
        <th>D</th>
        <th>E</th>
      </tr>
    </thead>
    <tr>
      <td>1</td>
      <td>1</td>
      <td>1</td>
      <td>1</td>
      <td>1</td>
    </tr>
    <tr>
      <td>2</td>
      <td>2</td>
      <td>2</td>
      <td>2</td>
      <td>2</td>
    </tr>
    <tr>
      <td>3</td>
      <td>3</td>
      <td>3</td>
      <td>3</td>
      <td>3</td>
    </tr>
    <tr>
      <td>4</td>
      <td>4</td>
      <td>4</td>
      <td>4</td>
      <td>4</td>
    </tr>
    <tr>
      <td>5</td>
      <td>5</td>
      <td>5</td>
      <td>5</td>
      <td>5</td>
    </tr>
    <tr>
      <td>6</td>
      <td>6</td>
      <td>6</td>
      <td>6</td>
      <td>6</td>
    </tr>
    <tr>
      <td>7</td>
      <td>7</td>
      <td>7</td>
      <td>7</td>
      <td>7</td>
    </tr>
    <tr>
      <td>8</td>
      <td>8</td>
      <td>8</td>
      <td>8</td>
      <td>8</td>
    </tr>
    <tr>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
    </tr>
    <tr>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
    </tr>
    <tr>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
    </tr>
    <tr>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
    </tr>
    <tr>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
    </tr>
    <tr>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
    </tr>
    <tr>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
    </tr>
    <tr>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
    </tr>
    <tr>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
    </tr>
    <tr>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
    </tr>
    <tr>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
    </tr>
    <tr>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
    </tr>
    <tr>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
    </tr>
    <tr>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
    </tr>
    <tr>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
    </tr>
    <tr>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
    </tr>
    <tr>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
    </tr>
    <tr>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
    </tr>
    <tr>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
    </tr>
    <tr>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
    </tr>
    <tr>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
    </tr>
    <tbody>
    </tbody>
  </table>
</div>


感谢您提供更新的答案。但是对于左和右仍然不起作用,不是吗?
灾变

参见编辑@Cataclysm,让我知道您的想法。我只是将表格边框放回去,还是您希望它们具有与表格边框颜色分开的某种颜色?
soulshined

谢谢 !现在,我的想法几乎完成了。此处更新了小提琴
灾变

1
@soulshined非常感谢队友!你救了我!!:)
维卡斯(Vikas)

2
<td style="position: sticky;
           top: 0;
           left: 0;
           right: 0;
           padding: 4px 3px;
           background-color: #d3d3d3;
           box-shadow: inset 0 1px 0 black, inset 0 -1px 0 black;">
</td>

用这个100%的工作


我使用框阴影添加了“底部边框”。比其他答案更简单。
克里斯·周

1

尝试了一些现有的答案,但是正如评论所提到的,它们导致边界之间只有一个像素的间隙。

解决了一个问题,尽管它需要JavaScript。它放置一个<div>在每个<th>上调整其大小适合<div><th><th>然后将边框应用于<div>

请注意,撰写本文时,position: stickyChromium上的尚无法使用<thead>,但在Firefox中仍可使用。但是,position: sticky如果未执行JavaScript ,则相关的CSS不会影响页面。

Run code snippet在您的浏览器中单击以查看它是否有效。

function onResize() {
    $("thead th div").each(function () {
        var width = $(this).parent().outerWidth() - 2; // -2 * border-width
        $(this).css("width", width + "px");
    });
}

$("thead th").each(function () {
    $(this).append($("<div>"));
});

$(window).on("resize", onResize);
onResize();
table {
    width: 100%;
    border-collapse: collapse;
}

th {
    text-align: left;
}

th, td {
    padding: 12px 20px;

    border: 1px solid rgba(0, 0, 0, 0.125);
}

table thead {
    position: sticky;
    top: 0;

    background: #FFF;
}

/* Used as a workaround for position: sticky not rendering the border */
thead th div {
    width: 30px;
    margin: 0 -20px; /* -20px to negate the 20px from the padding */
    position: absolute;
    top: 0;
    bottom: 0;
    z-index: -1;

    border-right: 1px solid rgba(0, 0, 0, 0.125);
    border-bottom: 1px solid rgba(0, 0, 0, 0.125);
}
<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>

<table>
    <thead>
        <tr>
            <th>A</th>
            <th>B</th>
            <th>C</th>
            <th>D</th>
        </tr>
    </thead>
    <tbody>
        <tr><td>1</td><td>2</td><td>3</td><td>4</td></tr>
        <tr><td>1</td><td>2</td><td>3</td><td>4</td></tr>
        <tr><td>1</td><td>2</td><td>3</td><td>4</td></tr>
        <tr><td>1</td><td>2</td><td>3</td><td>4</td></tr>

        <tr><td>1</td><td>2</td><td>3</td><td>4</td></tr>
        <tr><td>1</td><td>2</td><td>3</td><td>4</td></tr>
        <tr><td>1</td><td>2</td><td>3</td><td>4</td></tr>
        <tr><td>1</td><td>2</td><td>3</td><td>4</td></tr>

        <tr><td>1</td><td>2</td><td>3</td><td>4</td></tr>
        <tr><td>1</td><td>2</td><td>3</td><td>4</td></tr>
        <tr><td>1</td><td>2</td><td>3</td><td>4</td></tr>
        <tr><td>1</td><td>2</td><td>3</td><td>4</td></tr>

        <tr><td>1</td><td>2</td><td>3</td><td>4</td></tr>
        <tr><td>1</td><td>2</td><td>3</td><td>4</td></tr>
        <tr><td>1</td><td>2</td><td>3</td><td>4</td></tr>
        <tr><td>1</td><td>2</td><td>3</td><td>4</td></tr>
    </tbody>
</table>

在下面包装以前的JavaScript,以将其限制为Firefox。

if (navigator.userAgent.toLowerCase().indexOf("firefox") > -1) {
    // ...
}

屏幕截图(Firefox 71):

屏幕截图(Firefox 71)


1

现在,我可以psuedo classes使用@soulshined建议的用户设置边框样式。下面是工作的CSS更改,这是JSFiddle Link。已经在chrome和firefox上进行过测试。

#wrapper {
  width: 400px;
  height: 200px;
  overflow: auto;
  padding: 1px;
}

table {
  width: 100%;
  text-align: center;
  border-collapse: collapse;
}
table tr th {
  border: 1px solid green;
}
table tr th:first-child {
  border-left: 1px solid green;
}
table tr td {
  border: 1px solid green;
}

table thead th {
  position: -webkit-sticky;
  position: sticky;
  top: 0;
  background-color: #edecec;
}

th::before {
  content: '';
  position: absolute;
  left: 0;
  width: 100%;
  height: 100%;
  border-right: 1px solid green;
  display: block;
  top : 1px;
}

th::after {
  content: '';
  position: absolute;
  left: 0;
  width: 100%;
  height: 100%;
  border-bottom: 1px solid green;
  border-top: 1px solid green;
  display: block;
  top : -1px;
}

1

采用 ::after伪选择器来模拟右边界

例:

th::after {
  content: '';
  position: absolute;
  top: 0;
  right: 0;
  height: 100%;
  border-right: 1px solid #e7e7e7;
}



0
  1. 粘性,可见标头边框

html{
    padding: 0px;
    margin: 0px;
}
body{
    padding: 0px;
    margin: 0px;
    width:100%;
}

 th,td{
     padding:10px;
     border: 0.1px solid #e8e0e0;
     padding-right:10px;
 }   
 th{
     text-align: center;
    background: #f3f3f3;
    background-clip: padding-box;
 }


thead th:first-child {
  left: 0;
  z-index: 1;
}
tbody th:first-child  {
   text-align: center;
  position: -webkit-sticky; /* for Safari */
  position: sticky;
  left: 0;
 
}
tbody th,thead th:first-child  {
/* display:flex; */
/* text-align: center;
align-items: center;
align-self: center; */
    width:30px;
    
    min-width: 30px;
    max-width: 30px;
    word-break: break-all;
}
.fixed_header{
    width: 100%;
    /* height: 500px; */
    table-layout: fixed;
    border-collapse: collapse;
}
/* .fixed_header tbody{
  overflow: auto;
 
} */

/* fixed header */
thead th {
    /* for Safari */
 text-align: center;
  position: -webkit-sticky;
   position: sticky;

  top: 0;


}

.fixed_header th, .fixed_header td {
    padding:10px;
  /* text-align: left; */
  width: 90px;
}

.fixed_header td{
    /* padding:10px; */
/* word-break: break-all; */
/* max-width: 200px; */
}
.table_container{
/* position: fixed; */
position: relative;
width:100% ;
min-height: 500px;
overflow: auto;
background:cornsilk;
}
 <table class="fixed_header">
                <thead>
                  <tr>
                   <th></th>
                    <th>Col 1</th>
                    <th>Col 2</th>
                    <th>Col 3</th>
                    <th>Col 4</th>
                    <th>Col 5</th>
                          <th>Col 1</th>
                    <th>Col 2</th>
                    <th>Col 3</th>
                    <th>Col 4</th>
                    <th>Col 5</th>
                          <th>Col 1</th>
                    <th>Col 2</th>
                    <th>Col 3</th>
                    <th>Col 4</th>
                    <th>Col 5</th>
                          <th>Col 1</th>
                    <th>Col 2</th>
                    <th>Col 3</th>
                    <th>Col 4</th>
                    <th>Col 5</th>
                  </tr>
                </thead>
                <tbody>
                  <tr>
                    <th>1</th>
                    <td>row 1-1</td>
                    <td>row 1-2</td>
                    <td>row 1-3</td>
                    <td>row 1-4</td>
                    <td>row 1-1</td>
                    <td>row 1-2</td>
                    <td>row 1-3</td>
                    <td>row 1-4</td>
                    <td>row 1-1</td>
                    <td>row 1-2</td>
                    <td>row 1-3</td>
                    <td>row 1-4</td>
                    <td>row 1-1</td>
                    <td>row 1-2</td>
                    <td>row 1-3</td>
                    <td>row 1-4</td>
                    <td>row 1-1</td>
                    <td>row 1-2</td>
                    <td>row 1-3</td>
                    <td>row 1-4</td>  
                </tr>     

                </tbody>
              </table>
            </div>


0

我相信这是最简单的答案。

接受的答案不提供1px边框的解决方案。

注意:这是一种解决方法,所以请不要困扰我。

如果border-top从表标题中删除,则该表不会折叠,因此不会创建任何空间来透视底层单元格。更换border-top保持DIV中相同样式的边框。

CSS:

table thead tr:nth-child(1) th {
  position: sticky; 
  border-top:0;
}

.table_holder {
  border-top:1px solid black;
}

的HTML:

<div id="table_holder">
  <table> ... </table>
</div>

0

替换borderoutline怎么样?我敢说,尤其是对于表元素,其outline行为几乎与相同border。我知道它不是开箱即用的模型,但在视觉上是相同的。尝试这个:

table tr th,
table tr td {
  border: 0; 
  outline: 2px solid;
}

请记住,outline始终在整个元素周围进行渲染,没有类似的东西outline-left,因此它不是万灵丹。有关更多详细信息,请参见MDN上的概述

更新:好吧,我忽略了一个细节,轮廓未与tbody边框正确对齐。您必须为整个表启动交换borderoutline或者使用transform和轻推thead,但这也许不是一个好方法(当然,这取决于)。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.