【问题标题】:css pseudo element (triangle outside the tr) position misaligned when scrollbar appears滚动条出现时css伪元素(tr外的三角形)位置未对齐
【发布时间】:2017-08-20 04:13:55
【问题描述】:

我有一个高度固定的面板,overflow-y:auto; 在此面板中我正在显示表格,当用户单击其中一行时,行右侧的三角形出现,工作正常,直到滚动条没有出现表列表。如果有滚动条,则面板下方会出现右箭头。如何解决这个问题?

这是Working Fiddle,我还在下面添加了完整的代码sn-p和带有问题的图像

(function() {

  'use strict';

  angular
    .module('app', [])
    .controller('TableController', function($log, $scope) {
      $scope.tables = [{
          "name": "one_table",
          "purpose": "test"
        },
        {
          "name": "one_",
          "purpose": "test"
        }, {
          "name": "two_",
          "purpose": "test"

        }, {
          "name": "three_",
          "purpose": "test"
        }, {
          "name": "four_",
          "purpose": "test"
        }, {
          "name": "five_",
          "purpose": "test"
        }, {
          "name": "six_",
          "purpose": "test"
        }, {
          "name": "seven_",
          "purpose": "test"
        }, {
          "name": "eight_",
          "purpose": "test"
        }, {
          "name": "nine_",
          "purpose": "test"
        }, {
          "name": "ten_",
          "purpose": "test"
        }
      ];
      $scope.tindex = -1;
      $scope.rowClicked = function(idx) {
        $scope.tindex = idx;
      }
    });
})();
.panel-body {
  display: block;
  height: 230px;
  overflow-x: hidden;
  overflow-y: auto;
}

table {
  width: 100%;
  max-width: 100%;
}

.arrow-left:after {
  border-bottom: 20px solid transparent;
  border-left: 20px solid #eee;
  border-right: 20px solid transparent;
  border-top: 20px solid transparent;
  clear: both;
  content: '';
  float: right;
  height: 0px;
  margin: 1px auto;
  position: absolute;
  right: 8px;
  width: 0px;
}
<!DOCTYPE html>
<html ng-app="app">

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
</head>
<script src="https://code.jquery.com/jquery.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet" type="text/css" />
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.min.js"></script>

<body ng-controller="TableController">
  <div class="row col-md-12">
    <div class="col-md-4" data-define="tables">
      <div class="panel panel-default">
        <div class="panel-heading">
          <span>Tables</span>
        </div>
        <div class="panel-body no-padding">
          <table class="table table-striped">
            <tbody>
              <tr ng-repeat="table in tables track by $index" ng-click="rowClicked($index)" ng-class="tindex === $index ? 'arrow-left' : ''">
                <td>{{table.name}}</td>
                <td>{{table.purpose}}</td>
              </tr>
            </tbody>
          </table>
        </div>
      </div>
    </div>
  </div>

</body>

</html>

请帮助我找到正确的方法。

另一方面,我们可以使用 angular-custom 指令来完成此任务吗?

【问题讨论】:

  • 您需要在此处提供显示问题的标记,而不是明天可能会更改或消失的第三方网站。
  • 致关闭请求者;如果题外话,你会解释为什么这个问题?
  • stackoverflow.com/help/mcve 此外,您的 CSS 并不是显示问题的完整标记。除了补充您提供的代码外,不接受指向 jsfiddle 的链接。
  • @Rob 谢谢你的信息;我已经在问题中添加了代码 sn-p。
  • 这些第三方网站被用于每 3 个问题,内部代码 sn-p 应该是最小的,但外部链接是供观众使用的,以便他们可以尝试使用该小提琴。

标签: css angularjs scrollbar


【解决方案1】:

似乎伪元素的定位不正确,即使tr 被赋予position: relative

这个问题可以通过将伪元素添加到 td 来解决。

<tr ng-repeat="table in tables track by $index" >
   <td ng-click="rowClicked($index)" ng-class="tindex === $index ? 'arrow-left' : ''">{{table.name}}</td>
</tr>

并稍微修改 CSS:

table tbody tr td {
  position: relative;
}

.arrow-left:after {
    border-bottom: 20px solid transparent;
    border-left: 20px solid #eee;
    border-right: 20px solid transparent;
    border-top: 20px solid transparent;
    clear: both;
    content: '';
    float: right;
    height: 0px;
    margin: 1px auto;
    position: absolute;
    top: -3px;
    right: -18px;
    width: 0px;
}

