css pseudo element (triangle outside the tr) position misaligned when scrollbar appears

前端 未结 5 789
被撕碎了的回忆
被撕碎了的回忆 2021-01-18 07:52

I have a panel which height is fixed and overflow-y:auto; in this panel I am displaying table and when user click on one of the row, triangle on right side of

相关标签:
5条回答
  • 2021-01-18 07:53

    Did you expect like this.

    (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>

    0 讨论(0)
  • 2021-01-18 07:58

    It appears that the pseudoelement isn't being positioned correctly, even when the tr is given a position: relative

    This issue can be fixed by adding the pseudoelement to the td instead.

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

    and altering the CSS slightly:

    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;
    }
    

    I'm not sure if moving the click event to the td is a solution for you however.

    jsbin

    update

    To work with multiple td, update CSS as below:

    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

    0 讨论(0)
  • 2021-01-18 08:10

    If you apply position: relative to the table element, the arrow won't escape the container. For some reason the spec says a position: relative on table-row and other table elements are undefined.

    Here's the spec for more info: https://www.w3.org/TR/CSS21/visuren.html#propdef-position

    0 讨论(0)
  • 2021-01-18 08:12

    please check these result, i think its working the correct way of you expecting

    (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>

    0 讨论(0)
  • 2021-01-18 08:19

    Finally, I have resolved this by custom directive and little bit CSS and with help of my colleague.

    add a custom directive in panel-body and calculate the position of clicked row and the panel height and reposition the arrow class ( without any pseudo element). Below is full code

    (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>

    Here is a Working Fiddle

    Hope it helps someone.

    0 讨论(0)
提交回复
热议问题