2017-02-02 4 views
28

고정 된 (고정 된) 열과 헤더로 테이블을 만드는 방법을 웹에서 검색했습니다. 마침내 해결책을 찾은 다음 내 필요에 맞게 수정 한 것처럼 보입니다.고정 된 (고정 된) 열과 헤더가있는 HTML 테이블

원래 바이올린은 here입니다.

Here은 제 수정 된 솔루션입니다. Chrome (버전 : 55.0.2883.87 m) 및 Firefox (버전 : 51.0.1)에서 테스트했습니다.

문제는 완전히 IE (버전 : 11.0.9600.18427)에서 작동하지 않는다는 것입니다. 수평 스크롤하는 동안 헤더의 고정 된 부분도 스크롤됩니다. 누군가 IE에서 작동하도록 도와 줄 수 있습니까? 그리고 한 가지 더 질문 : 접근법을 사용하는 것이 안전한가요? 일부 명시되지 않은 동작을 사용하는 경우 향후 브라우저 또는 일부 최신 브라우저에서 내 표가 잘못된 방식으로 표시 될 수 있으며 몇 가지 다른 표가있는 안전한 솔루션을 사용하고 스크롤 위치와 행을 동기화하는 것이 좋습니다 신장. UPD : 질문 : 모바일 장치에서이 작업을 안정화하는 방법은 무엇입니까?

$(document).ready(function() { 
 
    $('tbody').scroll(function(e) { //detect a scroll event on the tbody 
 
    \t /* 
 
    Setting the thead left value to the negative valule of tbody.scrollLeft will make it track the movement 
 
    of the tbody element. Setting an elements left value to that of the tbody.scrollLeft left makes it maintain \t \t \t it's relative position at the left of the table.  
 
    */ 
 
    $('thead').css("left", -$("tbody").scrollLeft()); //fix the thead relative to the body scrolling 
 
    $('thead th:nth-child(1)').css("left", $("tbody").scrollLeft()); //fix the first cell of the header 
 
    $('tbody td:nth-child(1)').css("left", $("tbody").scrollLeft()); //fix the first column of tdbody 
 
    }); 
 
});
.container { 
 
    height:200px; 
 
    width:400px; 
 
    overflow: hidden; 
 
} 
 

 
table { 
 
    position: relative; 
 
    background-color: #aaa; 
 
    border-collapse: collapse; 
 
table-layout: fixed; 
 
display: flex; 
 
flex-direction: column; 
 
height: 100%; 
 
width: 100%; 
 
} 
 

 

 
/*thead*/ 
 
thead { 
 
    position: relative; 
 
    display: block; /*seperates the header from the body allowing it to be positioned*/ 
 
} 
 

 
thead th { 
 
    background-color: #99a; 
 
    min-width: 120px; 
 
    border: 1px solid #222; 
 
} 
 

 
thead th:nth-child(1) {/*first cell in the header*/ 
 
    position: relative; 
 
    background-color: #88b; 
 
} 
 

 

 
/*tbody*/ 
 