我不确定将点击事件移动到 td 是否适合您。

jsbin

更新

要使用多个td,请按如下方式更新 CSS:

table tbody tr td {
  position: relative;
}

.arrow-left td:last-of-type:after {
    border-bottom: 20px solid transparent;
    border-left: 20px solid #eee;
    border-right: 20px solid transparent;
    border-top: 20px solid transparent;
    clear: both;
    content: '';
    float: right;
    height: 0px;
    position: absolute;
    top: -2px;
    right: 0;
    width: 0px;
}

jsbin

【讨论】:

  • 我在原始表格数据的每个 tr 中有 3 个 td,这种方式对我没有帮助。
  • 我已在行的最后一个 td 添加了此类,但现在出现了新问题。三角形进入面板主体,但我希望它在它之外
  • @pro.mean 如果您使用的表与您在问题中提供的示例不同,您可以创建一个新的演示吗?否则很难提供帮助
  • 感谢您的回复,但我希望该三角形位于容器之外,但在您的小提琴中,它位于容器(面板)内。
  • 另外,如果我尝试在 CSS 中添加 right:-30px 属性,那么三角形会出现在滚动条后面..这就是问题...如果它在控制器之外,那么就不会有这样的问题.
【解决方案2】:

如果您将position: relative 应用于表格元素,箭头将不会脱离容器。出于某种原因,规范在table-row 上说position: relative,而其他表格元素是undefined

以下是更多信息的规范: https://www.w3.org/TR/CSS21/visuren.html#propdef-position

