반응형 테이블

dev | 2013-03-09

반응형 웹디자인에서 가변폭 콘텐츠는 필수이지만 가독성 문제가 항상 발생한다. 반응형 이미지나 반응형 동영상도 화면폭이 좁아지면 내용을 알아보기 힘들어 지지만 표의 경우에는 구조를 파악할 수 없게되어 이해가 더 힘들어진다. 이차원 데이터를 다루다보니 컬럼이 많을 경우에는 글자가 세로 한줄로 정렬되는 등 이해하기 쉬운 형식을 유지하기가 쉽지 않다.

이러한 문제점을 해결하기 위한 다양한 방법들이 이미 나와있다. 가장 대표적인 반응형 표는 표의 헤더를 CSS에서 새로 정의해서 선형화된 표를 보기 쉽게 하는 방법이다. 하지만 이 방법은 CSS에서 테이블 헤더 값을 지정해야 한다는 단점이 있다. 표의 내용을 스크롤되게 하는 방법도 있다. 이 방법은 브라우저 호환성에 문제가 있다. 이 밖에도 표의 데이터를 기본적으로 감추고 있다가 사용자의 요구에 의해서 보여주는 방법도 있다.

내가 시도한 방법은 첫번째 방법과 유사하지만 이를 보다 일반화 시켜서 추가적인 CSS 작업없이 사용할 수 있게 한 방법이다. 셀의 헤더를 제공하는 방법도 표의 선형화 방법을 참고하여 최대한의 정보를 제공하도록 하였다. 기본 전략은 표의 모양을 선형화하고 선형화 되어을 때 각 셀의 헤더 정보를 충실하게 제공하는 것이다.

표의 모양을 선형화 하는 방법은 매우 쉽다. 테이블 헤더와 테이블 데이터의 모양을 블록으로 바꾸고 너비를 자동으로 바꾸면 된다.

@media only screen and (max-width: 650px) {
	th, 
	td {
		display: block;
		width: auto;
	}
}

레이블을 제공하는 방법은 좀 복잡한데 기본적으로는 스크린리더와 같은 보조기기가 표를 선형화해서 사용자에게 전달하는 방법을 사용했다. 표의 헤더를 명시하는 방법은 크게 두가지가 있다. 하나는 scope 속성을 사용해서 헤더에 열이나 행을 명시해주는 방법이고 또다른 하나는 headers와 id를 이용해서 셀과 헤더를 명시적으로 연결해주는 방법이다. 여기서는 전자의 방법만을 구현했다. 일단 scope가 지정된 셀을 헤더로 판단하고 행과 열의 정보를 조합해서 셀에 data-cell-header라는 속성으로 헤더 정보를 넣어준다. 아래의 코드는 H3 사이트에 사용된 코드를 일부 개선한 코드이다.

function addCellHeader(table) {
	if (!table) {
		return false;
	}

	var trs = table.getElementsByTagName('tr');
	var trsChild;
	var grid = {};
	var cells;
	for (var i = 0, cntI = trs.length; i < cntI; i++) {
		if (!grid[i]) {
			grid[i] = {};
		}
		trsChild = trs.item(i).childNodes;
		cells = 0
		for (var j = 0, cntJ = trsChild.length; j < cntJ; j++) {
			if (trsChild[j].nodeType == 1) {
				grid[i][cells++] = trsChild[j];
			}
		}
	}

	var cellHeader = '';
	for (row in grid) {
		if (row == 0) {
			continue;
		}
		for (cell in grid[row]) {
			if (cell == 0) {
				continue;
			}
			cellHeader = grid[0][cell].innerHTML + ' - ' + grid[row][0].innerHTML
			grid[row][cell].setAttribute('data-cell-header', cellHeader);
		}
	}
}

addCellHeader(document.querySelector('.afternoon-session'));

이렇게 추가된 data-cell-header 정보를 CSS의 콘텐츠 생성 속성을 이용해서 화면에 넣어준다. 그리고 더이상 불필요해진 헤더는 감춰준다.

@media only screen and (max-width: 650px) {
	[data-cell-header]:before {
		content: attr(data-cell-header);
		display: block;
		/* 중략 */
	}
	th[scope] {
		display: none;
	}
}

핵심은 HTML의 의미와 접근성은 최대한 유지한 상태에서 어떻게 추가적인 인터페이스를 제공할 것인가이다. 그래서 추가적인 정보는 data-* 속성을 이용해서 저장하고 화면 출력은 CSS를 사용했다. headers와 id를 사용한 부분은 구현하지 않았는데 data-cell-header에 정보 넣는 방법만 추가한다면 나머지는 같은 방식으로 사용이 가능할 것이다. rowspan이나 colspan을 사용했을 경우에 헤더의 내용이 어떻게 지정되느냐에 따라 콘텐츠 이해가 원활하지 않은 경우가 있을 수 있는데 이는 콘텐츠 측면에서 고려되어야 하는 부분으로 생각된다. 전체 코드는 반응형 테이블 예제 페이지를 통해서 확인할 수 있다.

Comments

  • 퍼브르 2013-03-18

    table.morning-session [data-cell-header]:before 이런 선택자가 되는지와 content: attr(data-cell-header); 이런 값이 되는지는 처음 알았네요. 좋은 정보 감사합니다^^

  • daeyong 2013-10-09

    좋은 내용 감사합니다.

  • Jack 2014-07-09

    Thanks~

  • 몸부림 2015-11-25

    아주 많이 공부가 됬습니다 감사합니다~~

  • dada 2020-06-19

    어떻게 화면에 표현되는지 궁금한데 페이지 링크가 사라졌네요ㅠㅠ! 혹시 볼 수 있는 다른 백업링크가 있을까요?

  • dada 2020-06-19

    앗 죄송합니다 위쪽의 '시도한 방법' 의 링크가 사라졌다는 얘기였어요!

  • 신현석 2020-06-27

    "반응형 테이블 예제 페이지"에 있는 코드가 원래 사이트의 페이지와 거의 동일합니다.

Post a comment

:

: 공개 되지 않습니다. Gravatar를 표시 합니다.

:

: HTML 태그를 사용할 수 없습니다.