Web 이야기/티스토리&HTML&CSS

테이블 틀고정 CSS로 깔끔하게 고정하기 - HTML TABLE HEAD Fixed

뜨란 2018. 9. 7.
반응형

본 포스트는 틀고정 작업을 하기 위해 시행착오를 겪으며 만들었던 포스트입니다. 


보다 깔끔하게 만들 수 있도록 새로운 글을 작성하였으니 깔끔하게 동작하는 틀고정을 원하신다면 아래 링크의 글을 확인하시기 바랍니다.







* * *   * * *



DB에서 불러오는 데이터 테이블의 메뉴 필드를 고정시켜 달라는 요청이 있어 고정을 시도해봤는데 생각처럼 잘 되지 않았다.


정확히는 필드가 고정은 되는데 고정되어 있는 부분과 본문의 너비가 틀어지면서 원하는대로 깔끔한 고정이 이루어지지 않았다.


수 차례 시도 끝에 CSS만으로 깔끔하게 메뉴바를 틀고정하는 소스를 짜낼 수 있었다. 




해결 과정을 및 이해를 돕고자 간단한 테이블을 만들었다. 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
<style>
    .wrap{width:600px; height: 200px; border:1px solid #00c; padding:5px;  color:rgb(0, 0, 0); overflow: auto;}
    table{border:1px solid #000; width:100%; background:#E1E1E1; text-align: center; font-size: 20px;}        
    th{background:#5c5c5c;}
    th,td{border:1px solid rgba(0, 0, 0, 0.596); height:20px;}
    .tbwid_10{width:10%;}
    .tbwid_20{width:20%;}
    .tbwid_30{width:30%;}
</style>
 
 
<body>
    <div class="wrap">
        <table cellpadding=0 cellspacing=0 border=0>
            <tr>
                <th class="tbwid_20">구분</th>
                <th class="tbwid_30">품목</th>
                <th class="tbwid_10">수량</th>
                <th class="tbwid_20">단가</th>
                <th class="tbwid_20">구매금액</th>
            </tr>
            <tr>
                <td>게임</td>
                <td>배틀그라운드</td>
                <td>2</td>
                <td>20,000</td>
                <td>40,000</td>
            </tr>
            <tr>
                <td>게임</td>
                <td>오버워치</td>
                <td>1</td>
                <td>32,000</td>
                <td>32,000</td>
            </tr>
            <tr>
                <td>게임</td>
                <td>스타크래프트2</td>
                <td>2</td>
                <td>28,000</td>
                <td>56,000</td>
            </tr>
            <tr>
                <td>게임</td>
                <td>드래곤퀘스트11</td>
                <td>1</td>
                <td>40,000</td>
                <td>40,000</td>
            </tr>            
            <tr>
                <td>게임</td>
                <td>배틀그라운드</td>
                <td>2</td>
                <td>20,000</td>
                <td>40,000</td>
            </tr>
            <tr>
                <td>게임</td>
                <td>오버워치</td>
                <td>1</td>
                <td>32,000</td>
                <td>32,000</td>
            </tr>
            <tr>
                <td>게임</td>
                <td>스타크래프트2</td>
                <td>2</td>
                <td>28,000</td>
                <td>56,000</td>
            </tr>
            <tr>
                <td>게임</td>
                <td>드래곤퀘스트11</td>
                <td>1</td>
                <td>40,000</td>
                <td>40,000</td>
            </tr>            
            <tr>
                <td>게임</td>
                <td>배틀그라운드</td>
                <td>2</td>
                <td>20,000</td>
                <td>40,000</td>
            </tr>
            <tr>
                <td>게임</td>
                <td>오버워치</td>
                <td>1</td>
                <td>32,000</td>
                <td>32,000</td>
            </tr>
            <tr>
                <td>게임</td>
                <td>스타크래프트2</td>
                <td>2</td>
                <td>28,000</td>
                <td>56,000</td>
            </tr>
            <tr>
                <td>게임</td>
                <td>드래곤퀘스트11</td>
                <td>1</td>
                <td>40,000</td>
                <td>40,000</td>
            </tr>
        </table>
    </div>
cs

<틀고정 시도 전의 기본코드>



아래 사진에서처럼 구분, 품목, 수량, 단가, 구매금액 등이 나타나는 가장 윗줄,


HTML 태그상에서는 THEAD로 구분하거나 TH 등으로 구분하는 메뉴를 틀고정하는 것이 목표다.





우선 검색해서 찾았던 해결 방법 중에 thead를 별도의 div에 고정시켜 위로 띄워주는 방식을 적용해보았다.


wrap2라는 div를 하나 만들었고, position:relative를 부여하여 thead가 고정되도록 하는 방식으로 접근했다.


고정은 성공했으나 그림에서처럼 너비가 틀어졌다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
<style>    
    .wrap{width:600px; height: 200px; border:1px solid #00c; padding:5px;  color:rgb(0, 0, 0); overflow: auto;}
    .wrap2{width:100%;  height: 100%; position: relative;}
    .table{border:1px solid #000; width:100%; background:#E1E1E1; text-align: center; font-size: 20px;}        
    .table th{background:#5c5c5c;}
    .table th,td{border:1px solid rgba(0, 0, 0, 0.596); height:20px;}
    .tbwid_10{width:10%;}
    .tbwid_20{width:20%;}
    .tbwid_30{width:30%;}
    .table thead{position: fixed; top:0px; width:100%;}
</style>
 
 
<body>
    <div class="wrap">
        <div class="wrap2">
            <table class="table" cellpadding=0 cellspacing=0 border=0>                
                <thead>
                    <tr>
                        <th class="tbwid_20">구분</th>
                        <th class="tbwid_30">품목</th>
                        <th class="tbwid_10">수량</th>
                        <th class="tbwid_20">단가</th>
                        <th class="tbwid_20">구매금액</th>
                    </tr>                
                </thead>
                <tbody>
                    <tr>
                        <td class="tbwid_20">게임</th>
                        <td class="tbwid_30">배틀그라운드</td>
                        <td class="tbwid_10">2</td>
                        <td class="tbwid_20">20,000</td>
                        <td class="tbwid_20">40,000</td>
                    </tr>            
                    <tr>
                        <td>게임</td>
                        <td>오버워치</td>
                        <td>1</td>
                        <td>32,000</td>
                        <td>32,000</td>
                    </tr>
                    <tr>
                        <td>게임</td>
                        <td>스타크래프트2</td>
                        <td>2</td>
                        <td>28,000</td>
                        <td>56,000</td>
                    </tr>
                    <tr>
                        <td>게임</td>
                        <td>드래곤퀘스트11</td>
                        <td>1</td>
                        <td>40,000</td>
                        <td>40,000</td>
                    </tr>            
                    <tr>
                        <td>게임</td>
                        <td>배틀그라운드</td>
                        <td>2</td>
                        <td>20,000</td>
                        <td>40,000</td>
                    </tr>
                    <tr>
                        <td>게임</td>
                        <td>오버워치</td>
                        <td>1</td>
                        <td>32,000</td>
                        <td>32,000</td>
                    </tr>
                    <tr>
                        <td>게임</td>
                        <td>스타크래프트2</td>
                        <td>2</td>
                        <td>28,000</td>
                        <td>56,000</td>
                    </tr>
                    <tr>
                        <td>게임</td>
                        <td>드래곤퀘스트11</td>
                        <td>1</td>
                        <td>40,000</td>
                        <td>40,000</td>
                    </tr>            
                    <tr>
                        <td>게임</td>
                        <td>배틀그라운드</td>
                        <td>2</td>
                        <td>20,000</td>
                        <td>40,000</td>
                    </tr>
                    <tr>
                        <td>게임</td>
                        <td>오버워치</td>
                        <td>1</td>
                        <td>32,000</td>
                        <td>32,000</td>
                    </tr>
                    <tr>
                        <td>게임</td>
                        <td>스타크래프트2</td>
                        <td>2</td>
                        <td>28,000</td>
                        <td>56,000</td>
                    </tr>
                    <tr>
                        <td>게임</td>
                        <td>드래곤퀘스트11</td>
                        <td>1</td>
                        <td>40,000</td>
                        <td>40,000</td>
                    </tr>
                </tbody>
            </table>
        </div>
    </div>
cs

<1차 시도 - 1개의 테이블(THEAD지정)과 2개의 div를 사용>





다음으로는 2개의 테이블을 만들어서 테스트해보았다. 


테이블을 따로 만들었으나 간격만 틀릴 뿐 테이블 너비가 틀어지는 것은 동일하게 발생하였다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
<style>    
    .wrap{width:600px; height: 200px; border:1px solid #00c; padding:5px;  color:rgb(0, 0, 0); overflow: auto;}
    .wrap2{width:100%;  height: 100%; position: relative; border:1px solid #0c0;}
    .table1, .table2{border:1px solid #000; width:100%; background:#E1E1E1; text-align: center; font-size: 20px;}        
    .table1 th{background:#5c5c5c;}
    .table2 td{border:1px solid rgba(0, 0, 0, 0.596); height:20px;}
    .tbwid_10{width:10%;}
    .tbwid_20{width:20%;}
    .tbwid_30{width:30%;}
    .table1{position: fixed; top:20px; width:100%;}
</style>
 
    <div class="wrap">
        <div class="wrap2">
            <table class="table1" cellpadding=0 cellspacing=0 border=0>                                
                <tr>
                    <th class="tbwid_20">구분</th>
                    <th class="tbwid_30">품목</th>
                    <th class="tbwid_10">수량</th>
                    <th class="tbwid_20">단가</th>
                    <th class="tbwid_20">구매금액</th>
                </tr>    
            </table>                            
            <table class="table2" cellpadding=0 cellspacing=0 border=0>                                
                <tr>
                    <td class="tbwid_20">게임</th>
                    <td class="tbwid_30">배틀그라운드</td>
                    <td class="tbwid_10">2</td>
                    <td class="tbwid_20">20,000</td>
                    <td class="tbwid_20">40,000</td>
                </tr>            
                <tr>
                    <td>게임</td>
                    <td>오버워치</td>
                    <td>1</td>
                    <td>32,000</td>
                    <td>32,000</td>
                </tr>
                <tr>
                    <td>게임</td>
                    <td>스타크래프트2</td>
                    <td>2</td>
                    <td>28,000</td>
                    <td>56,000</td>
                </tr>
                <tr>
                    <td>게임</td>
                    <td>드래곤퀘스트11</td>
                    <td>1</td>
                    <td>40,000</td>
                    <td>40,000</td>
                </tr>            
                <tr>
                    <td>게임</td>
                    <td>배틀그라운드</td>
                    <td>2</td>
                    <td>20,000</td>
                    <td>40,000</td>
                </tr>
                <tr>
                    <td>게임</td>
                    <td>오버워치</td>
                    <td>1</td>
                    <td>32,000</td>
                    <td>32,000</td>
                </tr>
                <tr>
                    <td>게임</td>
                    <td>스타크래프트2</td>
                    <td>2</td>
                    <td>28,000</td>
                    <td>56,000</td>
                </tr>
                <tr>
                    <td>게임</td>
                    <td>드래곤퀘스트11</td>
                    <td>1</td>
                    <td>40,000</td>
                    <td>40,000</td>
                </tr>            
                <tr>
                    <td>게임</td>
                    <td>배틀그라운드</td>
                    <td>2</td>
                    <td>20,000</td>
                    <td>40,000</td>
                </tr>
                <tr>
                    <td>게임</td>
                    <td>오버워치</td>
                    <td>1</td>
                    <td>32,000</td>
                    <td>32,000</td>
                </tr>
                <tr>
                    <td>게임</td>
                    <td>스타크래프트2</td>
                    <td>2</td>
                    <td>28,000</td>
                    <td>56,000</td>
                </tr>
                <tr>
                    <td>게임</td>
                    <td>드래곤퀘스트11</td>
                    <td>1</td>
                    <td>40,000</td>
                    <td>40,000</td>
                </tr>                
            </table>
        </div>
    </div>
cs

<2차 시도 - 2개의 테이블과 2개의 div를 사용>





이후로도 한참을 해멨는데 결국 몇 번의 시행착오 끝에 아래와 같은 코드를 완성할 수 있었다. 



가장 중요한 부분이자 제대로 알고 있었으면 시간을 줄여줄 수 있었을 키포인트는 


fixed의 속성값은 부모 요소로부터가 아닌 viewport로부터 상속받는다는 것이다. 


즉 fixed로 설정한 순간부터 백날 width: 100% 지정해봤자 화면크기의 100%로 설정될 뿐 이었다는 것. 


그렇다고 px로 지정했다가는 확대 축소시 틀어진다. 



이를 해결하기 위해서, 즉 부모의 넓이를 상속받기 위해서는 너비값을 'width:inherit'로 지정해주어야 한다.



분명 처음에 입문할 때 접했을 내용이건만 까많게 잊고 있었다가 다시 검색하고나서 깨닫게 된 부분이다.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
<style>    
    .wrap{width:600px; height: 200px; border:1px solid #00c; padding:5px;  color:rgb(0, 0, 0);
            overflow: auto; position: relative; padding-right:20px;}    
    .table1, .table2{border:1px solid #000; width:100%; background:#E1E1E1;
                     text-align: center; font-size: 20px;}        
    .table1 th{background:#5c5c5c;}
    .table1 th,.table2 td{border:1px solid rgba(0, 0, 0, 0.596); height:20px;}    
    .wrap .table1{position: fixed; top:8px; width:inherit; z-index: 100;}
    .table2{position: absolute; top:24px; width:inherit;}
    .tbwid_10{width:10%;}
    .tbwid_20{width:20%;}
    .tbwid_30{width:30%;}
</style>
 
    <div class="wrap">        
            <table class="table1" cellpadding=0 cellspacing=0 border=0>                                
                <tr>
                    <th class="tbwid_20">구분</th>
                    <th class="tbwid_30">품목</th>
                    <th class="tbwid_10">수량</th>
                    <th class="tbwid_20">단가</th>
                    <th class="tbwid_20">구매금액</th>
                </tr>    
            </table>                            
            <table class="table2" cellpadding=0 cellspacing=0 border=0>                                
                <tr>
                    <td class="tbwid_20">게임</th>
                    <td class="tbwid_30">배틀그라운드</td>
                    <td class="tbwid_10">2</td>
                    <td class="tbwid_20">20,000</td>
                    <td class="tbwid_20">40,000</td>
                </tr>            
                <tr>
                    <td>게임</td>
                    <td>오버워치</td>
                    <td>1</td>
                    <td>32,000</td>
                    <td>32,000</td>
                </tr>
                <tr>
                    <td>게임</td>
                    <td>스타크래프트2</td>
                    <td>2</td>
                    <td>28,000</td>
                    <td>56,000</td>
                </tr>
                <tr>
                    <td>게임</td>
                    <td>드래곤퀘스트11</td>
                    <td>1</td>
                    <td>40,000</td>
                    <td>40,000</td>
                </tr>            
                <tr>
                    <td>게임</td>
                    <td>배틀그라운드</td>
                    <td>2</td>
                    <td>20,000</td>
                    <td>40,000</td>
                </tr>
                <tr>
                    <td>게임</td>
                    <td>오버워치</td>
                    <td>1</td>
                    <td>32,000</td>
                    <td>32,000</td>
                </tr>
                <tr>
                    <td>게임</td>
                    <td>스타크래프트2</td>
                    <td>2</td>
                    <td>28,000</td>
                    <td>56,000</td>
                </tr>
                <tr>
                    <td>게임</td>
                    <td>드래곤퀘스트11</td>
                    <td>1</td>
                    <td>40,000</td>
                    <td>40,000</td>
                </tr>            
                <tr>
                    <td>게임</td>
                    <td>배틀그라운드</td>
                    <td>2</td>
                    <td>20,000</td>
                    <td>40,000</td>
                </tr>
                <tr>
                    <td>게임</td>
                    <td>오버워치</td>
                    <td>1</td>
                    <td>32,000</td>
                    <td>32,000</td>
                </tr>
                <tr>
                    <td>게임</td>
                    <td>스타크래프트2</td>
                    <td>2</td>
                    <td>28,000</td>
                    <td>56,000</td>
                </tr>
                <tr>
                    <td>게임</td>
                    <td>드래곤퀘스트11</td>
                    <td>1</td>
                    <td>40,000</td>
                    <td>40,000</td>
                </tr>                
            </table>
        </div>
    </div>
cs

<최종 - 2개의 테이블과 1개의 div 사용>



table1과 table2가 동일한 넓이 값을 갖게 하기 위해서 둘다 inherit로 width를 지정해주자 드디어 원하는 모습이 나타났다. 


여기서 스크롤바의 넓이만큼 padding-right값을 지정, 고정 위치 등을 조금씩 조정해서 완성할 수 있었다.







(완성본 소스파일은 아래의 첨부파일로도 확인 가능하다.)




위의 결과화면에서 보이다시피 fixed로 틀고정을 진행하면 몇가지 제약조건이 필요하다. 


해당 화면에 테이블을 제외한 부분에 스크롤바가 없어야 하고, 문서(테이블)가 출력되는 부분을 iframe 등으로 viewport 영역을 제어해줘야 깔끔하게 자리잡을 수 있다. 


분명 이 방식보다 더 세련되고 깔끔한 방법이 있을테지만 css만으로 틀고정하는 방법으로는 쓸만하다고 생각한다.

반응형