JS

2013년 8월 10일 토요일

Scrollable Table with Fixed Header

HTML/CSS만 사용하여 머리글(첫 행)이 고정된 표를 만들고 싶은 경우가 있다. 이것은 해결하는 방법은 여러 가지가 있는데, 그 중 하나는 표를 두 개 만드는 방법이다. 이 방법을 간단하게 설명하면, 이 방법은 머리글만 포함하는 표와 머리글 없이 내용만 포함하는 표를 각각 만들어서 위아래로 붙여 놓는 방법이다. 그러나 이렇게 할 경우 첫번째 문제는 겉보기에는 두 개의 표가 하나로 보이지만 실제로는 각각의 표가 별개의 객체로 존재하게 되기 때문에, 머리글과 내용 사이의 논리적인 연관성을 표현하기 어려워진다는 것이다. 그리고 이것보다 더 현실적인 문제도 있는데, 이 문제는 열의 너비를 강제로 지정하지 않을 경우 위의 표와 아래의 표의 열 너비가 서로 일치하지 않게 될 수 있다는 것이다.

아무튼 원하는 요구 사항은 다음과 같다.
  • 하나의 table tag를 사용할 것
  • HTML/CSS만을 사용할 것
  • 열 너비를 강제로 지정하지 않아도 사용 가능하게 할 것
  • 테이블의 border가 변경되어도 머리글이 어긋나지 않을 것
인터넷을 검색하여 이런 방법을 찾았다. http://salzerdesign.com/test/fixedTable.html
아니면 이런 글도 있는데 이건 원리를 모르겠다.
 http://www.imaputz.com/cssStuff/bigFourVersion.html

그런데 위에서 링크한 방법은 열 너비를 맞추기 위해 머리글을 중복으로 넣어야 한다. 이렇게 하는 것이 조금 걸려서 내가 나름대로 다시 만들어 보았다. 원하는 박스가 정확한 위치에 있는지 쉽게 알아 보기 위해 일부러 border를 크게 만들어둔 상태이다. 실제 사용할 경우에는 약간 고쳐서 쓰면 될 것이다. 다음 링크에서 코드와 결과를 볼 수 있다. (http://jsfiddle.net/x72V3/3/) 그리고 남아 있는 문제점은 다음과 같다.
  • container에 가로 스크롤바가 발생할 경우, 내용만 좌우로 스크롤 되고 머리글은 좌우로 스크롤 되지 않는다. 이것은 position을 absolute로 했기 때문에 그렇다. 이 문제를 해결하기 위해 conationer를 하나 더 만드는 방법이 있긴 한데, 이렇게 하면 세로 스크롤바가 이상한 곳으로 숨어 버린다. (http://jsfiddle.net/JGeMg/3/)

div#container_out {
    position: relative;
    width: 800px;
    margin: auto;
    border: 5px solid gold;
}
div#container {
    border: 0;
    margin: 0;
    padding: 0;
}
table {
    width: 100%;
    border-collapse: collaspse;
}
td, th {
    border: 10px solid green;
    padding: 5px;
}
th {
    border: 10px solid blue;
}
div#container {
    height: 300px;
    overflow-y: auto;
}
@media screen {
    div#container {
        /* margin-top = (real-box-height of caption box)
           + (real-box-height of div.background)
        */
        margin-top: 120px;
        /* header height including borders, padings */
    }
    table caption div {
        position: absolute;
        height: 50px;
        padding: 5px;
        border: 5px solid silver;
        top: 0;
    }
    thead th div.background, thead th div.fixed {
        position: absolute;
        /* top = (real-box-height of caption box) */
        top: 70px;
        height: 20px;
        /* padding = (padding of other table cells) */
        padding: 5px;
        /* border-width = (border-width of other table cells) */
        border-width: 10px;
        border-style: solid;
        border-color: blue;
    }
    thead th div.background {
        left: 0;
        right: 0;
        background-color: #aaa;
    }
    thead th div.fixed {
        border-right-width: 0;
        /* margin-left = -(border-width) */
        margin-left: -10px;
    }
    tbody tr:first-child td {
        border-top: 0
    }
    th {
        height: 0;
        padding: 0;
        border-top: 0;
        border-bottom: 0;
        vertical-align: top;
    }
}