tbody { 
 
    flex: 1; 
 
    position: relative; 
 
    display: block; /*seperates the tbody from the header*/ 
 
    overflow: auto; 
 
} 
 

 
tbody td { 
 
    background-color: #bbc; 
 
    min-width: 120px; 
 
    border: 1px solid #222; 
 
} 
 

 
tbody tr td:nth-child(1) { /*the first cell in each tr*/ 
 
    position: relative; 
 
    background-color: #99a; 
 
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<body> 
 
<div class="container"> 
 

 
    <table> 
 
    <thead> 
 
     <tr> 
 
     <th>Name<br/>123</th> 
 
     <th>Town</th> 
 
     <th>County</th> 
 
     <th>Age</th> 
 
     <th>Profession</th> 
 
     <th>Anual Income</th> 
 
     <th>Matital Status</th> 
 
     <th>Children</th> 
 
     </tr> 
 
     <tr> 
 
     <th>Name</th> 
 
     <th>Town</th> 
 
     <th>County</th> 
 
     <th>Age<br/>123<br/>321</th> 
 
     <th>Profession</th> 
 
     <th>Anual Income</th> 
 
     <th>Matital Status</th> 
 
     <th>Children</th> 
 
     </tr> 
 
    </thead> 
 
    <tbody> 
 
     <tr> 
 
     <td>John Smith</td> 
 
     <td>Macelsfield</td> 
 
     <td>Cheshire<br/>123</td> 
 
     <td>52</td> 
 
     <td>Brewer</td> 
 
     <td>£47,000</td> 
 
     <td>Married</td> 
 
     <td>2</td> 
 
     </tr> 
 
     <tr> 
 
     <td>Jenny Jones<br/>123<br/>312</td> 
 
     <td>Threlkeld</td> 
 
     <td>Cumbria</td> 
 
     <td>34</td> 
 
     <td>Shepherdess</td> 
 
     <td>£28,000</td> 
 
     <td>Single</td> 
 
     <td>0</td> 
 
     </tr> 
 
     <tr> 
 
     <td>Peter Frampton</td> 
 
     <td>Avebury</td> 
 
     <td>Wiltshire</td> 
 
     <td>57</td> 
 
     <td>Musician</td> 
 
     <td>£124,000</td> 
 
     <td>Married</td> 
 
     <td>4</td> 
 
     </tr> 
 
     <tr> 
 
     <td>Simon King</td> 
 
     <td>Malvern</td> 
 
     <td>Worchestershire</td> 
 
     <td>48</td> 
 
     <td>Naturalist</td> 
 
     <td>£65,000</td> 
 
     <td>Married</td> 
 
     <td>2</td> 
 
     </tr> 
 
     <tr> 
 
     <td>Lucy Diamond</td> 
 
     <td>St Albans</td> 
 
     <td>Hertfordshire</td> 
 
     <td>67</td> 
 
     <td>Pharmasist</td> 
 
     <td>Retired</td> 
 
     <td>Married</td> 
 
     <td>3</td> 
 
     </tr> 
 
     <tr> 
 
     <td>Austin Stevenson</td> 
 
     <td>Edinburgh</td> 
 
     <td>Lothian </td> 
 
     <td>36</td> 
 
     <td>Vigilante</td> 
 
     <td>£86,000</td> 
 
     <td>Single</td> 
 
     <td>Unknown</td> 
 
     </tr> 
 
     <tr> 
 
     <td>Wilma Rubble</td> 
 
     <td>Bedford</td> 
 
     <td>Bedfordshire</td> 
 
     <td>43</td> 
 
     <td>Housewife</td> 
 
     <td>N/A</td> 
 
     <td>Married</td> 
 
     <td>1</td> 
 
     </tr> 
 
     <tr> 
 
     <td>Kat Dibble</td> 
 
     <td>Manhattan</td> 
 
     <td>New York</td> 
 
     <td>55</td> 
 
     <td>Policewoman</td> 
 
     <td>$36,000</td> 
 
     <td>Single</td> 
 
     <td>1</td> 
 
     </tr> 
 
     <tr> 
 
     <td>Henry Bolingbroke</td> 
 
     <td>Bolingbroke</td> 
 
     <td>Lincolnshire</td> 
 
     <td>45</td> 
 
     <td>Landowner</td> 
 
     <td>Lots</td> 
 
     <td>Married</td> 
 
     <td>6</td> 
 
     </tr> 
 
     <tr> 
 
     <td>Alan Brisingamen</td> 
 
     <td>Alderley</td> 
 
     <td>Cheshire</td> 
 
     <td>352</td> 
 
     <td>Arcanist</td> 
 
     <td>A pile of gems</td> 
 
     <td>Single</td> 
 
     <td>0</td> 
 
     </tr> 
 
    </tbody> 
 
    </table> 
 
    
 
</div> 
 
</body>

+0

시도해보십시오. theadth : nth-child (1) {/ * 헤더의 첫 번째 셀 */ 위치 : 상대적; background-color : # 88b; display : 블록; } – Singh87

+0

@ Singh87, 스크롤하는 동안 세포가 장소에 머무르는 데 도움이되지만 세포가 자동으로 높이를 조절하는 기능을 잃어 버립니다. –

+0

DataTables - https://datatables.net/extensions/fixedcolumns/examples/initialisation/left_right_columns.html을 고려해 보시기 바랍니다. 고정 행을 지원합니다. –

답변

8

이 매우 독특한 것입니다 : 여기

는 접근 방식을 보여 일부 코드입니다. IE11은 (크롬과 다른 브라우저보다) 다른 중첩 된 요소의 상대적 위치를 처리처럼

$('thead').css("left", -$("tbody").scrollLeft()); //fix the thead relative to the body scrolling 

것 같습니다 : 문제가있는 코드이 줄 것 같습니다. 이 경우 오프셋을 사용하여 상대 위치 지정을 사용하여 thead을 배치합니다. 또한 오프셋 및 상대 위치 지정을 사용하여 thead th (어린이)을 배치합니다. Chrome은 table을 기준으로 thead의 위치에 있으며, thead을 기준으로 th의 위치를 ​​차지하는 것으로 보입니다. 반면에 IE11은 table에 대해 상대적 위치가 thead 인 것으로 나타나고 th은 자체 위치에 관계없이 동일한 위치를 상속합니다.

IE11에서는 thead에 대해 다르게 위치를 처리합니다. 부모 위치 지정을 thead 대신 설정하는 대신 thead th 요소에서 위치를 설정하십시오. 그렇게하면 첫 번째 열이 thead의 위치를 ​​(IE에서) 상속받지 못하게됩니다.

$(document).ready(function() { 
    var isIE11 = !!navigator.userAgent.match(/Trident.*rv\:11\./); 
    var customScroller; 
    if (isIE11) 
    customScroller = function() { 
     $('thead th').css("left", -$("tbody").scrollLeft()); //if using IE11, fix the th element 
    }; 
    else 
    customScroller = function() { 
     $('thead').css("left", -$("tbody").scrollLeft()); //if not using IE11, fix the thead element 
    }; 

    $('tbody').scroll(function(e) { //detect a scroll event on the tbody 
    /* 
    Setting the thead left value to the negative valule of tbody.scrollLeft will make it track the movement 
    of the tbody element. Setting an elements left value to that of the tbody.scrollLeft left makes it maintain    it's relative position at the left of the table.  
    */ 
    customScroller(); //fix the thead relative to the body scrolling 
    $('thead th:nth-child(1)').css("left", $("tbody").scrollLeft()); 
//fix the first cell of the header 
    $('tbody td:nth-child(1)').css("left", $("tbody").scrollLeft()); //fix the first column of tdbody 
    }); 
}); 

다음은 브라우저에 따라 다른 handlings을 보여주는 코드와 전체 예입니다

https://jsfiddle.net/8tx4xfhx/5/

Alsol, 누군가가 전에이 문제를 발견 한 경우 볼 것이 좋을 것이다. IE11은 중첩 된 상대 위치를 다른 브라우저와 다르게 처리하는 것으로 보입니다. 표준이 무엇인지 정의하는 어딘가에 스펙이 있습니까? IE와 마찬가지로 상대 위치를 상속해야합니까? 또는 상대 위치는 항상 부모에 상대적이어야합니까? 나는 후자를 생각할 것이다. 그러나 성능 고려 사항도 취해야합니다.

+0

감사합니다, Matt. 질문의 두 번째 부분에 대해 말할 수 있습니까? 그러한 솔루션을 사용하는 것이 안전합니까? '

'에'display : flex'를 사용하고 있습니다. 나는 그것이 몇 가지 불특정 행동을 포함하고 솔루션은 일부 브라우저에서 작동하지 않을 것 같습니다. –

+0

안녕 Artem. 실제로, 나는 당신이 다른 것을 위해 그것을 사용하고 있을지도 모른다고 생각했기 때문에 거기에'display : flex' 만 남겼습니다. 그것은 그 속성없이 할 수 있습니다. 여기에서 이것을 확인하십시오 : https://jsfiddle.net/mspinks/wLren00o/2/. 이것은 외부 컨테이너 스크롤러를 사용합니다. 더 나은 솔루션이라고 생각합니다. 그리고 그것은'flex'를 사용하지 않습니다. –

+0

감사. 'thead'와'tbody'에 대한'display : block'은 어떻습니까? 나는 해결책을 시도하고 IE에서조차 충분히 잘 작동한다. 그러나 모바일 브라우저에서 스크롤링이 부드럽 지 않은 경우 고정 된 부분이 실제로 같은 장소에 항상 머물러 있지 않은지 확인할 수 있습니다. 거기에 관련이 있습니까? –

6

일반적으로 고정 된 행의 경우 & 개의 열에 대해 최상의 브라우저 호환성을 위해 CSS 전용 솔루션을 사용하는 것이 좋습니다.

여기 코드를 CSS 전용 솔루션으로 복제하려고했습니다.

저는 Mac에서 작업 중이므로 IE에 액세스 할 수 없습니다. 해당 작업 벌금이 동일한 지 확인하십시오.

업데이트 바이올린 :

table { 
 
    position: relative; 
 
    width: 700px; 
 
    background-color: #aaa; 
 
    overflow: hidden; 
 
    border-collapse: collapse; 
 
} 
 
/*thead*/ 
 

 
thead { 
 
    position: relative; 
 
    display: block; 
 
    /*seperates the header from the body allowing it to be positioned*/ 
 
    width: 700px; 
 
    overflow: visible; 
 
} 
 
thead th { 
 
    background-color: #99a; 
 
    min-width: 120px; 
 
    height: 36px; 
 
    min-height: 36px; 
 
    border: 1px solid #222; 
 
} 
 
thead th:nth-child(1) { 
 
    /*first cell in the header*/ 
 
    position: relative; 
 
    display: block; 
 
    background-color: #88b; 
 
} 
 
tbody tr td:nth-child(2) { 
 
    margin-left: 124px; 
 
    display: block; 
 
} 
 
/*tbody*/ 
 

 
tbody { 
 
    display: block; 
 
    width: 700px; 
 
    height: 239px; 
 
    overflow-y: auto; 
 
} 
 
tbody td { 
 
    background-color: #bbc; 
 
    min-width: 120px; 
 
    border: 1px solid #222; 
 
    height: 36px; 
 
    min-height: 36px; 
 
} 
 
tbody tr td:nth-child(1) { 
 
    /*the first cell in each tr*/ 
 
    position: absolute; 
 
    display: inline-block; 
 
    background-color: #99a; 
 
}
<body> 
 
    <table> 
 
    <thead> 
 
     <tr> 
 
     <th>Name</th> 
 
     <th>Town</th> 
 
     <th>County</th> 
 
     <th>Age</th> 
 
     <th>Profession</th> 
 
     <th>Anual Income</th> 
 
     <th>Matital Status</th> 
 
     <th>Children</th> 
 
     </tr> 
 
    </thead> 
 
    <tbody> 
 
     <tr> 
 
     <td>John Smith</td> 
 
     <td>Macelsfield</td> 
 
     <td>Cheshire</td> 
 
     <td>52</td> 
 
     <td>Brewer</td> 
 
     <td>£47,000</td> 
 
     <td>Married</td> 
 
     <td>2</td> 
 
     </tr> 
 
     <tr> 
 
     <td>Jenny Jones</td> 
 
     <td>Threlkeld</td> 
 
     <td>Cumbria</td> 
 
     <td>34</td> 
 
     <td>Shepherdess</td> 
 
     <td>£28,000</td> 
 
     <td>Single</td> 
 
     <td>0</td> 
 
     </tr> 
 
     <tr> 
 
     <td>Peter Frampton</td> 
 
     <td>Avebury</td> 
 
     <td>Wiltshire</td> 
 
     <td>57</td> 
 
     <td>Musician</td> 
 
     <td>£124,000</td> 
 
     <td>Married</td> 
 
     <td>4</td> 
 
     </tr> 
 
     <tr> 
 
     <td>Simon King</td> 
 
     <td>Malvern</td> 
 
     <td>Worchestershire</td> 
 
     <td>48</td> 
 
     <td>Naturalist</td> 
 
     <td>£65,000</td> 
 
     <td>Married</td> 
 
     <td>2</td> 
 
     </tr> 
 
     <tr> 
 
     <td>Lucy Diamond</td> 
 
     <td>St Albans</td> 
 
     <td>Hertfordshire</td> 
 
     <td>67</td> 
 
     <td>Pharmasist</td> 
 
     <td>Retired</td> 
 
     <td>Married</td> 
 
     <td>3</td> 
 
     </tr> 
 
     <tr> 
 
     <td>Austin Stevenson</td> 
 
     <td>Edinburgh</td> 
 
     <td>Lothian</td> 
 
     <td>36</td> 
 
     <td>Vigilante</td> 
 
     <td>£86,000</td> 
 
     <td>Single</td> 
 
     <td>Unknown</td> 
 
     </tr> 
 
     <tr> 
 
     <td>Wilma Rubble</td> 
 
     <td>Bedford</td> 
 
     <td>Bedfordshire</td> 
 
     <td>43</td> 
 
     <td>Housewife</td> 
 
     <td>N/A</td> 
 
     <td>Married</td> 
 
     <td>1</td> 
 
     </tr> 
 
     <tr> 
 
     <td>Kat Dibble</td> 
 
     <td>Manhattan</td> 
 
     <td>New York</td> 
 
     <td>55</td> 
 
     <td>Policewoman</td> 
 
     <td>$36,000</td> 
 
     <td>Single</td> 
 
     <td>1</td> 
 
     </tr> 
 
     <tr> 
 
     <td>Henry Bolingbroke</td> 
 
     <td>Bolingbroke</td> 
 
     <td>Lincolnshire</td> 
 
     <td>45</td> 
 
     <td>Landowner</td> 
 
     <td>Lots</td> 
 
     <td>Married</td> 
 
     <td>6</td> 
 
     </tr> 
 
     <tr> 
 
     <td>Alan Brisingamen</td> 
 
     <td>Alderley</td> 
 
     <td>Cheshire</td> 
 
     <td>352</td> 
 
     <td>Arcanist</td> 
 
     <td>A pile of gems</td> 
 
     <td>Single</td> 
 
     <td>0</td> 
 
     </tr> 
 
    </tbody> 
 
    </table> 
 
</body>

+0

답변 해 주셔서 감사합니다. 또한 CSS 전용 솔루션을 원하지만 문제가 있습니다. 고정 된 부분의 행 높이와 주요 부분을 프로그래밍 방식으로 동기화해야합니다. 여기를 참조하십시오 : https://www.dropbox.com/s/3kg3cjfhrryolfj/2017-02-16_9-48-43.png?dl=0 –

7

당신은 jquery.floatThead.js의 참조 코드 샘플 아래 시도해야합니다 : https://jsfiddle.net/nashcheez/bzuasLcz/81/

코드를 참조하십시오.

    var $demoTable = $("div.table-responsive table"); 
        $demoTable.floatThead({ 
         top: 200, 
         scrollContainer: function ($table) {         
          return $table.closest('.table-responsive'); 
         }, 
         position: 'absolute' 
        }); 

당신은 jquery.floatThead.js 파일의 참조를 얻고 테이블에 이것을 적용하려고해야합니다.

아래 링크에서 확인할 수 있습니다.

+0

좋은데, 헤더에 관한 것 뿐이므로 실제로 헤더 헤더를 복제합니다. 다른 테이블과 그것을 절대적으로 배치합니다. –

+0

헤더를 복제하지 않고 다른 테이블로 이동합니다 (그리고 위치 지정 옵션에 따라 뒤로 이동). 하지만 그래, 열 동결에 대해서는 아무 것도하지 않아. – mkoryak

1

문제는 IE가 행 전체와 독립된 셀의 left 속성을 조정할 수 없다는 것입니다. IE의 개발자 창과 Chrome의 개발자 창을 사용하여 DOM을 직접 편집하여이를 볼 수 있습니다.

크롬에서 좌우로 스크롤하면 요소 뷰어에서 요소이 변경되어 모든 CSS를 덮어 쓰는 것을 볼 수 있습니다. 이 동일한 화면에서 페이지를 새로 고침하고 요소 속성을 수동으로 설정할 수 있습니다 (style:'left:300px'). 그러면 헤더 셀이 오른쪽 300px로 이동하고 나머지 헤더 셀 위로 마우스가 이동합니다. 이는 좋은 동작이며이 방법을 작동시키는 동작입니다.

IE에서 동일한 작업을 수행하고 style: 'left:300px'을 th 요소에 추가하면 셀이 이동하지 않습니다. 우리가 그 셀의 스타일 속성에 대해 아무 것도하지 않으면 테이블의 자리를 그 자리로 떠나게됩니다. 이 방법을 실패하게 만드는 것은 IE의 '특징'입니다. IE는 행 내의 요소에 어떤 속성이 적용되는지에 관계없이 셀 순서를 유지할 것을 주장합니다.

트릭은 모든 브라우저를 행복하게 만드는 방식으로 이러한 복잡성을 해결하는 것입니다. 이 작업을 수행하는 방법은 여러 가지가 있지만 두 테이블을 사용하고 DIV를 사용하여 가장자리가 일치하도록 위치를 지정합니다. 하나의 tbody가 위 또는 아래로 스크롤하면 같은 방식으로 다른 tbody에 영향을 미칠 수 있도록 자바 스크립트를 추가합니다. 오른쪽 또는 왼쪽으로 스크롤하면 고정 된 열 머리글을 보유하는 첫 번째 테이블에는 아무런 변화가 없으며 오른쪽 테이블은 계획대로 스크롤 방향으로 이동합니다.

IE는 두 테이블을 사용하여 더 이상 고정하려고하는 헤더를 이동중인 헤더와 연결하지 않습니다. 조심성있는 CSS는 해킹을 숨기고 테이블을 하나의 테이블로 나타냅니다.

행운과 행복 코딩!

+1

감사합니다, Jared. 실제로 나는 당신이 묘사 한 방법을 현재 사용하고 있습니다. 하지만 문제는 고정 테이블과 스크롤 테이블의 행 높이를 동기화해야한다는 것입니다. 테이블이 매우 동적 인 경우 : 필요에 따라 레코드를로드하는 경우, 사용자가 셀 내용을 편집 할 수있는 경우, 데이터를 동적으로 변경할 수 있는지 등을 고려하면 성가 시게됩니다. 나도 별도의 div에 헤더를 배치하므로 자바 스크립트에서 나는 수평 스크롤, 수직 스크롤, 행의 높이 동기화를 수행해야한다. 내 꿈은 모든 것을 1 개의 테이블로 만드는 것입니다. –

+0

그것은 이해할 수 있고 좋은 꿈입니다. IE가 모든 사람의 삶을 복잡하게 만드는 것은 수치스러운 일입니다. 창조적 인 대안으로 운이 좋을 수도 있습니다. 예를 들어, div를 스크롤하는 대신 스크롤 이벤트를 테이블에 표시되는 다른 데이터로 변환 할 수 있습니다. Javascript는 동적으로 셀 값을 변경하여 이산 측정에서 스크롤 동작이 발생하는 것처럼 보이도록 만들 수 있지만 실제로 셀의 데이터는 변경됩니다. –

관련 문제