【讨论】:

    【解决方案3】:

    您是否期望这样。

    (function() {
    
      'use strict';
    
      angular
        .module('app', [])
        .controller('TableController', function($log, $scope) {
          $scope.tables = [{
              "name": "one_table",
              "purpose": "test"
            },
            {
              "name": "one_",
              "purpose": "test"
            }, {
              "name": "two_",
              "purpose": "test"
    
            }, {
              "name": "three_",
              "purpose": "test"
            }, {
              "name": "four_",
              "purpose": "test"
            }, {
              "name": "five_",
              "purpose": "test"
            }, {
              "name": "six_",
              "purpose": "test"
            }, {
              "name": "seven_",
              "purpose": "test"
            }, {
              "name": "eight_",
              "purpose": "test"
            }, {
              "name": "nine_",
              "purpose": "test"
            }, {
              "name": "ten_",
              "purpose": "test"
            }
          ];
          $scope.tindex = -1;
          $scope.rowClicked = function(idx) {
            $scope.tindex = idx;
          }
        });
    })();
    .panel-body {
     display: block;
        height: 230px;
        overflow-x: hidden;
        overflow-y: auto;
    }
    
    table {
    
        color:#000!important;
      width: 100%;
      max-width: 100%;
    }
    
    .arrow-left:after {
        border-bottom: 15px solid transparent;
        border-left: 15px solid #eee;
       border-right: 15px solid transparent; 
        border-top: 15px solid transparent;
        clear: both;
        content: '';
        float: right;
        height: 0px;
        margin: 1px auto;
        position: relative;
        right: 8px;
        width: 0px;
    }
    .arrow-left1:after {
            border-bottom: 15px solid transparent;
        border-left: 15px solid #eee;
        border-right: 15px solid transparent;
        border-top: 15px solid transparent;
        clear: both;
        content: '';
        float: left;
        height: 0px;
        margin: 1px auto;
        position: relative;
        right: 0px;
        width: 0px;
    }
    <!DOCTYPE html>
    <html ng-app="app">
    
    <head>
      <meta charset="utf-8">
      <meta name="viewport" content="width=device-width">
      <title>JS Bin</title>
    </head>
    <script src="https://code.jquery.com/jquery.min.js"></script>
    <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet" type="text/css" />
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.min.js"></script>
    
    <body ng-controller="TableController">
      <div class="row col-md-12">
        <div class="col-md-4" data-define="tables">
          <div class="panel panel-default">
            <div class="panel-heading">
              <span>Tables</span>
            </div>
            <div class="panel-body no-padding">
              <table class="table table-striped">
                <tbody>
                  <tr ng-repeat="table in tables track by $index" ng-click="rowClicked($index)">
                    <td>{{table.name}}</td>
                    <td>{{table.purpose}}</td>
                    <td ng-class="tindex === $index ? 'arrow-left' : ''"></td>
                  </tr>
                </tbody>
              </table>
            </div>
            <br><br>
             <div class="panel-body no-padding">
              <table class="table table-striped">
                <tbody>
                  <tr ng-repeat="table in tables track by $index" ng-click="rowClicked($index)" ng-class="tindex === $index ? 'arrow-left1' : ''">
                    <td>{{table.name}}</td>
                    <td>{{table.purpose}}</td>  
                    <td>{{table.purpose}}</td>
                  </tr>
                </tbody>
              </table>
            </div>
            
          </div>
        </div>
      </div>
    
    </body>
    
    </html>

    【讨论】:

    • 我想要容器(表格面板)滚动条之外的那个三角形
    【解决方案4】:

    请检查这些结果,我认为它的工作方式符合您的期望

    (function() {
    
        'use strict';
    
        angular
            .module('app',[])
            .controller('TableController', function($log, $scope) {
            $scope.tables = [
            {
              "name": "one_table",
              "columns": [
                {"name": "id"},{"name": "f_name"}           
              ]
            },
            {
              "name": "one_",
              "columns": []
            }, {
              "name": "two_",
              "columns": []
            }, {
              "name": "three_",
              "columns": []
            }, {
              "name": "four_",
              "columns": []
            }, {
              "name": "five_",
              "columns": []
            }, {
              "name": "six_",
              "columns": []
            }, {
              "name": "seven_",
              "columns": []
            }, {
              "name": "eight_",
              "columns": []
            }, {
              "name": "nine_",
              "columns": []
            }, {
              "name": "ten_",
              "columns": []
            }
          ];
          $scope.tindex = -1;
          $scope.rowClicked = function (idx) {
            $scope.tindex = idx;
          }
        });
    })();
    .panel-body {
        display: block;
        height: 230px;
        overflow-x: hidden;
        overflow-y: auto;
    }
    table {
        width:100%;
        max-width: 100%;
    }
    .table tbody tr td {
        border-top: 0px !important;
    }
    .arrow-left:after {
        border-bottom: 20px solid transparent;
        border-left: 20px solid #ccc;
        /* border-right: 20px solid transparent; */
        border-top: 20px solid transparent;
        clear: both;
        content: '';
        float: right;
        height: 0px;
        /* margin: 1px auto; */
        position: relative;
        right:8px;
        width: 0px;
    }
    table tr {
        width:100%;
        position:relative;
        border-top: 1px solid #ccc;
      
    }
    table tr td {
        width:100%;
    }
    <!DOCTYPE html>
    <html ng-app="app">
    <head>
      <meta charset="utf-8">
      <meta name="viewport" content="width=device-width">
      <title>JS Bin</title>
    </head>
    <script src="https://code.jquery.com/jquery.min.js"></script>
    <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet" type="text/css" />
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.0/angular.min.js"></script>
    <body ng-controller="TableController">
    <div class="row col-md-12">
      <div class="col-md-4" data-define="tables">
          <div class="panel panel-default">
              <div class="panel-heading">
                  <span>Tables</span>
              </div>
              <div class="panel-body no-padding">
                  <table class="table table-striped">
                      <tbody >
                          <tr ng-repeat="table in tables track by $index" ng-click="rowClicked($index)" ng-class="tindex === $index ? 'arrow-left' : ''">
                              <td>{{table.name}}</td>
                          </tr>
                      </tbody>
                  </table>
              </div>
          </div>
          <div class="col-md-4" data-define="tables">HERE </div>
      </div>
      </div>
    
    </body>
    </html>

    【讨论】:

    • 感谢您的努力,但我的要求是在容器外显示该三角形。
    【解决方案5】:

    最后,在同事的帮助下,我通过自定义指令和一点点 CSS 解决了这个问题。

    panel-body中添加一个自定义指令并计算点击行的位置和面板高度并重新定位箭头类(没有任何伪元素)。以下是完整代码

    (function() {
    
        'use strict';
    
        angular
            .module('app',[])
            .controller('TableController', function($log, $scope) {
            $scope.tables = [
            {
              "name": "one_table",
              "columns": [
                {"name": "id"},{"name": "f_name"}           
              ]
            },
            {
              "name": "one_",
              "columns": []
            }, {
              "name": "two_",
              "columns": []
            }, {
              "name": "three_",
              "columns": []
            }, {
              "name": "four_",
              "columns": []
            }, {
              "name": "five_",
              "columns": []
            }, {
              "name": "six_",
              "columns": []
            }, {
              "name": "seven_",
              "columns": []
            }, {
              "name": "eight_",
              "columns": []
            }, {
              "name": "nine_",
              "columns": []
            }, {
              "name": "ten_",
              "columns": []
            }
          ];
          $scope.tindex = -1;
          $scope.rowClicked = function (idx) {
            $scope.tblRowClicked = idx;
            $scope.tindex = idx;
          }
        }).directive('showArrow', function($window, $timeout) {
                return {
                    restrict: 'A',
                    link: function(scope, element) {
                        // change the arrow position
                        var minHeight, maxHeight, maxWidth, tableHeight, style;
                        var row, rowPos, arrow;
                        var changeArrowPosition = function() {
                            $timeout(function() {
                                row = element.find('.hover');
                                rowPos = row.position(); // get position of clicked row
                                //console.log("rowPos:minHeight:maxHeight:tableHeight", rowPos, minHeight, maxHeight,tableHeight);
                                arrow = element.children('.dir-right');
                                arrow.hide();
                                if (rowPos) {
                                    if (rowPos.top >= minHeight && rowPos.top <= maxHeight) {
                                        style = {"top": rowPos.top + "px"};
                                        arrow.css(style);
                                        // if table height is lesser than panel height
                                        if (tableHeight <= maxHeight && maxWidth > 435) {
                                            style = {"margin": "auto 5px"};
                                            arrow.css(style);
                                        }
                                        arrow.addClass('arrow-right').show();
                                    }
                                }
                            });
                        };
    
                        element.on("click scroll", function() {
                            var elem = angular.element(this);
                            maxHeight = elem.height(); // panel height
                            maxWidth = elem.width(); //panel width
                            tableHeight = elem.children('table').height(); // table height
                            minHeight = elem.children('table').find('tr').eq(0).height(); // firt row height
                            changeArrowPosition();
                        });
                    }
                };
            });
        
    })();
    .panel-body {
        display: block;
        height: 230px;
        padding: 0px !important;
        overflow-x: hidden;
        overflow-y: auto;
    }
    table {
      width:100%;
      max-width: 100%;
    }
    tr {
      cursor: pointer;
    }
    tr.hover {
      background-color: #e5ee4f!important;
    }
    .arrow-right {
        border-bottom: 20px solid transparent;
        border-left: 20px solid #e5ee4f;
        border-right: 20px solid transparent;
        border-top: 20px solid transparent;
        clear: both;
        content: '';
        float: right;
        height: 0px;
        left: 96%;
        margin: 0px auto;
        position: absolute;
        width: 0px;
    }
    
    .dir-right {
        display: none;
    }
    <!DOCTYPE html>
    <html ng-app="app">
    <head>
      <meta charset="utf-8">
      <meta name="viewport" content="width=device-width">
      <title>JS Bin</title>
    </head>
    <script src="https://code.jquery.com/jquery.min.js"></script>
    <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet" type="text/css" />
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.0/angular.min.js"></script>
    <body ng-controller="TableController">
    <div class="row">
      <div class="col-md-12">
        <div class="col-md-4" data-define="tables">
          <div class="panel panel-default">
              <div class="panel-heading">
                  <span>Tables</span>
              </div>
              <div class="panel-body" show-arrow>
                  <table class="table table-striped">
                      <tbody >
                          <tr ng-repeat="table in tables track by $index" ng-click="rowClicked($index)" ng-class="tindex === $index ? 'hover' : ''">
                              <td>{{table.name}}</td>
                          </tr>
                      </tbody>
                  </table>
                  <i ng-if="vm.tblRowClicked === vm.tindex" class="dir-right"></i>
              </div>
          </div>
         </div>
       </div>
      </div>
    </body>
    </html>

    这是Working Fiddle

    希望对某人有所帮助。

    【讨论】:

      猜你喜欢
      • 2018-06-05
      • 1970-01-01
      • 2014-01-02
      • 1970-01-01
      • 1970-01-01
      • 2021-12-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多