<br />
<div id="container_out">
    <div id="container">
        <table>
            <caption>
                <div>Table 1: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer nibh risus, posuere sed euismod vel, laoreet ut quam. Sed vel.</div>
            </caption>
            <thead>
                <tr>
                    <th>
                        <div class="background"></div>
                        <div class="fixed A">A</div>
                    </th>
                    <th>
                        <div class="fixed B">B</div>
                    </th>
                    <th>
                        <div class="fixed C">C</div>
                    </th>
                    <th>
                        <div class="fixed D">D</div>
                    </th>
                </tr>
            </thead>
            <tbody>
                <tr>
                    <td>1111111111111111111</td>
                    <td>222</td>
                    <td>33333333333333333333333</td>
                    <td>444</td>
                </tr>
                <tr>
                    <td>1111111111111111111</td>
                    <td>222</td>
                    <td>33333333333333333333333</td>
                    <td>444</td>
                </tr>
                <tr>
                    <td>1111111111111111111</td>
                    <td>222</td>
                    <td>33333333333333333333333</td>
                    <td>444</td>
                </tr>
                <tr>
                    <td>1111111111111111111</td>
                    <td>222</td>
                    <td>33333333333333333333333</td>
                    <td>444</td>
                </tr>
                <tr>
                    <td>1111111111111111111</td>
                    <td>222</td>
                    <td>33333333333333333333333</td>
                    <td>444</td>
                </tr>
                <tr>
                    <td>1111111111111111111</td>
                    <td>222</td>
                    <td>33333333333333333333333</td>
                    <td>444</td>
                </tr>
                <tr>
                    <td>1111111111111111111</td>
                    <td>222</td>
                    <td>33333333333333333333333</td>
                    <td>444</td>
                </tr>
                <tr>
                    <td>1111111111111111111</td>
                    <td>222</td>
                    <td>33333333333333333333333</td>
                    <td>444</td>
                </tr>
                <tr>
                    <td>1111111111111111111</td>
                    <td>222</td>
                    <td>33333333333333333333333</td>
                    <td>444</td>
                </tr>
                <tr>
                    <td>1111111111111111111</td>
                    <td>222</td>
                    <td>33333333333333333333333</td>
                    <td>444</td>
                </tr>
                <tr>
                    <td>1111111111111111111</td>
                    <td>222</td>
                    <td>33333333333333333333333</td>
                    <td>444</td>
                </tr>
                <tr>
                    <td>1111111111111111111</td>
                    <td>222</td>
                    <td>33333333333333333333333</td>
                    <td>444</td>
                </tr>
                <tr>
                    <td>1111111111111111111</td>
                    <td>222</td>
                    <td>33333333333333333333333</td>
                    <td>444</td>
                </tr>
                <tr>
                    <td>1111111111111111111</td>
                    <td>222</td>
                    <td>33333333333333333333333</td>
                    <td>444</td>
                </tr>
            </tbody>
        </table>
    </div>
</div>

가로 스크롤바가 있는 버전의 CSS. 이건 귀찮아서 픽셀 계산 식에 대한 주석을 달지 않았다.

div#container_out {
    position: relative;
    margin: auto;
    border: 5px solid gold;
    overflow: hidden;
    width: 800px;
}
div#container {
    border: 0;
    margin: 0;
    padding: 0;
}
table {
    width: 1180px;
    border-collapse: collaspse;
}
td, th {
    border: 10px solid green;
    padding: 5px;
}
th {
    border: 10px solid blue;
}
div#container_x {
    position: relative;
    overflow-x: auto;
    width: 800px;
}
div#container {
    height: 300px;
    width: 1200px;
    overflow-y: auto;
}
@media screen {
    div#container {
        /* margin-top = (real-box-height of caption box)
           + (real-box-height of div.background)
        */
        margin-top: 120px;
        /* header height including borders, padings */
    }
    table caption div {
        position: absolute;
        width: 1180px;
        height: 50px;
        padding: 5px;
        border: 5px solid silver;
        top: 0;
    }
    thead th div.background, thead th div.fixed {
        position: absolute;
        /* top = (real-box-height of caption box) */
        top: 70px;
        height: 20px;
        /* padding = (padding of other table cells) */
        padding: 5px;
        /* border-width = (border-width of other table cells) */
        border-width: 10px;
        border-style: solid;
        border-color: blue;
    }
    thead th div.background {
        left: 0;
        right: 0;
        background-color: #aaa;
        width: 1170px;
    }
    thead th div.fixed {
        border-right-width: 0;
        /* margin-left = -(border-width) */
        margin-left: -10px;
    }
    tbody tr:first-child td {
        border-top: 0
    }
    th {
        height: 0;
        padding: 0;
        border-top: 0;
        border-bottom: 0;
        vertical-align: top;
    }
}

댓글 없음:

댓글 쓰기