1. 소개
이 절은 규범적이지 않다
많은 유형의 정보(예: 지난 1년 동안 수집된 날씨 판독값)는 두 축 그리드에서 시각적으로 표현하는 것이 가장 좋다. 여기서 행은 목록의 한 항목 (예: 날짜 및 그날 측정된 다양한 날씨 속성)을 나타내고, 열은 항목 속성의 연속적인 값 (예: 지난 1년 동안 측정된 기온)을 나타낸다.
때로는 표현을 더 이해하기 쉽게 만들기 위해, 그리드의 일부 셀이 실제 데이터 대신 부모 행/열의 설명이나 요약을 나타내는 데 사용된다. 이는 첫 번째 행 및/또는 열에 있는 셀(헤더라고 함) 또는 마지막 행 및/또는 열에 있는 셀(푸터라고 함)에서 더 자주 발생한다.
이러한 종류의 표 형식 데이터 표현은 일반적으로 테이블이라고 알려져 있다. 테이블 레이아웃은 달력이나 타임라인과 같은 다른 그리드 형태의 표현을 렌더링하는 데 남용될 수 있지만, 표현되는 정보가 데이터 테이블로서 의미가 없는 경우 작성자는 다른 레이아웃 모드를 선호해야 한다.
HTML에서 테이블의 렌더링은 오랫동안 HTML 명세에서 정의되어 왔다. 그러나 CSS에 정의된 기능과의 상호작용은 오랫동안 정의되지 않은 상태로 남아 있었다. 이 명세의 목표는 HTML 테이블과 CSS를 모두 지원하는 사용자 에이전트의 예상 동작을 정의하는 것이다.
이 문서에 정의된 일부 동작은 해당 동작이 해결하려는 문제를 해결하는 가장 논리적이거나 유용한 방식이 아닐 수 있음을 유의하라. 그러나 이러한 동작은 종종 호환성 요구 사항의 결과이며, 이 명세 편집자의 의도적인 선택이 아니다. 더 복잡한 레이아웃을 사용하려는 작성자는 CSS Grid와 같은 더 현대적인 CSS 모듈에 의존할 것을 권장한다.
테스트
다음 테스트는 이 명세에 설명된 기능의 일반적인 사용과 관련된 크래시 테스트이지만, 특정 규범적 문장에 연결되어 있지는 않다.
- colspan-zero-crash.html (라이브 테스트) (소스)
- caption-repaint-crash.html (라이브 테스트) (소스)
- caption-with-multicol-table-cell.html (라이브 테스트) (소스)
- cell-contents-with-negative-outer-size.html (라이브 테스트) (소스)
- col_span_dynamic_crash.html (라이브 테스트) (소스)
- dialog-table-crash.html (라이브 테스트) (소스)
- dynamic-recompute-baseline.html (라이브 테스트) (소스)
- dynamic_col_width_crash.html (라이브 테스트) (소스)
- dynamic_table_layout_crash.html (라이브 테스트) (소스)
- empty-tbody-after-tall-section-crash.html (라이브 테스트) (소스)
- empty_cells_crash.html (라이브 테스트) (소스)
- empty_table_with_cols.html (라이브 테스트) (소스)
- expression_width_crash.html (라이브 테스트) (소스)
- inline-splitting-crash.html (라이브 테스트) (소스)
- large-border-crash.html (라이브 테스트) (소스)
- large-col-widths.html (라이브 테스트) (소스)
- legacy_ng_mix_crash.html (라이브 테스트) (소스)
- move-oof-inside-section-row-with-borders.html (라이브 테스트) (소스)
- negative-section-distribution.html (라이브 테스트) (소스)
- negative_caption_margin.html (라이브 테스트) (소스)
- orthogonal-cell-borders.html (라이브 테스트) (소스)
- orthogonal-cell-crash.html (라이브 테스트) (소스)
- table-column-display-change-chrome-crash.html (라이브 테스트) (소스)
- textarea-intrinsic-size-crash.html (라이브 테스트) (소스)
- transition-table-row-group-crash.html (라이브 테스트) (소스)
- uninitialized_read_crash.html (라이브 테스트) (소스)
- vertical_percentage_crash.html (라이브 테스트) (소스)
- tfoot-crash-print.html (라이브 테스트) (소스)
- th-text-align.html (라이브 테스트) (소스)
- toggle-row-display-property-001.html (라이브 테스트) (소스)
- table-collapsed-row-or-column-crash.html (라이브 테스트) (소스)
테이블 레이아웃과 일반적으로 관련된 테스트
- absolute-tables-001.html (라이브 테스트) (소스)
- absolute-tables-006.html (라이브 테스트) (소스)
- anonymous-table-cell-margin-collapsing.html (라이브 테스트) (소스)
- chrome-rowspan-bug.html (라이브 테스트) (소스)
- col_removal.html (라이브 테스트) (소스)
- colspan-001.html (라이브 테스트) (소스)
- colspan-002.html (라이브 테스트) (소스)
- colspan-003.html (라이브 테스트) (소스)
- colspan-004.html (라이브 테스트) (소스)
- dynamic-rowspan-change.html (라이브 테스트) (소스)
- html-display-table.html (라이브 테스트) (소스)
- inheritance.html (라이브 테스트) (소스)
- multicol-table-collapsed-border-crash.html (라이브 테스트) (소스)
- multicol-table-crash.html (라이브 테스트) (소스)
- remove-caption-from-anon-table.html (라이브 테스트) (소스)
- remove-colgroup-from-anon-table.html (라이브 테스트) (소스)
- row-group-order.html (라이브 테스트) (소스)
- table-position-sticky-computed.html (라이브 테스트) (소스)
- table-cell-child-overflow-measure.html (라이브 테스트) (소스)
- table-cell-inline-size-box-sizing-quirks.html (라이브 테스트) (소스)
- table-cell-scroll-height.html (라이브 테스트) (소스)
- table-cell-writing-mode-computed.html (라이브 테스트) (소스)
- zero-rowspan-001.html (라이브 테스트) (소스)
- zero-rowspan-002.html (라이브 테스트) (소스)
- subpixel-table-cell-height-001.html (라이브 테스트) (소스)
- subpixel-table-width-001.html (라이브 테스트) (소스)
1.1. 값 정의
이 명세는 CSS 속성 정의 규약을 [CSS2]에서 따르며, 값 정의 구문은 [CSS-VALUES-3]에서 사용한다. 이 명세에서 정의되지 않은 값 타입은 CSS Values & Units [CSS-VALUES-3]에 정의되어 있다. 다른 CSS 모듈과의 조합은 이러한 값 타입의 정의를 확장할 수 있다.
정의에 나열된 속성별 값에 더해, 이 명세에서 정의된 모든 속성은 CSS 전역 키워드도 속성 값으로 허용한다. 가독성을 위해 이를 명시적으로 반복하지 않았다.
2. 콘텐츠 모델
2.1. 테이블 구조
CSS 테이블 모델은 HTML4 테이블 모델을 기반으로 하며, 여기서 테이블의 구조는 테이블의 시각적 레이아웃과 밀접하게 대응한다. 이 모델에서 테이블은 선택적 캡션과 임의 개수의 셀 행으로 구성된다.
또한 인접한 행과 열은 구조적으로 그룹화될 수 있으며, 이러한 그룹화는 표현에 반영될 수 있다(예: 행 그룹 주위에 테두리가 그려질 수 있음).
테이블 모델은 작성자가 문서 언어에서 열이 아니라 행을 명시적으로 지정하므로 "행 우선"이라고 한다. 모든 행이 지정된 후 열이 파생된다: 첫 번째 행의 첫 번째 셀은 첫 번째 열과 spanning이 요구하는 만큼의 다른 열에 속하며(필요하면 이를 생성한다), 그 행의 다음 셀들은 각각 다음 사용 가능한 열과 spanning이 요구하는 만큼의 다른 열에 속한다(필요하면 이를 생성한다); 다음 행의 셀들은 각각 해당 행에서 다음 사용 가능한 열(rowspan을 고려함)과 spanning이 요구하는 만큼의 다른 열에 속한다(필요하면 이를 생성한다). (§ 3.3 행/열 그리드의 치수 산정 참조).
요약하면, 테이블 모델의 인스턴스는 다음으로 구성된다:
- 다음을 포함하는 table-root:
CSS 모델은 문서 언어가 이러한 각 구성 요소에 대응하는 요소를 포함할 것을 요구하지 않는다. 미리 정의된 테이블 요소가 없는 문서 언어(XML 애플리케이션 등)의 경우, 작성자는 문서 언어 요소를 테이블 요소에 매핑해야 한다. 이는 display 속성으로 수행된다.
다음 display 값은 임의 요소에 테이블 서식 지정 규칙을 할당한다:
- table (HTML: <table>과 동등)
- 요소가 흐름 레이아웃에 배치될 때 블록 수준인 테이블을 정의한다고 지정한다.
- inline-table (HTML: <table>과 동등)
- 요소가 흐름 레이아웃에 배치될 때 인라인 수준인 테이블을 정의한다고 지정한다.
- table-row (HTML: <tr>과 동등)
- 요소가 셀의 행임을 지정한다.
- table-row-group (HTML: <tbody>와 동등)
-
요소가 일정 수의 행을 그룹화한다고 지정한다.
명시적으로 달리 언급되지 않는 한, 이 명세에서 table-row-groups에 대한 언급은 특수화된 table-header-groups 및 table-footer-groups도 포함한다.
- table-header-group (HTML: <thead>와 동등)
-
table-row-group과 같지만,
레이아웃 목적상,
이러한 첫 번째 행 그룹은 항상 다른 모든 행 및 행 그룹보다 먼저 표시된다.
테이블이 여러
display: table-header-group박스를 소유하는 경우, 첫 번째 것만 헤더로 취급되고, 나머지는display: table-row-group을 가진 것처럼 취급된다. - table-footer-group (HTML: <tfoot>와 동등)
-
table-row-group과 같지만,
레이아웃 목적상,
이러한 첫 번째 행 그룹은 항상 다른 모든 행 및 행 그룹 뒤에 표시된다.
테이블이 여러
display: table-footer-group박스를 소유하는 경우, 첫 번째 것만 푸터로 취급되고, 나머지는display: table-row-group을 가진 것처럼 취급된다. - table-column (HTML: <col>과 동등)
- 요소가 셀의 열을 설명한다고 지정한다.
- table-column-group (HTML: <colgroup>과 동등)
- 요소가 하나 이상의 열을 그룹화한다고 지정한다.
- table-cell (HTML: <td> 또는 <th>와 동등)
- 요소가 테이블 셀을 나타낸다고 지정한다.
- table-caption (HTML: <caption>과 동등)
- 테이블의 캡션을 지정한다. 테이블 캡션은 테이블 여백과 그 테두리 사이에 배치된다.
참고: 대체 요소 중 display 값이 table-row, table-row-group , table-header-group, table-footer-group, table-column, table-column-group, table-cell, 그리고 table-caption인 요소는 인라인 수준 박스로 취급된다. 이는 CSS Display 3 § 2.4 Layout-Internal Display Types: the table-* and ruby-* keywords에 따른 것이다; 대체 요소 중 display 값이 table 또는 inline-table인 요소는 자신의 외부 display 타입에 따라 동작한다. 이는 CSS Display 3 § 2.1 Outer Display Roles for Flow Layout: the block, inline, and run-in keywords에 따른 것이다. 이는 CSS 2.1에서의 중단적 변경이지만 구현과 일치한다.
2.1.1. 용어
테이블 구조 display 타입 외에도, 이 명세에서는 다음 표현도 사용된다:
- 테이블 래퍼 박스
- 자신이 소유한 각 table-caption이 차지하는 공간을 고려하기 위해 테이블 그리드 박스 주위에 생성되는 블록 컨테이너 박스.
- 테이블 그리드 박스
- 캡션을 제외한 table-internal 박스를 포함하는 블록 수준 박스.
- table-root 요소
- 내부 display 타입이 table인 요소.
- table-non-root 박스 또는 요소
- 적절한 테이블 자식 또는 table-cell 박스.
- table-track 박스 또는 요소
- table-row 또는 table-column 박스.
- table-track-group 박스 또는 요소
- table-row-group 또는 table-column-group 박스.
- 적절한 테이블 자식 박스 또는 요소
- table-track-group, table-track 또는 table-caption 박스.
- 적절한 table-row 부모 박스 또는 요소
- table-root 또는 table-row-group 박스.
- table-internal 박스 또는 요소
- table-cell, table-track 또는 table-track-group 박스.
- 표 형식 컨테이너
- table-row 또는 적절한 table-row 부모 박스.
- 연속된 박스
- 두 형제 박스 사이에, 선택적으로 공백만 포함하는 익명 인라인 외에는 끼어 있는 형제가 없으면 두 형제 박스는 연속된 것이다. 형제 박스들의 시퀀스에서 각 박스가 그 앞의 박스와 연속적이면, 그 시퀀스는 연속된 것이다.
- 테이블 그리드
-
table-root의
모든 table-rows와
table-cells의 위치를
설명하는 데 필요한 만큼의 행과 열을 포함하는
행렬. 이는 그리드 치수 산정 알고리즘에 의해 결정된다.
그리드의 각 행은 table-row에 대응할 수 있고, 각 열은 table-column에 대응할 수 있다.
- 슬롯 of the table grid
-
슬롯
(r,c)은 테이블 그리드에서 행r과 열c의 교차로 생성되는 사용 가능한 공간이다.테이블 그리드의 각 슬롯은 적어도 하나의 table-cell에 의해 덮이며(그중 일부는 익명), 많아야 둘이다. table-root의 각 table-cell은 적어도 하나의 슬롯을 덮는다.
하나보다 많은 슬롯을 덮는 table-cell은 조밀하게 그렇게 한다. 즉, 해당 셀이 덮는 슬롯 집합은 항상 네 개의 엄격하게 양수인 정수
(rowStart, colStart, rowSpan, colSpan)집합으로 설명될 수 있다. 이때 슬롯(r,c)은r이rowStart(포함)와rowStart+rowSpan(제외) 사이의 구간에 있고,c가colStart(포함)와colStart+colSpan(제외) 사이의 구간에 있는 경우에만 table-cell에 의해 덮인다;이러한 table-cell은 행
rowStart와 열colStart에서 시작한다고 한다. 또한:- table-cell이 그에 대응하는 행 (resp. 열)에서 시작하면, 그 table-cell은 table-row (resp. table-column)을 시작한다고 한다.
- table-cell의 시작 행 (resp. 열)을 그룹이 포함하면, 그 table-cell은 table-row-group (resp. table-column-group)을 시작한다고 한다.
이러한 table-cell은 위 조건에 맞는 모든 행
r과 열c에 걸친다고 한다. 또한:- table-cell이 그에 대응하는 행 (resp. 열)에 걸치면, table-cell은 table-row (resp. table-column)에 걸친다고 한다.
- 행 (resp. 열)에 대응하는 table-row (resp. table-column)은 이 행 (resp. 열)에 걸친다고 한다.
- table-row (resp. table-column)은 그리드의 모든 열 (resp. 행)에 걸친다고 한다.
- 행 (resp. 열)을 포함하는 table-row-group (resp. table-column)은 그 행 (resp. 열)에 걸친다고 한다.
- table-row-group (resp. table-column)은 그리드의 모든 열 (resp. 행)에 걸친다고 한다.
2.2. 수정
HTML 이외의 문서 언어에는 CSS 2.1 테이블 모델의 모든 요소가 포함되어 있지 않을 수 있다. 이러한 경우 테이블 모델이 작동하도록 "누락된" 요소가 있다고 가정해야 한다.
모든 table-internal 요소는 필요한 경우 자신 주위에 필요한 익명 테이블 객체를 자동으로 생성한다. table-root의 자손 중 table-internal이 아닌 모든 것은 적어도 세 개의 중첩된 객체, 즉 table/inline-table, table-row, table-cell에 대응하는 조상 집합을 테이블 안에 가져야 한다. 누락된 박스는 다음 규칙에 따라 익명 박스의 생성을 야기한다:
2.2.1. 수정 알고리즘
이 규칙들의 목적상, out-of-flow 요소는 너비와 높이가 0인 인라인 요소로 표현된다. 그 포함 블록은 그에 맞게 선택된다.
다음 단계는 세 단계로 수행된다:
-
관련 없는 박스 제거:
다음 박스는display:none인 것처럼 버려진다:- table-column의 자식.
- table-column이 아닌 table-column-group의 자식.
- 공백만 포함하고, 각각이 table-non-root 박스인 두 직접 형제 사이에 있는 익명 인라인 박스.
-
다음 기준을 모두 충족하는 익명 인라인 박스:
- 공백만 포함한다
- 표 형식 컨테이너의 첫 번째 및/또는 마지막 자식이다
- 직접 형제가 있다면, 그 형제는 table-non-root 박스이다
-
누락된 자식 래퍼 생성:
- 적절한 테이블 자식 박스가 아닌 table-root 박스의 연속된 자식들의 각 시퀀스 주위에는 익명 table-row 박스가 생성되어야 한다. !!Testcase
- table-row 박스가 아닌 table-row-group 박스의 연속된 자식들의 각 시퀀스 주위에는 익명 table-row 박스가 생성되어야 한다. !Testcase
- table-cell 박스가 아닌 table-row 박스의 연속된 자식들의 각 시퀀스 주위에는 익명 table-cell 박스가 생성되어야 한다. !Testcase
-
누락된 부모 생성:
- 부모가 table-row가 아닌 연속된 table-cell 박스들의 각 시퀀스 주위에는 익명 table-row 박스가 생성되어야 한다. Testcase
-
잘못 부모 지정된
연속된 적절한 테이블 자식 박스들의 각 시퀀스 주위에는
익명 table 또는 inline-table 박스가
생성되어야 한다.
해당 박스의 부모가 인라인, run-in, ruby 박스(또는 자식의 inlinification을 수행하는 모든 박스)이면,
inline-table 박스가 생성되어야 하며;
그렇지 않으면 table 박스여야 한다.
- table-row는 그 부모가 table-row-group도 아니고 table-root 박스도 아니면 잘못 부모 지정된 것이다.
- table-column 박스는 그 부모가 table-column-group 박스도 아니고 table-root 박스도 아니면 잘못 부모 지정된 것이다.
- table-row-group, table-column-group, 또는 table-caption 박스는 그 부모가 table-root 박스가 아니면 잘못 부모 지정된 것이다.
- 각 table-root 주위에는 익명 table-wrapper 박스가 생성되어야 한다.
그 display 타입은 inline-table 박스의 경우
inline-block이고, table 박스의 경우 block이다. 테이블 래퍼 박스는 블록 서식 컨텍스트를 확립한다. inline-table의 baseline 수직 정렬을 수행할 때는 테이블 래퍼 박스가 아니라 table-root 박스가 사용된다. 테이블 래퍼 박스의 너비는 그 안의 테이블 그리드 박스의 border-edge 너비이다. 테이블 래퍼 박스 크기에서 width 및 height에 의존하게 될 백분율은 테이블 래퍼 박스 자체가 아니라 대신 테이블 래퍼 박스의 포함 블록에 상대적이다.
block으로 전환된다.
이 변환은 테이블 수정 전에 발생한다.
테스트
- anonymous-table-ws-001.html (라이브 테스트) (소스)
- fixup-dynamic-anonymous-inline-table-001.html (라이브 테스트) (소스)
- fixup-dynamic-anonymous-inline-table-002.html (라이브 테스트) (소스)
- fixup-dynamic-anonymous-inline-table-003.html (라이브 테스트) (소스)
- fixup-dynamic-anonymous-table-001.html (라이브 테스트) (소스)
- table-model-fixup.html (라이브 테스트) (소스)
2.2.2. 수정 박스의 특성
수정 목적을 위해 생성된 익명 박스는 이 명세에서 달리 언급된 경우를 제외하고, display 타입 외에는 특정 스타일이나 기본 스타일을 받지 않는다.
이는 특히 그 계산된 배경이 “transparent”이고, 계산된 padding이 “0px”이며, 계산된 border-style이 “none”임을 의미한다.
또한 익명 박스는 박스 트리를 통해 속성 값을 상속한다는 점을 상기할 가치가 있다.
2.2.3. 예제
< div class = "row" > < div class = "cell" > George</ div > < div class = "cell" > 4287</ div > < div class = "cell" > 1998</ div > </ div >
관련 스타일은 다음과 같다:
.row{ display : table-row} .cell{ display : table-cell}
수정 후, 이는 마치 다음이 초기 HTML인 것처럼 레이아웃 박스를 생성한다:
< table > < tr > < td > George</ td > < td > 4287</ td > < td > 1998</ td > </ tr > </ table >
이 예제에서는 세 개의 table-cell
익명 박스가 행의 텍스트를 포함한다고 가정된다.
display: table-row를 가진 div 내부의 텍스트는
시각적
서식 모델에 설명된 것처럼 익명 인라인 박스에 캡슐화된다:
< div class = "inline-table" > < div class = "row" > This is the top row.</ div > < div class = "row" > This is the middle row.</ div > < div class = "row" > This is the bottom row.</ div > </ div >
.inline-table{ display : inline-table; } .row{ display : table-row; }
이는 마치 다음이 초기 HTML인 것처럼 레이아웃 박스를 생성한다:
< table > < tr > < td > This is the top row.</ td > </ tr > < tr > < td > This is the middle row.</ td > </ tr > < tr > < td > This is the bottom row.</ td > </ tr > </ table >
3. 레이아웃
3.1. 핵심 레이아웃 원칙
다른 블록 수준 박스와 달리, 테이블은 기본적으로 자신의 포함 블록을 채우지 않는다.
width가
auto로 계산되면, 테이블은 대신 fit-content가 지정된 것처럼 동작한다.
이는 대신 stretch가 지정된 것처럼 동작하는 대부분의 블록 수준 박스와 다르다.
테이블의 min-content 너비는 모든 열의 min-content 너비와 분배할 수 없는 공간을 맞추는 데 필요한 너비이다.
테이블의 max-content 너비는 모든 열의 max-content 너비와 분배할 수 없는 공간을 맞추는 데 필요한 너비이다.
테이블에 할당된 너비가 그 min-content 너비보다 크면, 사용 가능한 너비 분배 알고리즘은 그 결과에 따라 열 너비를 조정한다.
이 절은 다른 명세에 설명된 너비 계산에 적용되는 일반 목적 규칙을 재정의한다.
특히, 테이블의 margin이 0으로 설정되고 width가 auto로 설정되면,
테이블은 포함 블록을 채우도록 자동으로 크기가 정해지지 않는다.
그러나 테이블에 대한 width의 사용값이 발견되면(아래에 주어진 알고리즘 사용)
해당 규칙의 다른 부분은 적용된다.
따라서 예를 들어 왼쪽 및 오른쪽 auto margin을 사용하여 테이블을 가운데 정렬할 수 있다.
3.2. 테이블 레이아웃 알고리즘
테이블을 레이아웃하려면, 사용자 에이전트는 다음 작업을 적용해야 한다:
- 테이블에 필요한 행/열 수를 결정한다.
이는 § 3.3 행/열 그리드의 치수 산정에 설명된 단계를 실행하여 수행된다. -
[A] 행/열 그리드에 하나 이상의 슬롯이 있는 경우:
- 각 셀 슬롯이 적어도 하나의 셀에 의해 점유되도록
보장한다.
이는 § 3.4 누락된 셀 수정에 설명된 단계를 실행하여 수행된다. - 각 열의 최소 너비를 계산한다.
이는 § 3.8 테이블 측정값 계산에 설명된 단계를 실행하여 수행된다. - 테이블의 너비를 계산한다.
이는 § 3.9.1 테이블 너비 계산에 설명된 단계를 실행하여 수행된다. - 테이블의 너비를 열들 사이에 분배한다.
이는 § 3.9.3 분배 알고리즘에 설명된 단계를 실행하여 수행된다. - 테이블의 높이를 계산한다.
이는 § 3.10.1 테이블 높이 계산에 설명된 단계를 실행하여 수행된다. - 테이블의 높이를 행들 사이에 분배한다.
이는 § 3.10.5 분배 알고리즘에 설명된 단계를 실행하여 수행된다.
[B] 그렇지 않으면, 빈 테이블이 레이아웃된다:
- 테이블의 너비를 계산한다.
이는 CAPMIN의 가장 큰 값과, 테이블 그리드 박스의 계산된 너비 (테두리와 padding 포함)가 definite이면 그 값을 반환하여 수행된다 (그렇지 않으면 0 사용). - 테이블의 높이를 계산한다.
이는 모든 table-caption 높이의 합 (그 너비는 테이블 너비로 설정되며, margin은 적절히 고려됨)과 테이블 그리드 박스의 계산된 높이(테두리와 padding 포함)가 definite이면 그 값을 반환하여 수행된다(그렇지 않으면 0 사용).
- 각 셀 슬롯이 적어도 하나의 셀에 의해 점유되도록
보장한다.
- 각 table-caption 및 table-cell에 위치와 크기를 할당한다.
이는 § 3.11 셀, 캡션 및 기타 내부 테이블 박스의 배치 단계를 실행하여 수행된다.
다음 도식은 이해하기 쉽도록 알고리즘을 다른 방식으로 설명한다.
3.3. 행/열 그리드의 치수 산정
테이블 구조 절에서 언급했듯이, 테이블에 몇 개의 행과 열이 있는지는 테이블 구조에서 결정될 수 있다. 행/열 그리드의 치수 산정과 해당 그리드에서 table-cell에 slot(들)을 할당하는 것 모두 테이블에 대한 HTML 알고리즘을 실행해야 한다.
3.3.1. HTML 알고리즘
display 타입에 해당하는 HTML table 요소에서 유래하지 않은 CSS 박스는 이 알고리즘을 적용하기 전에 아래에 설명된 것처럼 그 HTML 대응 요소로 변환되어야 한다. 이 명세 레벨에서는 CSS만으로 셀의 span을 지정할 방법이 없으며, 이를 위해서는 HTML td 요소를 사용해야 한다.
HTML5 테이블 서식 지정 알고리즘을 적용한다. 이때 박스는 자신의 display 타입에 해당하는 HTML 요소처럼 동작하며, 그 박스의 원래 요소가 같은 타입의 HTML 요소인 경우에만 그 속성을 사용한다 (그렇지 않으면 아무 속성도 없는 것처럼 동작한다).
< ul class = "table" > < li >< b > One</ b >< i > 1</ i ></ li > < li >< b > Two</ b >< i > 2</ i ></ li > < li >< b > Three</ b >< i > 3</ i ></ li > </ ul > < style > ul . table { display : table ; } ul . table > li { display : table-row ; } ul . table > li > * { display : table-cell ; } </ style >
이는 다음과 같은 행/열 그리드를 생성한다
< table >< tbody > < tr > < td ></ td > < td ></ td > </ tr > < tr > < td ></ td > < td ></ td > </ tr > < tr > < td ></ td > < td ></ td > </ tr > </ tbody ></ table >
<!-- built using dom api, as this would be fixed by the html parser -->
< grid style = "display: table" > < row style = "display: table-row" > < th rowspan = "2" > 1</ th > < colgroup style = "display: table-cell" span = "2" colspan = "2" > 2</ colgroup > </ row > < tr > < td > A</ td > < td > B</ td > < td > C</ td > </ tr > </ grid >
이는 다음과 같은 행/열 그리드를 생성한다
< table > < tr > < th rowspan = "2" > 1</ th > < td > 2</ td > </ tr > < tr > < td > A</ td > < td > B</ td > < td > C</ td > </ tr > </ table >
첫 번째 행의 두 번째 셀에는 ```colspan=2```가 적용되지 않는다는 점에 유의하라. 그 원래 요소가 HTML TD 요소가 아니기 때문이다.
테스트
3.3.2. 트랙 병합
HTML 테이블 서식 지정 알고리즘은 때때로 테이블을 올바르게 레이아웃하는 데 필요한 것보다 더 많은 트랙을 생성한다. 이러한 트랙은 역사적으로 사용자 에이전트에서 무시되어 왔으므로, 다음 단계는 명세의 뒤쪽에서 이를 예외로 다루지 않기 위해 완전히 제거한다. 이 변경으로 기능을 유지하려고 노력했지만, 이 변경 때문에 문제가 발생한 것을 발견하면 이슈를 제출해 달라.
얻어진 그리드를 다음과 같이 연속된 트랙을 병합하여 반복적으로 수정한다: 얻어진 행/열 그리드에 적격 트랙이 존재하고, 해당 트랙을 명시적으로 정의하는 table-column/table-row 박스가 없으며, 해당 트랙과 이전 트랙 모두가 정확히 같은 셀 집합에 의해 span되는 동안, 테이블 레이아웃을 계산할 목적상 이 두 트랙은 하나의 단일 트랙으로 병합되어야 한다. 이를 보정하기 위해 삭제된 트랙에 걸쳤던 셀의 span을 하나 줄이고, 필요한 경우 셀이 originate하는 트랙도 마찬가지로 이동한다. (spanning-ghost-rows 테스트 케이스 참조)
자동 모드의 테이블의 경우, 모든 트랙은 트랙 병합 알고리즘의 목적상 적격 트랙이다. 고정 모드의 테이블의 경우, 그런 방식으로 병합될 수 있는 것은 행뿐이다. 즉, 모든 열은 보존된다.
마지막으로, table-root 그리드에 올바른 행과 열의 개수(매핑된 요소에서)를 할당하고, 각 table-cell에는 정확한 rowStart/colStart/rowSpan/colSpan(매핑된 요소에서)을 할당한다.
3.4. 누락된 셀 수정
다음 절은 누락된 셀이 그리드에서 해당 위치를 익명 table-cell 박스가 차지한 것처럼 렌더링된다고 말하는 CSS 2.1 문장을 명확히 하고 확장한다 ("누락된 셀"은 아직 어떤 table-cell 박스에도 덮이지 않은 행/열 그리드의 슬롯이다).
테이블의 열 수가 알려지면, 모든 table-row 박스는 span을 고려했을 때 테이블의 모든 열을 채우기에 충분한 셀을 소유하도록 수정되어야 한다. 이 조건이 충족될 때까지 새 table-cell 익명 박스를 그 행의 콘텐츠에 추가해야 한다.
테스트
3.5. 테이블 레이아웃 모드
이 절은 테이블이 레이아웃되는 방식을 수정하는 플래그를 다룬다. 테이블 레이아웃에는 세 가지 주요 플래그가 있다: table-layout, border-collapse, 그리고 caption-side. border-collapse 플래그에는 선택적 border-spacing 매개변수가 있다.
3.5.1. Table-Layout 속성
| 이름: | table-layout |
|---|---|
| 값: | auto | fixed |
| 초깃값: | auto |
| 적용 대상: | table grid 박스 |
| 상속: | no |
| 백분율: | n/a |
| 계산값: | 지정된 키워드 |
| 표준 순서: | 문법 기준 |
| 애니메이션 타입: | 불연속 |
테스트
table-layout 속성의 계산값이 fixed와 같고,
table root의 지정된 너비가
<length-percentage>, min-content 또는 fit-content 중 하나일 때마다,
table-root는 고정 모드로
레이아웃된다고 한다.
지정된 너비가 그러한 값 중 하나가 아니거나,
table-layout 속성의 계산값이 auto이면,
table-root는 자동 모드로
레이아웃된다고 한다.
table-root가 고정 모드로 레이아웃될 때, 너비 계산의 목적상 그 table-cell의 콘텐츠는 무시되고, 열 크기 산정의 집계 알고리즘은 첫 번째 행 트랙에 속하는 table-cell만 고려한다. 따라서 레이아웃은 테이블의 table-column 또는 첫 번째 행의 셀에 대해 명시적으로 지정된 값에만 의존한다; indefinite 너비를 가진 열에는 definite 너비를 가진 열을 고려한 뒤 남은 공간의 공정한 몫이 할당되며, 남은 공간이 없으면 0px이 할당된다 (§ 3.8.3 열 측정값 계산 참조).
3.5.2. Border-Collapse 속성
| 이름: | border-collapse |
|---|---|
| 값: | separate | collapse |
| 초깃값: | separate |
| 적용 대상: | table grid 박스 |
| 상속: | yes |
| 백분율: | n/a |
| 계산값: | 지정된 키워드 |
| 표준 순서: | 문법 기준 |
| 애니메이션 타입: | 불연속 |
border-collapse 속성의 값이 collapse이면,
인접한 셀의 테두리가 함께 병합되어 각 셀이 공유 테두리의 절반만 그리게 된다.
그 결과 border-spacing 같은 일부 다른 속성은
이 경우 적용되지 않는다(§ 3.6.2 collapsed-borders
모드에 적용되는 재정의 참조),
(§ 3.7 테두리 병합 참조).
이 경우 table-root는 collapsed-borders 모드로 레이아웃된다고 한다. 그렇지 않으면, table-root는 separated-borders 모드로 레이아웃된다고 한다.
테스트
- background-clip-001.html (라이브 테스트) (소스)
- box-shadow-001.html (라이브 테스트) (소스)
- collapsed-border-color-change-with-compositing.html (라이브 테스트) (소스)
- collapsed-border-remove-row-group.html (라이브 테스트) (소스)
- collapsed-scroll-overflow.html (라이브 테스트) (소스)
- border-collapse-computed.html (라이브 테스트) (소스)
- border-collapse-invalid.html (라이브 테스트) (소스)
- border-collapse-valid.html (라이브 테스트) (소스)
3.5.2.1. Border-Spacing 속성
| 이름: | border-spacing |
|---|---|
| 값: | <length>{1,2} |
| 초깃값: | 0px 0px |
| 적용 대상: | table grid 박스, border-collapse가 separate일 때 |
| 상속: | yes |
| 백분율: | n/a |
| 계산값: | 두 개의 절대 길이 |
| 표준 순서: | 문법 기준 |
| 애니메이션 타입: | 계산값 기준 |
이 길이는 separated-borders 모드에서 인접한 셀 테두리를 분리하는 거리를 지정하며, 엄격히 음수여서는 안 된다.
하나의 길이가 지정되면, 이는 가로 및 세로 간격 모두를 제공한다. 두 개가 지정되면, 첫 번째는 가로 간격을, 두 번째는 세로 간격을 제공한다.
이것이 테이블 레이아웃에 어떻게 영향을 주는지에 대한 자세한 내용은 § 3.8.1 분배할 수 없는 공간 계산을 참조하라.
테스트
3.5.3. Caption-Side 속성
| 이름: | caption-side |
|---|---|
| 값: | top | bottom |
| 초깃값: | top |
| 적용 대상: | table-caption 박스 |
| 상속: | yes |
| 백분율: | n/a |
| 계산값: | 지정된 키워드 |
| 표준 순서: | 문법 기준 |
| 애니메이션 타입: | 불연속 |
테스트
이 속성은 테이블 그리드 박스에 대한 캡션 박스의 위치를 지정한다. 값의 의미는 다음과 같다:
- top
- 캡션 박스를 테이블 그리드 박스 위에 배치한다.
- bottom
- 캡션 박스를 테이블 그리드 박스 아래에 배치한다.
캡션 박스 안에서 캡션 콘텐츠를 가로로 정렬하려면 text-align 속성을 사용한다.
이 예제에서는 caption-side 속성이 캡션을 테이블 아래에 배치한다. 캡션은 테이블의 부모만큼 넓어지고, 캡션 텍스트는 왼쪽 정렬된다.
caption {
caption-side: bottom;
width: auto;
text-align: left
}
3.6. 스타일 재정의
일부 CSS 속성은 CSS 테이블 안에서 다르게 동작한다. 다음 절들은 예외와 그 효과를 나열한다.
3.6.1. 모든 모드에 적용되는 재정의
다음 규칙은 사용 중인 레이아웃 모드와 관계없이 모든 테이블에 적용된다.
-
테이블에서 속성 position, float,
margin-*, top, right,
bottom, 그리고 left의 계산값은
table grid 박스가 아니라 table-wrapper 박스에 사용된다;
transform-style의 사용값을
flat으로 강제할 수 있는 속성( 목록 참조) 및 그 단축/장축 관련 속성도 마찬가지이다: 이 목록에는 현재 overflow, opacity, filter, clip, clip-path, isolation, mask-*, mix-blend-mode, transform-* 및 perspective가 포함된다.
지정된 값이 table grid 및/또는 wrapper 박스에 적용되지 않는 경우, 해당 박스에는 대신 unset 값이 사용된다(속성에 따라 inherit 또는 initial). - overflow 속성이 table-root 및 table-wrapper
박스에 있고, 그 값이
visible,clip또는hidden중 하나가 아니면, 무시되며 그 값이visible인 것처럼 취급된다. - table-column 및 table-column-group 박스의 모든 CSS 속성은, 이 명세가 명시적으로 지정한 경우를 제외하고 무시된다.
- margin, padding, overflow 및 z-index는 table-track 및 table-track-group 박스에서 무시된다.
- margin은 table-cell 박스에서 무시된다 (0px로 설정된 것처럼).
- background는 table-cell 박스에서 § 5.3.2 셀 배경 그리기에 설명된 특별한 배경 페인팅 알고리즘을 사용하여 칠해진다.
3.6.2. collapsed-borders 모드에 적용되는 재정의
테이블이 collapsed-borders 모드로 레이아웃될 때, 다음 규칙이 적용된다:
- padding은 table-root에서 무시된다(0px로 설정된 것처럼).
- border-spacing은 table-root에서 무시된다(0px로 설정된 것처럼).
- border-radius는 table-root와 table-non-root 박스 모두에서 무시된다(0px로 설정된 것처럼).
- table-root와 그가 소유한 table-cell 박스의 테두리 레이아웃 및 렌더링에 사용되는 값은 § 3.7 테두리 병합에 설명된 특별한 충돌 해결 알고리즘을 사용하여 결정된다.
3.7. 테두리 병합
이 전체 절은 병합된 테두리 렌더링을 합리적으로 만들기 위한 제안이다. 구현들이 매우 눈에 띄게 서로 다르기 때문에, 다른 부분보다 더 많은 논의가 필요할 것으로 예상된다. 브라우저가 이를 매우 다르게 처리하므로, 재구현 없이는 수렴이 일어날 수 없다. 이 제안의 주요 우려 사항은 가능한 한 많은 경우를 지원하면서도 테이블의 새 구현에 필요한 노력을 가능한 낮게 유지하는 것이었다.
배경: CSS+HTML은 테이블 접합부에 대해 전례 없는 테두리 모드 조합을 허용하며, 모든 경우를 올바르게 지원하기 어렵게 만든다; 실제로 일부 조합은 well-posed problems가 아니므로, 어떤 렌더링 알고리즘도 최적일 수 없다.
현재 웹 브라우저가 사용하는 테이블 렌더링 모델(배경 및 테두리)은 단순한 것(HTML)에서 매우 복잡한 것(HTML+CSS)으로 성장했기 때문에 말도 안 되는 상태이다 (버그가 많고 상호 운용되지 않으며 전혀 CSS답지 않다는 의미에서). 많은 일반적인 CSS 가정이 깨져 있으며, 렌더링은 크게 갈라진다.
이 제안은 이러한 상황을 고치는 것을 목표로 한다.
테스트
- border-collapse-double-border.html (라이브 테스트) (소스)
- border-collapse-dynamic-col-001.html (라이브 테스트) (소스)
- border-collapse-dynamic-oof.html (라이브 테스트) (소스)
- border-collapse-dynamic-section.html (라이브 테스트) (소스)
- border-collapse-empty-cell.html (라이브 테스트) (소스)
- border-collapse-rowspan-cell.html (라이브 테스트) (소스)
- collapsed-border-remove-cell.html (라이브 테스트) (소스)
border-collapsing breaking change from 2.1 [Issue #604]
3.7.1. 병합된 테두리의 충돌 해결
collapsed-borders 모드로 레이아웃될 때, 테두리를 공유하는 table-root 및 table-cell 박스는 동일한 스타일, 너비 및 색상으로 렌더링되도록(가능한 경우) 자신의 테두리를 통합하려고 시도한다. 이는 다음 알고리즘을 실행하여 수행된다.
3.7.1.1. 병합된 테두리의 충돌 해결 알고리즘
table-root의 임의의 table-cell C°에 대해:
-
border-right와의 충돌을 해결한다:
- S를 RowStart/ColumnStart 순서의 셀별로 정렬된 table-cell 테두리 스타일의 순서 있는 집합으로 둔다; 처음에는 S가 C°의 border-right 스타일만 포함하도록 둔다
- C°의 오른쪽 테두리와 자신의 왼쪽 테두리의 일부를 공유하는 모든 셀의 border-left 스타일을 집합 S에 추가한다
- 새 테두리 스타일이 S에 추가되지 않을 때까지 다음 두 명령을 반복한다:
- S의 충돌하는 테두리를 조화한다
-
border-bottom과의 충돌을 해결한다:
- S를 RowStart/ColumnStart 순서의 셀별로 정렬된 table-cell 테두리 스타일의 순서 있는 집합으로 둔다; 처음에는 S가 C°의 border-bottom 스타일만 포함하도록 둔다
- C°의 아래쪽 테두리와 자신의 위쪽 테두리의 일부를 공유하는 모든 셀의 border-top 스타일을 집합 S에 추가한다
- 새 테두리 스타일이 S에 추가되지 않을 때까지 다음 두 명령을 반복한다:
- S의 충돌하는 테두리를 조화한다
-
모든 테두리의 사용 너비를 2로 나눈다.
이 효과는 필요한 모든 곳에서 렌더링 시 보정되지만, 레이아웃 정확성을 위해 필요하다. (§ 5.3.3.1 collapsed-borders 모드에서의 변경 참조)
그런 다음, 해당 table-root에 대해:
- table-root의
border-{top,bottom,left,right}를
테이블의 테두리를 형성하는 모든 셀의 대응 테두리와(각각 독립적으로) 조화한다.
이때 table-root의 테두리 속성을 실제로 수정하지 않는다.
테이블과 셀 테두리 스타일의 명시도가 같으면, 셀 테두리 스타일을 유지한다.
이 작업이 완료되면, table-root의 border-{…}-width를 해당 테두리에 대한 조화 과정 중 발견된 최대 너비의 절반으로 설정하고, border-{…}-style을 solid로, border-{…}-color를 transparent로 설정한다.
https://jsfiddle.net/bn3d1sm4/
https://jsfiddle.net/bn3d1sm4/1/
https://jsfiddle.net/bn3d1sm4/2/
…
https://jsfiddle.net/bn3d1sm4/15/
테스트
3.7.1.2. 병합된 테두리의 조화 알고리즘
병합된 테두리의 조화에서 명시도를 변경할 것인가? [Issue #606]
순서 있는 테두리 스타일 집합(셀 C1, C2, …에 위치한 BC1, BC2, …)이 주어졌을 때, 해당 충돌하는 테두리에 대한 테두리 속성의 사용값을 결정하기 위해 다음 알고리즘을 실행한다.
- CurrentlyWinningBorderProperties를 “border: 0px none transparent”로 설정한다
-
각 테두리 BCi에 대해:
- BCi 테두리의 속성을 고려한다
-
테두리가 두 열을 분리하는 경우:
- 각 테두리 BCi에 대해: Ci 셀이 span하는 각 table-column에 대해, 있다면. BCi와 연속적으로 그려질 table-column의 모든 테두리의 테두리 속성을 고려한다.
- 각 테두리 BCi에 대해: Ci 셀이 span하는 열을 포함하는 각 table-column-group에 대해, 있다면. BCi와 연속적으로 그려질 table-column-group의 모든 테두리의 테두리 속성을 고려한다.
-
테두리가 두 행을 분리하는 경우:
- 각 테두리 BCi에 대해: Ci 셀이 span하는 각 table-row에 대해, 있다면. BCi와 연속적으로 그려질 table-column의 모든 테두리의 테두리 속성을 고려한다.
- 각 테두리 BCi에 대해: Ci 셀이 span하는 열을 포함하는 각 table-row-group에 대해, 있다면. BCi와 연속적으로 그려질 table-row-group의 모든 테두리의 테두리 속성을 고려한다.
- CurrentlyWinningBorderProperties를 반환한다
3.7.1.3. 테두리 스타일의 명시도
두 테두리 스타일이 주어졌을 때, 가장 명시도가 높은 테두리 스타일은 다음과 같은 테두리 스타일이다…
- … 하나만 border-style 값으로 "hidden"을 갖는 경우, 그 값을 갖는 것
- … CSS 픽셀로 변환했을 때 가장 큰 border-width를 갖는 것
-
… 다음 목록에서 가장 먼저 나오는 border-style을 갖는 것:
double, solid, dashed, dotted, ridge, outset, groove, inset, none
이 기준 중 어느 것도 일치하지 않으면, 두 테두리는 같은 명시도를 공유한다.
3.8. 테이블 측정값 계산
테스트
3.8.1. 분배할 수 없는 공간 계산
테이블의 분배할 수 없는 공간은 연속된 table-cell의 테두리 사이 거리 (및 table-root의 테두리와 table-cell 사이 거리)의 합이다.
두 연속된 table-cell의 테두리 사이 거리는, 있다면 border-spacing이다.
테이블 테두리와 테이블 가장자리의 셀 테두리 사이 거리는 해당 변에 대한 테이블의 padding에 관련된 border spacing 거리(있다면)를 더한 값이다.
3.8.2. 셀 측정값 계산
다음 용어는 테이블 또는 테이블 셀의 매개변수이다. 이러한 매개변수는 border-collapse 값이 다른 테이블(separate 또는 collapse) 사이의 차이를 캡슐화하여 이 절의 나머지 하위 절들이 이를 다르게 참조할 필요가 없도록 한다.
- 셀 intrinsic 오프셋
-
셀 intrinsic 오프셋은 테이블 셀의 padding 및 border 중
intrinsic 너비 계산과 관련된 부분을 포착하는 용어이다.
이는 border-left-width, padding-left, padding-right 및
border-right-width의 계산값 집합
(margin-left 및 margin-right의 0 값과 함께)이며
다음과 같이 정의된다:
- separated-borders 모드: table-cell의 계산된 가로 padding 및 border
- collapsed-borders 모드: 셀의 계산된 가로 padding 및, border 값의 경우, 셀의 사용 border-width 값(승리한 border-width의 절반)
- 테이블 intrinsic 오프셋
-
테이블 intrinsic 오프셋은 테이블의 padding 및 border 중
intrinsic 너비 계산과 관련된 부분을 포착한다.
이는 border-left-width, padding-left, padding-right 및
border-right-width의 계산값 집합
(margin-left 및 margin-right의 0 값과 함께)이며
다음과 같이 정의된다:
- separated-borders 모드: table-root의 계산된 가로 padding 및 border
- collapsed-borders 모드: 셀의 사용 border-width 값(승리한 border-width의 절반)
margin은 테이블 intrinsic 오프셋에 포함되지 않는다. margin 처리는 caption-side 속성에 의존하기 때문이다.
border collapsing 모드에서 intrinsic 오프셋 처리 [Issue #608]
- 전체 가로 border spacing
-
전체 가로 border spacing은 각 테이블에 대해 정의된다:
- 적어도 하나의 열을 포함하고 separated-borders 모드로 레이아웃된 테이블의 경우, border-spacing 속성 계산값의 가로 구성 요소에 테이블의 열 수에 1을 더한 값을 곱한 값
- 그렇지 않으면 0
- 오프셋 조정 min-width, width 및 max-width
-
- table-track 및 table-track-group 박스의 경우, width 속성의 오프셋 조정 값은 요소에 적용된 box-sizing 값과 관계없이 그 계산값이다.
-
table-cell 박스의 경우,
width 속성의 오프셋 조정 값은
box-sizing 값에 따라
셀의 border-{left|right}-width 및/또는 padding-{left|right}가 결국 차감된
그 계산값이다.
테이블이 collapsed-borders 모드로 레이아웃될 때, 차감할 border 값은 각 변에서 승리한 border 값의 절반이다 (충돌 해결 설명 참고 참조)
- outer min-content 및 outer max-content 너비
-
outer min-content 및 max-content 너비는 테이블 셀, 열 및 열 그룹에 대해 정의된다.
이 정의에서 사용되는 width, min-width, 및 max-width 값은
위에서 정의한 오프셋 조정 값이다:
- table-cell의 outer min-content 너비는
max(min-width, min-content width)이며, 셀 intrinsic 오프셋으로 조정된다. - table-column 또는 table-column-group의 outer min-content 너비는
max(min-width, width)이다. - 제약되지 않은 열 안의
table-cell의 outer max-content 너비는
max(min-width, width, min-content width, min(max-width, max-content width))이며, 셀 intrinsic 오프셋으로 조정된다. - 제약된 열 안의
table-cell의 outer max-content 너비는
max(min-width, width, min-content width, min(max-width, width))이며, 셀 intrinsic 오프셋으로 조정된다. - table-column 또는 table-column-group의 outer max-content 너비는
max(min-width, min(max-width, width))이다.
- table-cell의 outer min-content 너비는
- 백분율 기여
-
테이블 셀, 열 또는 열 그룹의 백분율 기여는
백분율인 계산값을 갖는 width 및
max-width의 계산값으로 정의된다:
min(percentage width, percentage max-width).
계산값이 백분율이 아니면, width에는0%를 사용하고, max-width에는무한백분율을 사용한다.
3.8.3. 열 측정값 계산
이 하위 절은 테이블의 각 열과 관련된 세 가지 중요한 값을 정의한다: 그 min-content 너비(이 열에 부여되는 가능한 가장 작은 너비), 그 max-content 너비(다른 제약이 적용되지 않는다면 열에 부여될 너비), 그 intrinsic 백분율 너비(열이 얻고자 하는 테이블 너비의 백분율이며, 결국 그 max-content 너비를 재정의할 수 있다).
이러한 값을 계산하기 위해 반복 알고리즘이 사용된다. 먼저, 하나보다 많은 열에 걸치는 셀을 무시하고 이러한 값이 계산된다. 그런 다음, 점차 더 많은 열에 걸치는 셀을 고려하여 이러한 값을 업데이트한다. 테이블의 모든 열에 걸쳤던 셀을 고려하면 이 알고리즘은 끝나고 값은 최종화된다.
고정 모드로 레이아웃될 때 열을 측정하는 목적상, (헤더와 푸터를 재정렬한 후) 테이블의 첫 번째 행에서 originate하는 셀만 고려된다, 있다면. 또한 셀의 min-content 및 max-content 너비는 length-percentage로 직접 지정된 경우가 아니라면 0으로 간주되며, 직접 지정된 경우에는 테이블 너비를 기준으로 해결된다(그것이 definite이면, 그렇지 않으면 0 사용).
셀의 outer min-content 너비를 계산하는 목적상, 테이블 셀의 자손 중 자신의 너비가 부모 셀 너비의 백분율에 의존하는 것은 auto 너비를 가진 것으로 간주된다. Testcase Testcase
- span이 최대 1인 셀을 기준으로 한 열의 min-content 너비
-
다음 중 가장 큰 값:
-
열에 지정된 너비:
- 그에 대응하는 table-column이 있으면(그리고 auto가 아니면), 그 outer min-content 너비
- 그에 대응하는 table-column-group이 있으면, 그 outer min-content 너비
- 또는 없으면 0
- 그 열에 span하고 colSpan이 1인 각 셀의 outer min-content 너비 (고정 모드에서는 첫 번째 행의 것만) 또는 없으면 0
-
열에 지정된 너비:
- span이 최대 1인 셀을 기준으로 한 열의 max-content 너비
-
다음 중 가장 큰 값:
- 그에 대응하는 table-column-group이 있으면, 그 outer max-content 너비
- 그에 대응하는 table-column이 있으면, 그 outer max-content 너비
- 그 열에 span하고 colSpan이 1인 각 셀의 outer max-content 너비 (고정 모드이면 첫 번째 행의 것만) 또는 그런 셀이 없으면 0
- span이 최대 1인 셀을 기준으로 한 열의 intrinsic 백분율 너비
- 백분율 기여 중 가장 큰 값: 그 열에 span하고 colSpan이 1인 각 셀, 그에 대응하는 table-column(있다면), 그리고 그에 대응하는 table-column-group(있다면)의 백분율 기여
- span이 최대 N(N > 1)인 셀을 기준으로 한 열의 min-content 너비
-
span이 최대 N-1인 셀을 기준으로 한 열의 min-content 너비와
해당 열에서 colSpan이 N인 셀들의 기여 중
가장 큰 값.
여기서 셀의 기여는 다음 단계를 수행한 결과이다:
- 기준 min-content 너비를 셀이 span하는 모든 열의, span이 최대 N-1인 셀을 기준으로 한 max-content 너비의 합으로 정의한다.
- 기준 border spacing을 셀이 span하는 모든 열 중 그 셀이 originate하는 열을 제외한 열에 대한 가로 border-spacing의 합으로 정의한다.
-
셀의 기여는 다음의 합이다:
- span이 최대 N-1인 셀을 기준으로 한 열의 min-content 너비
-
다음의 곱:
-
다음 비율:
- 해당 열의 span이 최대 N-1인 셀을 기준으로 한 max-content 너비에서 해당 열의 span이 최대 N-1인 셀을 기준으로 한 min-content 너비를 뺀 값 대
- 기준 max-content 너비에서 기준 min-content 너비를 뺀 값
- 셀의 outer min-content 너비에서 기준 min-content 너비와 기준 border spacing을 뺀 값. 이는 최소 0, 최대 기준 max-content 너비와 기준 min-content 너비의 차이로 clamp된다
-
다음 비율:
-
다음의 곱:
- span이 최대 N-1인 셀을 기준으로 한 해당 열의 max-content 너비와 기준 max-content 너비의 비율
- 셀의 outer min-content 너비에서 기준 max-content 너비와 기준 border spacing을 뺀 값, 또는 이것이 음수이면 0
- span이 최대 N(N > 1)인 셀을 기준으로 한 열의 max-content 너비
-
span이 최대 N-1인 셀을 기준으로 한
max-content 너비와 해당 열에서 colSpan이 N인 셀들의 기여 중 가장 큰 값.
여기서 셀의 기여는 다음 단계를 수행한 결과이다:
- 기준 max-content 너비를 셀이 span하는 모든 열의 span이 최대 N-1인 셀을 기준으로 한 max-content 너비의 합으로 정의한다.
- 기준 border spacing을 셀이 span하는 모든 열 중 그 셀이 originate하는 열을 제외한 열에 대한 가로 border-spacing의 합으로 정의한다.
-
셀의 기여는 다음의 합이다:
- span이 최대 N-1인 셀을 기준으로 한 열의 max-content 너비
-
다음의 곱:
- span이 최대 N-1인 셀을 기준으로 한 해당 열의 max-content 너비와 기준 max-content 너비의 비율
- 셀의 outer max-content 너비에서 기준 max-content 너비와 기준 border spacing을 뺀 값, 또는 이것이 음수이면 0
- span이 최대 N(N > 1)인 셀을 기준으로 한 열의 intrinsic 백분율 너비
-
span이 최대 N-1인 셀을 기준으로 한 열의 intrinsic 백분율 너비가 0%보다 크면,
span이 최대 N인 셀을 기준으로 한 열의 intrinsic 백분율 너비는
span이 최대 N-1인 셀을 기준으로 한 열의 intrinsic 백분율 너비와 같다.
그렇지 않으면, 해당 열에서 colSpan이 N인 셀들의 기여 중 가장 큰 값이다. 여기서 셀의 기여는 다음 단계를 수행한 결과이다:- 셀의 백분율 기여로 시작한다.
- 셀이 span하는 모든 열의 span이 최대 N-1인 셀을 기준으로 한 열의 intrinsic 백분율 너비를 뺀다. 이것이 음수 결과를 주면, 0%로 바꾼다.
-
다음 비율을 곱한다
- 열의 non-spanning max-content 너비 대
- 셀이 span하는 모든 열 중 span이 최대 N-1인 셀을 기준으로 한 열의 intrinsic 백분율 너비가 0%인 열들의 non-spanning max-content 너비의 합.
- 열의 min-content 너비
- span이 최대 N인 셀을 기준으로 한 열의 min-content 너비. 여기서 N은 테이블의 열 수이다
- 열의 max-content 너비
- span이 최대 N인 셀을 기준으로 한 열의 max-content 너비. 여기서 N은 테이블의 열 수이다
- 열의 intrinsic 백분율 너비
-
다음 중 더 작은 값:
- span이 최대 N인 셀을 기준으로 한 열의 intrinsic 백분율 너비. 여기서 N은 테이블의 열 수이다
- 100%에서 테이블의 모든 이전 열의 intrinsic 백분율 너비의 합을 뺀 값 (direction이 "ltr"이면 더 왼쪽, "rtl"이면 오른쪽) Testcase
열의 intrinsic 백분율 너비 총합을 최대 100%로 clamp한다는 것은 테이블 레이아웃 알고리즘이 열 전환에 대해 불변이 아님을 의미한다.
- 제약성
- 열은 다음 중 하나가 "auto"가 아니고 백분율도 아닌 계산된 width를 가지면 제약된다: 그에 대응하는 table-column-group(있다면), 그에 대응하는 table-column(있다면), 또는 해당 열에만 span하는 셀 중 하나.
테스트
- computing-row-measure-0.html (라이브 테스트) (소스)
- computing-row-measure-1.html (라이브 테스트) (소스)
- percentage-sizing-of-table-cell-children.html (라이브 테스트) (소스)
- percentage-sizing-of-table-cell-replaced-children-001.html (라이브 테스트) (소스)
- computing-column-measure-0.html (라이브 테스트) (소스)
- computing-column-measure-1.html (라이브 테스트) (소스)
- computing-column-measure-2.html (라이브 테스트) (소스)
3.9. 사용 가능한 너비 분배
테스트
- distribution-algo-1.html (라이브 테스트) (소스)
- distribution-algo-2.html (라이브 테스트) (소스)
- distribution-algo-min-content-guess.html (라이브 테스트) (소스)
- distribution-algo-min-content-percent-guess.html (라이브 테스트) (소스)
- distribution-algo-min-content-specified-guess.1.html (라이브 테스트) (소스)
- distribution-algo-min-content-specified-guess.html (라이브 테스트) (소스)
- td-with-subpixel-padding-vertical-rl.html (라이브 테스트) (소스)
- td-with-subpixel-padding.html (라이브 테스트) (소스)
3.9.1. 테이블 너비 계산
모든 열의 최종 너비를 결정하기 전에, 테이블 자체의 너비를 계산할 필요가 있다.
앞서 언급했듯이, 이는 일반적으로 모든 열의 선호 너비의 합에 여분을 더한 값일 것이다. 이 경우 너비 분배의 결과는 각 열에 그 선호 너비를 부여하는 것이다. 그러나 작성자가 명시적으로 다른 너비를 요청하는 몇 가지 경우와, 테이블에 필요한 너비를 부여할 수 없는 몇 가지 경우가 있다.
캡션 너비 최솟값 (CAPMIN)은 테이블 캡션의 min-content 기여 중 가장 큰 값이다.
행/열 그리드 너비 최솟값 (GRIDMIN) 너비는 모든 열의 min-content 너비의 합에 셀 간격 또는 테두리를 더한 값이다.
행/열 그리드 너비 최댓값 (GRIDMAX) 너비는 모든 열의 max-content 너비의 합에 셀 간격 또는 테두리를 더한 값이다.
테이블의 사용 min-width는 해결된 min-width, CAPMIN, 그리고 GRIDMIN 중 더 큰 값이다.
테이블의 사용 너비는 열 및 캡션 너비에 따라 다음과 같이 달라진다:
-
table-root의 width
속성이
auto가 아닌 계산값 (resolved-table-width로 해결됨)을 가지면, 사용 너비는 resolved-table-width와 테이블의 사용 min-width 중 더 큰 값이다.사용 너비가 GRIDMIN보다 크면, 여분 너비는 열에 분배되어야 한다. § 3.9 사용 가능한 너비 분배 참조. - table-root가 'width: auto'를 가지면, 사용 너비는 min(GRIDMAX, 테이블의 포함 블록 너비)와 테이블의 사용 min-width 중 더 큰 값이다.
할당 가능한 테이블 너비는 테이블의 사용 너비에서 전체 가로 border spacing(있다면)을 뺀 값이다. 이것이 우리가 열에 할당할 수 있는 너비이다.
테스트
- visibility-collapse-col-001.html (라이브 테스트) (소스)
- visibility-collapse-col-002.html (라이브 테스트) (소스)
- visibility-collapse-col-003.html (라이브 테스트) (소스)
- visibility-collapse-col-004-dynamic.html (라이브 테스트) (소스)
- visibility-collapse-col-005.html (라이브 테스트) (소스)
- visibility-collapse-colspan-001.html (라이브 테스트) (소스)
- visibility-collapse-colspan-002.html (라이브 테스트) (소스)
- visibility-hidden-col-001.html (라이브 테스트) (소스)
- visibility-hidden-nested-001.html (라이브 테스트) (소스)
- visibility-hidden-nested-002.html (라이브 테스트) (소스)
- computing-table-width-0.html (라이브 테스트) (소스)
- computing-table-width-1.html (라이브 테스트) (소스)
- table-intrinsic-size-001.html (라이브 테스트) (소스)
- table-intrinsic-size-002.html (라이브 테스트) (소스)
- table-intrinsic-size-003.html (라이브 테스트) (소스)
- table-intrinsic-size-004.html (라이브 테스트) (소스)
3.9.2. 핵심 분배 원칙
이 절은 규범적이지 않다.
3.9.2.1. 규칙
이상적으로는 각 열이 자신의 선호 너비(일반적으로 max-content 너비)를 가져야 한다. 그러나 앞서 계산된 할당 가능한 테이블 너비가 이 결과를 달성하기에 너무 크거나 너무 작을 수 있으며, 이 경우 사용자 에이전트는 너비 분배 알고리즘에 설명된 대로 임시 너비를 열에 할당해야 한다.
이 알고리즘은 열의 사용 너비를 결정할 때 세 가지 규칙을 따른다:
규칙 0: 고정 모드에서는 auto 및 백분율 열에 0픽셀의 최소 너비가 할당되며, 백분율 해결은 다른 규칙 집합을 따른다. 그 목표는 픽셀 열이 항상 자신의 선호 너비를 할당받도록 보장하는 것이다.
규칙 1: 선호 너비를 할당할 때, 지정된 백분율 열은 지정된 단위 값 열보다 높은 우선순위를 가지며, 지정된 단위 값 열은 auto 열보다 높은 우선순위를 가진다.
규칙 2: 같은 크기 지정 타입(백분율 열, 픽셀 열 또는
auto 열)을 사용하는 열은 같은 분배 방법을 따른다.
예를 들어 모두 자신의 min-content 너비를 얻거나 모두 자신의 max-content
너비를 얻는다.
이 규칙에는 하나의 예외가 있다.
percent-column에 선호 백분율 너비를 부여할 때,
그 결과가 자신의 min-content 너비보다 작은 크기가 된다면,
그 열에는 대신 자신의 min-content 너비가 할당된다.
그러나 percent-columns 그룹 전체는 여전히
선호 백분율 너비를 할당받은 것으로 간주된다.
규칙 3: 모든 열에 할당된 너비의 합은 할당 가능한 테이블 너비와 같아야 한다.
3.9.2.2. 사용 가능한 크기 지정
세 가지 타입의 열 모두에는 다음과 같은 가능한 사용 너비가 있다.
- min-content 너비:
열의 콘텐츠를 맞추는 데 필요한 크기 - min-content 너비 + delta:
min-content와 선호 너비 사이의 값 - 선호 너비:
열에 지정된 크기, 또는 줄바꿈 없이 열의 콘텐츠를 맞추는 데 필요한 크기 - 선호 너비 + delta
선호 너비보다 큰 값
분배 알고리즘은 이러한 값을 정의하고 언제 사용할지 설명한다.
3.9.3. 분배 알고리즘
테이블이 주어진 사용 너비로 레이아웃될 때, 각 열의 사용 너비는 다음과 같이 결정되어야 한다. 최종적으로는 이 알고리즘에 대한 변경 사항 중 고정 모드에 적용되는 것을 고려한 뒤이다.
먼저, 테이블의 각 열에 크기 지정 타입을 할당한다:
-
percent-column:
어떤 제약이든 백분율만 사용하도록 정의된 열 (0%와 다른 값을 가짐) -
pixel-column:
어떤 제약이든 정의된 길이만 사용하도록 정의된 열 (그리고 percent-column이 아님) -
auto-column:
그 밖의 모든 열
그런 다음, 크기 지정 타입별로 유효한 크기 지정 방법을 열에 할당하여 다음 sizing-guesses를 얻는다:
- min-content sizing-guess는 각 열에 자신의 min-content 너비가 할당되는 열 너비 할당 집합이다.
-
min-content-percentage sizing-guess는
다음과 같은 열 너비 할당 집합이다:
-
각 percent-column에는 다음 중 더 큰 값이 할당된다:
- 자신의 intrinsic 백분율 너비 × 할당 가능한 너비
- 자신의 min-content 너비.
- 그 밖의 모든 열에는 자신의 min-content 너비가 할당된다.
-
각 percent-column에는 다음 중 더 큰 값이 할당된다:
-
min-content-specified sizing-guess는
다음과 같은 열 너비 할당 집합이다:
-
각 percent-column에는 다음 중 더 큰 값이 할당된다:
- 자신의 intrinsic 백분율 너비 × 할당 가능한 너비
- 자신의 min-content 너비
- 제약된 그 밖의 모든 열에는 자신의 max-content 너비가 할당된다
- 그 밖의 모든 열에는 자신의 min-content 너비가 할당된다.
-
각 percent-column에는 다음 중 더 큰 값이 할당된다:
-
max-content
sizing-guess는 다음과 같은 열 너비 할당 집합이다:
-
각 percent-column에는 다음 중 더 큰 값이 할당된다:
- 자신의 intrinsic 백분율 너비 × 할당 가능한 너비
- 자신의 min-content 너비
- 그 밖의 모든 열에는 자신의 max-content 너비가 할당된다.
-
각 percent-column에는 다음 중 더 큰 값이 할당된다:
-
할당 가능한 테이블 너비는 항상 min-content sizing-guess의 결과인 테이블 너비보다 크거나 같다.
-
네 가지 sizing-guesses (min-content, min-content-percentage, min-content-specified, max-content)에서 각 열의 너비는 감소하지 않는 순서이다.
할당 가능한 테이블 너비가 max-content sizing-guess보다 작거나 같으면, 열의 사용 너비는 사용 가능한 너비를 경계로 하는 두 연속 sizing-guesses의 선형 결합(가중치의 합이 1인)이어야 한다.
그렇지 않으면, 열의 사용 너비는 max-content sizing-guess에서 시작하여 테이블 열에 초과 너비를 분배한 결과이다. 이는 (사용 너비에 대해) 초과 너비를 열에 분배하는 규칙에 따른다.
다음 도식은 이해하기 쉽도록 알고리즘을 다른 방식으로 설명한다.
범례
크기 지정 알고리즘: 테이블의 각 그림은 열의 크기를 지정하는 방식을 나타낸다. 왼쪽의 네 가지 경우는 명세 위에서 설명한 sizing-guesses이다: min-content, min-content-percentage, min-content-specified, 그리고 max-content. 오른쪽의 경우는 사용 가능한 크기가 네 가지 sizing-guesses 중 하나와 정확히 일치하지 않을 때 필요한 보간이다.
크기 지정 방법의 선택: 크기 지정 방법 선택은 항상 min-content sizing-guess(왼쪽 위)에서 시작한 다음, 사용 가능한 너비와 현재 사용 중인 방법이 소비하는 너비를 비교하며 진행된다. 초록색 화살표는 현재 방법을 적용한 후 분배할 여분 공간이 있을 때 따라야 하는 방향을 나타낸다. 빨간색 화살표는 현재 방법을 적용하여 너무 많은 공간을 분배했으며 되돌아가야 할 때 따라야 하는 방향을 나타낸다.
열 타입: 각 열 타입(auto, px, %)은 도식에서 자체 색상(노란색, 파란색, 주황색)을 가진다. 보간에서는: 이전 sizing-guess의 크기에서 줄어든 열은 빨간색으로 다시 칠해지고, 이전 sizing-guess의 크기에서 커진 열은 초록색으로 다시 칠해진다.
3.9.3.1. 고정 모드에서의 너비 분배 변경
이전 알고리즘에 대한 다음 변경 사항은 고정 모드에서 적용된다:
-
percent-column 및 auto-column의 min-content 너비는 0으로 간주된다
-
셀은 자신의 너비가 백분율이면 자신의 테두리와 padding 크기를 무시한다(box-sizing이 무시됨)
-
할당 가능한 테이블 너비를 기준으로 백분율을 해결할 때, 이 해결을 기준으로 한 열 너비의 합이 할당 가능한 테이블 너비를 초과한다면, 대신 열 너비의 합이 할당 가능한 테이블 너비와 정확히 일치하도록 자신의 백분율 값에 상대적으로 해결되어야 한다.
-
크기가 백분율과 픽셀 길이의 합으로 계산되는 열은 마치 두 개의 열로 계산되는 것처럼 크기가 정해져야 한다. 하나는 픽셀 값, 다른 하나는 백분율 값이다. 이는 백분율을 없애도록 해결하는 것과 다르다. 백분율 기반 열에서 너비 분배가 작동하는 방식 때문이다.
3.9.3.2. 초과 너비를 열에 분배
초과 너비를 열에 분배하기 위한 규칙은 두 가지 방식으로 호출될 수 있다:
- 테이블의 초과 너비를 그 열에 분배하여 해당 열의 사용 너비를 계산하는 경우(사용 너비 계산), 또는
- 하나보다 많은 열에 걸치는 셀의 초과 max-content 또는 min-content 너비를 그 셀이 걸치는 열의 max-content 또는 min-content 너비에 분배하는 경우(intrinsic 너비 계산).
이 두 경우의 규칙은 대체로 같지만, 약간의 차이가 있다.
이 절의 나머지 부분에서는 분배되는 너비라는 용어를 이러한 너비 중 분배되는 하나를 가리키는 데 사용하며, 초과 너비는 분배되는 너비가 그것이 분배될 열들의 분배된 너비 합을 초과하는 양을 가리키는 데 사용된다.
- intrinsic 백분율 너비가 0%이고 0이 아닌 max-content 너비를 가진 originate 셀이 있는 제약되지 않은 열이 있다면 (즉 이 규칙에 의해 커질 수 있는 열), 이 규칙에 의해 커질 수 있는 열의 분배되는 너비는 max-content 너비에 비례하여 증가한다. 따라서 전체 증가량은 초과 너비가 된다.
- 그렇지 않고, intrinsic 백분율 너비가 0%인 originate 셀이 있는 제약되지 않은 열이 있다면 (즉 이 규칙에 의해 커질 수 있는 열이며, 이전 규칙 덕분에 max-content 너비가 0이어야 함), 이 규칙에 의해 커질 수 있는 열의 분배되는 너비는 같은 양만큼 증가한다. 따라서 전체 증가량은 초과 너비가 된다.
- 그렇지 않고, intrinsic 백분율 너비가 0%이고 0이 아닌 max-content 너비를 가진 제약된 열이 있다면 (즉 이 규칙에 의해 커질 수 있는 열이며, 다른 규칙 때문에 originate 셀이 있어야 함), 이 규칙에 의해 커질 수 있는 열의 분배되는 너비는 max-content 너비에 비례하여 증가한다. 따라서 전체 증가량은 초과 너비가 된다.
- 그렇지 않고, intrinsic 백분율 너비가 0%보다 큰 열이 있다면 (즉 이 규칙에 의해 커질 수 있는 열이며, 다른 규칙 때문에 originate 셀이 있어야 함), 이 규칙에 의해 커질 수 있는 열의 분배되는 너비는 intrinsic 백분율 너비에 비례하여 증가한다. 따라서 전체 증가량은 초과 너비가 된다.
- 그렇지 않고, 그러한 열이 하나라도 있다면, originate 셀이 있는 모든 열의 분배되는 너비는 같은 양만큼 증가한다. 따라서 전체 증가량은 초과 너비가 된다.
- 그렇지 않으면, 모든 열의 분배되는 너비가 같은 양만큼 증가한다. 따라서 전체 증가량은 초과 너비가 된다.
- 너비가 지정되지 않은 열이 있으면, 초과 너비는 그러한 열에 동일하게 분배된다
- 그렇지 않고, 기본 할당에서 0이 아닌 길이 너비를 가진 열이 있으면, 초과 너비는 그러한 열 사이에서 너비에 비례하여 분배된다
- 그렇지 않고, 기본 할당에서 0이 아닌 백분율 너비를 가진 열이 있으면, 초과 너비는 그러한 열 사이에서 백분율 너비에 비례하여 분배된다
- 그렇지 않으면, 초과 너비는 크기가 0인 열에 동일하게 분배된다
테스트
3.10. 사용 가능한 높이 분배
테스트
3.10.1. 테이블 높이 계산
테이블의 높이는 행 높이의 합에 셀 간격 또는 테두리를 더한 값이다. 테이블에 auto가 아닌 값을 가진 height 속성이 있으면, 이는 테이블 그리드의 최소 높이로 취급되며, 행들의 집합적 최소 높이가 이 수치보다 작게 되는 경우 최종적으로 행 높이에 분배된다. 집합적 크기가 지정된 height보다 커지면, 지정된 height는 효과가 없다.
행의 최소 높이는 다음 중 최댓값이다:
- 그에 대응하는 table-row(있다면)의 계산된 height (definite이면, 백분율은 0px로 간주됨)
- 현재 행에만 걸치는 각 셀의 계산된 height (definite이면, 백분율은 0px로 취급됨), 그리고
- 그 행에 걸치는 셀이 요구하는 최소 높이(ROWMIN).
ROWMIN은 첫 번째 행 레이아웃 패스 이후의 행의 최소 높이의 합으로 정의된다.
테이블의 높이를 계산하려면, 따라서 모든 행에 대해 첫 번째 패스 레이아웃을 수행하고, 모든 최소 행 높이와 간격/테두리의 합을 계산한 다음, 그 값 또는 table-root에 지정된 height(min-height) 중 더 큰 값을 반환해야 한다.
테이블 높이가 결정되면, 행은 일반적으로 두 번째 레이아웃 패스를 거치며(이때 셀 높이는 더 이상 auto로 간주되지 않음), 그 다음 높이 분배가 발생하여 행 높이를 조정하고 집합적으로 테이블 높이를 충족하게 하며, 그 다음 table-cell 자손은 두 번째 레이아웃을 거칠 수 있다 (이때 백분율 높이가 해결됨).
테스트
- absolute-crash.html (라이브 테스트) (소스)
- absolute-tables-004.html (라이브 테스트) (소스)
- absolute-tables-005.html (라이브 테스트) (소스)
- absolute-tables-007.html (라이브 테스트) (소스)
- empty-table-height.html (라이브 테스트) (소스)
- max-height-table.html (라이브 테스트) (소스)
- min-height-table.html (라이브 테스트) (소스)
- min-height-table-2.html (라이브 테스트) (소스)
- min-max-size-table-content-box.html (라이브 테스트) (소스)
- table-border-paint-caption-change.html (라이브 테스트) (소스)
- percentages-grandchildren-quirks-mode-001.html (라이브 테스트) (소스)
- percentages-grandchildren-quirks-mode-002.html (라이브 테스트) (소스)
- table-as-item-cell-percentage-001.html (라이브 테스트) (소스)
- table-as-item-cell-percentage-002.html (라이브 테스트) (소스)
- table-as-item-cell-percentage-003.html (라이브 테스트) (소스)
- table-as-item-cell-percentage-004.html (라이브 테스트) (소스)
- visibility-collapse-non-rowcol-001.html (라이브 테스트) (소스)
- visibility-collapse-row-001.html (라이브 테스트) (소스)
- visibility-collapse-row-002-dynamic.html (라이브 테스트) (소스)
- visibility-collapse-row-003-dynamic.html (라이브 테스트) (소스)
- visibility-collapse-row-004.html (라이브 테스트) (소스)
- visibility-collapse-row-005.html (라이브 테스트) (소스)
- visibility-collapse-row-group-001.html (라이브 테스트) (소스)
- visibility-collapse-row-group-002.html (라이브 테스트) (소스)
- visibility-collapse-rowcol-001.html (라이브 테스트) (소스)
- visibility-collapse-rowcol-002.html (라이브 테스트) (소스)
- visibility-collapse-rowspan-001.html (라이브 테스트) (소스)
- visibility-collapse-rowspan-003-border-separate.html (라이브 테스트) (소스)
- visibility-collapse-rowspan-003.html (라이브 테스트) (소스)
- visibility-hidden-row-001.html (라이브 테스트) (소스)
- visibility-hidden-row-002.html (라이브 테스트) (소스)
3.10.2. 행 레이아웃 (첫 번째 패스)
행의 최소 높이(span 관련 높이 분배 없음)는 해당 행에서 originate하는 셀을 포함하는 가상의 linebox의 높이로 정의되며, 여러 행에 걸치는 셀은 높이가 0px인 것으로 간주된다 (그러나 올바른 baseline은 유지한다). 이 가상의 linebox에서 셀 높이는 auto로 간주되며, 그 너비(테두리와 padding 포함)는 셀이 span하는 열의 너비와 내부 간격으로 강제되지만, 그 밖의 속성은 보존된다.
이 높이를 계산하는 목적상, 자신의 높이가 부모 셀 높이의 백분율에 의존하는 테이블 셀의 자손은 (아래 절 참조) overflow가 visible, clip, 또는 으로 설정되어 있거나 대체 요소인 경우 auto 높이를 가진 것으로 간주되며, 그렇지 않으면 0px 높이를 가진 것으로 간주된다. Testcase !!Testcase
셀의 baseline은 셀 안의 첫 번째 in-flow line box의 baseline, 또는 셀 안의 첫 번째 in-flow table-row 중 더 먼저 오는 것으로 정의된다. 그러한 line box나 table-row가 없으면, baseline은 셀 박스의 content edge의 아래쪽이다.
테스트
다음은 이것이 실제로 어떻게 작동하는지 보여준다:
td { vertical-align: baseline; outline: 3px solid silver; }
img { float: left; clear: left; width: 32px; height: 32px; }
img[title] { float: none; }
<table><tr>
<td>Baseline</td>
<td>Baseline<table><tr><td>After</td></tr></table></td>
<td><table><tr><td>Baseline</td></tr></table>After</td>
<td><table align=right><tr><td>Before</td></tr></table><p>Baseline</p></td>
<td><img src="http://w3.org/favicon.ico"><p>Baseline</p></td>
<td><img src="http://w3.org/favicon.ico" title="Baseline"/><br/><img src="http://w3.org/favicon.ico" title="After"></td>
<td><img src="http://w3.org/favicon.ico"><img src="http://w3.org/favicon.ico"><!--Baseline--></td>
</tr></table>
baseline을 찾는 목적상, 스크롤 메커니즘을 가진 in-flow 박스(overflow 속성 참조)는 자신의 원점 위치로 스크롤된 것처럼 간주되어야 한다.
셀의 baseline은 셀의 아래쪽 테두리보다 아래에 위치할 수 있다. 아래 예제를 참조하라.
이 예제의 셀은 아래쪽 테두리 아래에 baseline을 가진다:
div { height: 0; overflow: hidden; }
<table>
<tr>
<td>
<div> Test </div>
</td>
</tr>
</table>
각 테이블 셀의 vertical-align 속성은 행 안에서 그 정렬을 결정한다. 각 셀의 콘텐츠는 baseline, top, middle, bottom을 가지며, 행 자체도 마찬가지이다.
테이블 셀의 컨텍스트에서 vertical-align 값은 다음 의미를 가진다:
| baseline | 셀의 baseline은 그 셀이 span하는 첫 번째 행의 다른 셀들의 baseline과 정렬된다 (셀과 행의 baseline 정의 참조). |
|---|---|
| top | 셀 박스의 위쪽이 그 셀이 span하는 첫 번째 행의 위쪽과 정렬된다. |
| bottom | 셀 박스의 아래쪽이 그 셀이 span하는 마지막 행의 아래쪽과 정렬된다. |
| middle | 셀의 중심이 그 셀이 span하는 행들의 중심과 정렬된다. |
| ... | 다른 값은 셀에 적용되지 않는다; 대신 셀은 baseline에서 정렬된다. |
'vertical-align: baseline'을 가진 모든 셀에 대해 셀 박스의 위쪽과 baseline 사이의 최대 거리가 행의 baseline을 설정하는 데 사용된다. 행에 'vertical-align: baseline'을 가진 셀이 없다면, 그 행의 baseline은 행에서 가장 낮은 셀의 아래쪽 content edge이다.
table-root의 baseline은 첫 번째 행이 있으면 그 행의 baseline이다. 그렇지 않으면 table-root의 아래쪽 content edge이다.
모호한 상황을 피하기 위해, 셀의 정렬은 다음 순서로 진행된다:
- 먼저 baseline에 정렬된 셀이 배치된다. 이는 행의 baseline을 확립한다.
- 다음으로 'vertical-align: top'인 셀이 배치된다. 이제 행은 top, 가능한 baseline, 그리고 임시 높이를 가지며, 이는 위쪽에서 지금까지 배치된 셀들의 가장 낮은 아래쪽까지의 거리이다.
- 남아 있는 셀 중 아래쪽 또는 middle에 정렬된 셀이 현재 행 높이보다 더 큰 높이를 가지는 경우, 행의 높이는 아래쪽을 낮춤으로써 그 셀들의 최댓값으로 증가한다.
- 마지막으로, 남아 있는 셀에 위치를 할당한다.
이전 알고리즘이 행의 다양한 정렬선을 어떻게 생성하는지 보여 주는 예제.
행 레이아웃 중에는 행 안 셀의 지정된 높이가 무시되었고 하나보다 많은 행에 걸치는 셀이 올바르게 크기 지정되지 않았으므로, 그 높이는 최종적으로 자신이 span한 행 집합에 분배될 필요가 있다. 이는 열 측정과 같은 알고리즘을 실행하여 수행되며, span=1 값은 (min-content의 경우) 이전 행 레이아웃의 결과 높이, 대응하는 table-row에 지정된 높이(있다면), 그리고 이 행에만 span하는 셀에 지정된 가장 큰 높이 중 가장 큰 값으로 초기화된다 (알고리즘은 그 할당 위에서 span 2의 셀을 고려하는 것으로 시작한다).
이 단계를 적용한 결과 크기가 증가한 행은 아래쪽을 낮추어 조정한다.
어떤 업데이트된 행의 아래쪽에 위치가 의존하던 셀은 각각의 행에서 다시 올바르게 배치되어야 한다.
이 시점에서, 자신이 span하는 행들의 집합적 높이보다 작은 셀 박스는 추가적인 위쪽 및/또는 아래쪽 padding을 받는다. 이를 통해 콘텐츠는 수직으로 이동하지 않지만 그 위/아래 edge는 자신이 span하는 첫 번째/마지막 행의 edge와 맞게 된다.
테스트
- dynamic-table-cell-height.html (라이브 테스트) (소스)
- percent-height-overflow-auto-in-restricted-block-size-cell.html (라이브 테스트) (소스)
- percentage-sizing-of-table-cell-007.html (라이브 테스트) (소스)
- percentage-sizing-of-table-cell-children-003.html (라이브 테스트) (소스)
- percentage-sizing-of-table-cell-children-004.html (라이브 테스트) (소스)
- percentage-sizing-of-table-cell-children-005.html (라이브 테스트) (소스)
- percentage-sizing-of-table-cell-children-006.html (라이브 테스트) (소스)
3.10.3. 행 레이아웃 (두 번째 패스)
테이블 높이가 결정되면, 필요한 경우 행/셀에 지정된 height에 사용된 백분율을 고려하여 table-row에 올바른 최소 높이를 할당하기 위해 두 번째 행 레이아웃 패스가 수행된다. 그 밖에는 첫 번째 패스 행 레이아웃에 대한 모든 지시가 적용된다 (위 참조).
그런 다음 이 두 번째 패스 이후 table-row의 새 높이 합이 이전에 결정된 테이블 높이를 채우는 데 필요한 것과 다르면, 아래에 정의된 높이 분배 알고리즘이 적용된다 아래 (행을 첫 번째 패스 최소 높이와 두 번째 패스 최소 높이 사이의 중간 크기로 줄이거나, 모든 행의 높이를 두 번째 패스 최소 높이 너머로 증가시켜 사용 가능한 공간을 채우기 위해; 어느 경우에도 이는 행의 baseline에 영향을 주지 않는다).
3.10.4. 핵심 분배 원칙
높이 분배에 대한 조사
3.10.5. 분배 알고리즘
첫 번째 단계는 각 행에 base size와 reference size를 부여하는 것이다.
그 base size는 테이블에 지정된 높이가 없었다면 가졌을 크기 (ROWMIN이 평가될 때 할당되었던 크기)이다.
그 reference size는 다음 중 가장 큰 값이다
- 초기 base height와
- 새 base height (두 번째 레이아웃 패스 중 평가된 것. 이때 rowgroup/row/cell의 지정된 높이에 사용된 백분율은 0px로 무시되는 대신 테이블 높이에 따라 해결됨).
두 번째 단계는 이러한 크기를 기준으로 각 행의 최종 높이를 계산하는 것이다.
테이블 높이가 reference size 합보다 작거나 같으면, 각 행에 할당되는 최종 높이는 올바른 전체 높이를 산출하는 base size와 reference size의 가중 평균이 된다.
그렇지 않고, 테이블이 “auto-height” 행 (크기가 콘텐츠 크기에 의해서만 결정되고 지정된 높이가 없는 행)을 하나라도 소유한다면, 각 non-auto-height 행은 reference height를 받고, auto-height 행은 reference size에 어떤 증가분을 더해 받는다. 이 증가분은 지정된 테이블 높이에 도달하기 위해 부족한 높이를 그러한 행의 수로 나눈 값과 같다.
그렇지 않으면, 모든 행은 reference size에 어떤 증가분을 더해 받는다. 이 증가분은 지정된 테이블 높이에 도달하기 위해 부족한 높이를 행의 수로 나눈 값과 같다.
어떤 업데이트된 행의 아래쪽에 위치가 의존하던 셀은 각각의 행에서 다시 올바르게 배치되어야 한다.
이 시점에서, 자신이 span하는 행들의 집합적 높이보다 작은 셀 박스는 추가적인 위쪽 및/또는 아래쪽 padding을 받는다. 이를 통해 콘텐츠는 수직으로 이동하지 않지만 그 위/아래 edge는 자신이 span하는 첫 번째/마지막 행의 edge와 맞게 된다.
테스트
- extra-height-given-to-all-row-groups-001.html (라이브 테스트) (소스)
- extra-height-given-to-all-row-groups-002.html (라이브 테스트) (소스)
- extra-height-given-to-all-row-groups-003.html (라이브 테스트) (소스)
- extra-height-given-to-all-row-groups-004.html (라이브 테스트) (소스)
- extra-height-given-to-all-row-groups-005.html (라이브 테스트) (소스)
- td-different-subpixel-padding-in-same-row-vertical-rl.html (라이브 테스트) (소스)
- td-different-subpixel-padding-in-same-row.html (라이브 테스트) (소스)
3.10.6. Table-cell 콘텐츠 레이아웃 (두 번째 패스)
table-height 분배가 끝나고, 행 높이의 합에 간격/테두리를 더한 값이 테이블 높이와 같아지면, 첫 번째 패스 행 레이아웃 규칙에 의해 백분율 높이가 무시되거나 0px로 취급된 자손을 포함한 table-cell의 콘텐츠는 (위 참조) 아래에 정의된 대로 두 번째 레이아웃 패스를 거쳐야 한다.
table-cell 콘텐츠에서 백분율 높이 해결: 높이 분배가 끝난 후 테이블과 행의 최종 크기가 결정되면, table-cell의 콘텐츠도 두 번째 레이아웃 패스를 거쳐야 한다. 여기서, 적절한 경우, 이번에는 백분율 기반 높이가 부모 셀의 사용 높이를 기준으로 해결된다.
table-cell의 직접 자식에서 백분율 높이를 해결하는 것이 적절하다는 것은 셀이 자신의 높이를 명시적으로 지정한 것으로 간주되거나 자식이 절대 위치 지정되었을 때이다. CSS 2를 참조하라.
호환성 이유로, 추가로 다음이 명확히 된다. 셀의 계산된 높이가 길이이거나, 그 table-root 조상의 계산된 높이가 길이 또는 백분율이면, 해당 백분율이 auto처럼 동작하는지 여부와 관계없이 셀은 자신의 높이를 명시적으로 지정한 것으로 간주된다.
<section style="height: var(--wrapper-height)">
<table style="height: var(--table-height)">
<tr>
<td style="height: var(--table-cell-height)">
<div style="height:100%; background:yellow">A</div>
</td>
<td style="height: var(--other-table-cell-height)">
B<br>C
</td>
</tr>
</table>
</section>
| --table-cell-height | --table-height | 결과 |
|---|---|---|
| <length> | <any> | |
| <any> | <length> | |
| <any> | <percentage> | |
| auto | auto | |
| <percentage> | auto |
--other-table-cell-height도 --wrapper-height도
알고리즘의 결과에 영향을 주지 않는다는 점에 유의하라.
이 명세의 이전 버전은 테이블이 백분율 높이를 가질 때 --wrapper-height가
고려된다고 잘못 명시했지만,
구현이 배포되었을 때 호환성 문제가 나타났고, 그 동작은 이후 특별 처리되었다.
테스트
3.11. 셀, 캡션 및 기타 내부 테이블 박스의 위치 지정
테스트
visibility:collapse가 무엇을 하는지에 대한 결정이 필요하다. [Issue #478]
테이블 그리드의 각 열 너비와 각 행 높이가 결정되면, 알고리즘의 마지막 단계는 각 table-internal 박스에 최종 위치를 할당하는 것이다.
아래에서 계산되는 width/height/left/top은 CSS Layout Box의 치수를 정의한다. 이는 CSSOM-VIEW에 정의된 offset* 속성을 통해 접근 가능하다는 뜻이다 (현재는 대응하는 HTMLElement 참조를 얻을 수 있는 css 박스로 제한됨).
table-wrapper 박스는 모든 table-non-root 박스의 margin box와 table-root border-box를 포함하도록 크기가 정해진다.
테이블 안에서 caption-side가 "top"인 임의의 table-caption의 위치는 다음과 같은 직사각형으로 정의된다:
-
width/height는:
- 레이아웃 중 캡션에 할당된 width/height
-
top 위치는 다음의 합이다:
- 이전 top 캡션을 위해 예약된 높이(마진 포함), 있다면
- 이전 캡션과 마진을 병합한 뒤 남아 있는 필요한 추가 top margin, 있다면.
-
left 위치는 다음의 합이다:
- 캡션의 왼쪽 margin
- (테이블 너비에서 캡션의 너비와 그 전체 가로 margin을 뺀 값)의 절반.
테이블 안에서 임의의 table-cell, table-track 또는 table-track-group 박스의 위치는 다음과 같은 직사각형으로 정의된다:
-
width/height는 다음의 합이다:
- 모든 span된 visible 열/행의 width/height
- 가로/세로 border-spacing에 span된 visible 열/행의 수에서 1을 뺀 값을 곱한 것
-
left/top 위치는 다음의 합이다:
- top의 경우: top 캡션을 위해 예약된 높이(마진 포함), 있다면
- 테이블의 padding-left/padding-top 및 border-left-width/border-top-width
- 모든 이전 visible 열/행의 width/height
- 가로/세로 border-spacing에 이전 visible 열/행의 수에 1을 더한 값을 곱한 것
- 한 방향에서 첫 번째 track 앞이나 마지막 track 뒤의 border-spacing은 어떤 track 또는 track-group의 너비/높이에 포함되지 않는다.
- track 사이의 border-spacing은 어떤 track의 너비/높이에도 포함되지 않지만, 두 track을 모두 span하는 track-group의 너비/높이에는 포함된다.
테이블 안에서 caption-side가 "bottom"인 임의의 table-caption의 위치는 다음과 같은 직사각형으로 정의된다:
-
width/height는:
- 레이아웃 중 캡션에 할당된 width/height
-
top 위치는 다음의 합이다:
- top 캡션을 위해 예약된 높이(마진 포함), 있다면
- 테이블의 padding-top 및 border-top-width
- 모든 visible 행의 높이
- 테이블의 padding-bottom 및 border-bottom-width
- 이전 bottom 캡션을 위해 예약된 높이(마진 포함), 있다면
- 이전 bottom 캡션과 마진을 병합한 뒤 남아 있는 필요한 추가 top margin, 있다면.
-
left 위치는 다음의 합이다:
- 캡션의 왼쪽 margin
- (테이블 너비에서 캡션의 너비와 그 전체 가로 margin을 뺀 값)의 절반.
collapse로 설정되어 있지 않으면
visible
track으로 간주된다.
4. 절대 위치 지정
4.1. table-root를 containing block으로 사용하는 경우
절대 위치 지정 요소의 containing block이 table-wrapper 박스에 의해 생성되는 경우, containing block은 테이블 마진이 적용되는 영역에 대응한다. 여기에는 테이블 테두리가 그려지는 영역과 모든 table-caption의 margin 영역이 포함된다. 그러면 offset 속성(top/right/bottom/left)은 일반적인 경우처럼 이 containing block의 대응하는 edge에서 안쪽으로의 offset을 나타낸다.
절대 위치 지정은 table 및 그 in-flow 콘텐츠의 레이아웃 이후에 발생하며, 어떤 table grid track의 크기 지정에도 기여하지 않고 테이블 그리드의 크기/구성에도 어떤 방식으로든 영향을 주지 않는다.
노란색 영역은 테이블 content edge이고, 노란색 화살표는 테이블 마진이다.
초록색 영역은 테이블 캡션이고, 초록색 화살표는 캡션 마진이다.
파란색 영역은 테이블 배경 영역이며, 더 어두운 파란색 영역은 테이블 테두리 영역이다.
검은색 영역은 테이블에 상대적으로 위치 지정된 자손이고, 화살표는 top/left/bottom/right 변위를 나타낸다.
테스트
4.2. table-internal을 containing block으로 사용하는 경우
절대 위치 지정 요소의 containing block이 table-internal에 의해 생성되는 경우, containing block은 레이아웃 중 박스에 할당될 영역의 왼쪽 위 모서리에서 시작하는 영역에 대응하지만, 그 크기는 모든 track이 visible로 간주되었을 때의 레이아웃 중 박스에 할당될 영역 중 하나로 계산된다(일부 박스에 visibility가 collapse로 설정되었는지 여부와 무관). 적절한 경우 borders 및 paddings는 포함하지 않는다.
offset 속성(top/right/bottom/left)은 일반적인 경우처럼 이 containing block의 대응하는 edge에서 안쪽으로의 offset을 나타낸다.
이는 Firefox에서만 동작한다. 하지만 향후 position:sticky를 구현하기 더 쉽게 만들 것이다. [Chrome bug] [Interop risk: Firefox bug] [Issue #858]
테스트
4.3. table-internal 박스를 non-containing block 부모로 사용하는 경우
절대 위치 지정 박스의 non-containing block 부모가 미치는 유일한 영향은 top+bottom 및/또는 left+right가 모두 auto가 되는 경우 그 static position을 정의하는 것이다.
table-cell의 경우, 절대 위치 지정 콘텐츠는 평소처럼 block layout 규칙에 따라 위치 지정된다.
table fixup 때문에, table-cell이 아닌 table-internal 박스의 자식인 절대 위치 지정 박스를 만드는 것은 불가능하다 (자세한 내용은 float 및 position에 대한 참고를 참조).
5. 렌더링
테스트
5.1. 셀의 페인트 순서
테이블 셀은 실제로 셀이 그려지게 되는 위치와 무관하게, 평소처럼 DOM 순서대로 table-root 안에서 페인트된다.
5.2. 빈 셀 렌더링(separated-borders 모드)
| 이름: | empty-cells |
|---|---|
| 값: | show | hide |
| 초깃값: | show |
| 적용 대상: | table-cell 박스 |
| 상속: | yes |
| 백분율: | n/a |
| 계산값: | 지정된 키워드 |
| 표준 순서: | 문법 기준 |
| 애니메이션 타입: | 불연속 |
테스트
collapsed-borders 모드에서는, 이 속성이 아무 효과도 없다.
separated-borders 모드에서,
이 속성의 값이 hide이면,
empty cells의 주변/뒤에 어떤 테두리나 배경도 그려지지
않는다.
빈 셀은 다음을 포함하지 않는 table-cell이다:
- floating 콘텐츠, 그리고
- white-space 속성 처리에 의해 병합되어 사라진 공백 이외의 in-flow 콘텐츠.
empty-cells:hide를 단순화할 수 있는가? [Issue #605]
예를 들어, 다음 마크업과 css를 보자:
< table > < td >< span ></ span ></ td > < td ></ td > < td >< span ></ span ></ td > </ table >
table{ width : 500 px ; height : 300 px ; empty-cells : hide; } table{ background : black; border : 10 px solid black; } td{ background : white; } table{ border-spacing : 0 px ; } td{ padding : 0 ; }
이 코드 조각의 올바른 렌더링은 여기에 묘사되어 있다:
5.3. 배경과 테두리 그리기
5.3.1. 테이블 배경과 테두리 그리기
다른 박스 타입과 달리, table 및 inline-table 박스는 자신의 전체 client rect 주변에 배경과 테두리를 페인트하지 않는다. 실제로 table caption은 시각적으로 테이블 마진과 테두리 사이에 위치해야 하며, 이는 table-root에 적용되는 다양한 효과의 그리기 영역을 수정할 필요가 있음을 의미한다.
페인팅 영역:
- table-root의 content-box를 기준으로 페인트되는 배경, 테두리 및 outline은 테이블 그리드와 그 border spacing이 차지하는 직사각형 영역을 기준으로 페인트된다.
- table-root의 padding-box를 기준으로 페인트되는 배경, 테두리 및 outline은 테이블 그리드와 그 border spacing이 차지하는 직사각형 영역을 기준으로, 각 변에서 table-root padding만큼 확장되어 페인트된다.
- table-root의 border-box를 기준으로 페인트되는 배경, 테두리 및 outline은 테이블 그리드와 그 border spacing이 차지하는 직사각형 영역을 기준으로, 각 변에서 table-root padding 및 border-width만큼 확장되어 페인트된다.
5.3.1.1. collapsed-borders 모드에서의 변경
테이블이 collapsed-borders 모드로 레이아웃될 때, 그 테두리 및 table-cell의 테두리 렌더링은 수정된다. 다음 규칙은 그 방식이 어떠한지를 설명한다.
§ 5.3 배경과 테두리 그리기에 정의된 배경 및 테두리 페인팅 규칙은 재정의되지 않는 한 계속 적용된다.
빈 테이블이 아닌 table-root의 테두리는 collapsed-borders 모드에서 페인트되지 않는다. 단, border-image 속성이 설정된 경우는 예외이다.
이 후자의 경우, 테두리는 테이블 테두리가 그 사용값이 지정하는 것보다 두 배 큰 것처럼, 그리고 그 초과분이 table-root의 padding 영역 안에 렌더링된 것처럼 그려진다.
테이블에 의해 그려지지 않더라도, 테이블 테두리는 여전히 레이아웃에서 그 공간을 차지한다.
셀은 그 공유 테두리를 렌더링한다.
테스트
5.3.2. 셀 배경 그리기
자신의 background 외에도, table-cell 박스는 자신이 속한 table-track 및 table-track-group 박스의 배경도 렌더링한다. 이는 단순히 그 배경을 상속하는 것과는 실제로 다르다. 왜냐하면 background-origin 및 background-size 계산은 실제로 셀이 아닌 grouping 박스의 bounds에서 수행되기 때문이다.
각 테이블 셀의 배경을 찾는 목적상, 서로 다른 table 박스는 겹쳐진 여섯 개의 레이어 위에 있는 것으로 생각할 수 있다. 한 레이어에 설정된 배경은 그 위의 레이어들이 투명한 배경을 가질 때만 보인다.
- 테이블 배경은 테이블에 의해 렌더링되며, 셀 배경에 영향을 주지 않는다.
- 셀이 처음으로 그리는 배경은 그 셀의 originating table-column-group의 배경이다(있다면). background-positioning의 목적상, column group은 row/column grid에서 column group에서 originate하고 column group에 속하지 않는 어떤 열에도 들어가지 않으면서 단일 셀이 차지할 수 있는 가장 큰 가능한 영역을 차지할 것으로 기대된다.
- 셀이 두 번째로 그리는 배경은 그 셀의 originating table-column의 배경이다(있다면). background-positioning의 목적상, column은 row/column grid에서 column에서 originate하고 다른 어떤 열에도 들어가지 않으면서 단일 셀이 차지할 수 있는 가장 큰 가능한 영역을 차지할 것으로 기대된다.
- 셀이 세 번째로 그리는 배경은 그 셀의 originating table-row-group의 배경이다(있다면). background-positioning의 목적상, row group은 row/column grid에서 row group에서 originate하고 row group에 속하지 않는 어떤 행에도 들어가지 않으면서 단일 셀이 차지할 수 있는 가장 큰 가능한 영역을 차지할 것으로 기대된다.
- 셀이 네 번째로 그리는 배경은 그 셀의 originating table-row의 배경이다(있다면). background-positioning의 목적상, row는 row/column grid에서 row에서 originate하고 다른 어떤 행에도 들어가지 않으면서 단일 셀이 차지할 수 있는 가장 큰 가능한 영역을 차지할 것으로 기대된다.
- 셀이 다섯 번째로 그리는 배경은 자신의 배경이다. 이는 모든 배경이 렌더링된 뒤 맨 위에 나타나는 것이다.
위 그림이 보여 주듯이, 모든 행이 같은 수의 셀을 포함하더라도,
모든 셀이 지정된 콘텐츠를 가질 수 있는 것은 아니다. separated-borders 모드에서, 그들의 empty-cells
속성 값이 hide이면,
이러한 empty cells는
전혀 렌더링되지 않는다.
마치 visibility: hidden이 그들에게 지정된 것처럼
테이블 배경이 비쳐 보이게 한다.
테스트
5.3.3. 셀 테두리 그리기
separated-borders 모드에서 table cell의 테두리는 평소처럼 렌더링된다.
5.3.3.1. collapsed-borders 모드에서의 변경
table-cell의 테두리는 collapsed-borders 모드에서 셀 테두리가 그 사용값이 지정하는 것보다 두 배 큰 것처럼, 그리고 그 초과분이 셀의 margin 영역에 렌더링된 것처럼 렌더링된다. 추가 제약으로, 테이블 edge 중 하나에 위치하지 않는 테두리의 각 변에 대해, 그 테두리는 실제 사용값이 정의하는 border-box 그리기 영역으로 실제로 clip된다. 단, border-image 속성이 설정된 경우는 예외이다.
앞서 언급한 clipping 동작을 적용한 결과 테두리가 정수가 아닌 양의 device pixel 위에서 잘리게 되면, 브라우저는 clipping 영역의 x 및 y 값을 올림함으로써 대신 clipping 영역을 device pixel에 맞추기로 결정할 수 있다. 값을 올림하면 일반적인 writing mode에서, 여러 셀 사이에서 다투는 픽셀을 얻는 셀이 실제로 가장 왼쪽 위의 셀이 된다. 이 명세에 따르면 그 셀은 다른 셀보다 더 큰 명시도를 가진다. § 5.1 셀의 페인트 순서 및 § 3.7.1.1 병합된 테두리의 충돌 해결 알고리즘 참조.
5.3.4. 테두리 스타일(collapsed-borders 모드)
border-style 값 중 일부는 테이블이 collapsed-borders 모드에 있을 때 평소와 다른 의미를 가진다. 이러한 정의는 border-style 값에 대한 기본 동작을 재정의한다.
- hidden
-
none과 같지만, 다른 모든 테두리도 억제한다(§ 3.7.1.3 테두리 스타일의 명시도 참조). - inset
-
ridge와 같다. - outset
-
groove와 같다.
5.4. visibility: collapse에 대한 렌더링
table part에 visibility: collapse가 설정되면, 렌더링은 그것이 table-cell, spanning table-cell, 또는 table-track/table-track-group에 있는지에 따라 다르게 처리된다.
테스트
5.4.1. visibility: collapse table cell 렌더링
CSS 2.2에서 말하듯이, table-cell의 visibility가 collapse로 설정되면, visibility: hidden이 설정된 것과 동일하게 렌더링된다.이는 table-cell을 포함하는 table-row에 visibility:collapse를 설정할 때 발생한다. 행을 숨기되 다른 행에 걸치는 그 셀들을 계속 표시하려면, 해당 셀에 visibility:visible을 설정하여 그 값이 상속되지 않도록 하라.
table-cell이 하나보다 많은 table-track에 걸치고, 그 table-track 중 적어도 하나가 visibility: collapse로 설정되어 있다면, 콘텐츠를 table-cell의 border-box로 clip한다. 이는 셀이 걸치는 track 중 어느 것이 collapsed되었는지와 관계없이, 셀의 왼쪽 위(rtl에서는 오른쪽 위) 콘텐츠가 계속 보인다는 뜻이다.
5.4.2. visibility: collapse table-track 또는 table-track-group 렌더링
table-track 또는 table-track-group에 visibility: collapse가 있으면, 주어진 table-track 또는 table-track-group 안의 셀이 기여하는 모든 배경, 테두리 또는 outline은 완전히 collapsed되지 않은 셀에 계속 페인트된다 (그 셀들이 여러 track에 걸쳤기 때문이다).테스트
- visibility-collapse-colspan-003.html (라이브 테스트) (소스)
- visibility-collapse-colspan-crash.html (라이브 테스트) (소스)
- visibility-collapse-rowspan-002-border-separate.html (라이브 테스트) (소스)
- visibility-collapse-rowspan-002.html (라이브 테스트) (소스)
- visibility-collapse-rowspan-004-dynamic.html (라이브 테스트) (소스)
- visibility-collapse-rowspan-005.html (라이브 테스트) (소스)
- visibility-collapse-rowspan-crash.html (라이브 테스트) (소스)
6. 분할
6.1. fragmentainer 사이에서 나누기
테이블을 분할할 때, 사용자 에이전트는 그 행을 span하는 셀이 이후의 어떤 행도 span하지 않고, 그 높이가 fragmentainer의 높이와 너비 모두보다 적어도 두 배 작으면 테이블 행을 분할되지 않은 상태로 보존하려고 시도해야 한다. 다른 행은 자유롭게 분할 가능하다고 한다.
테이블이 fragmentainer 안에 완전히 들어가지 않고, 적어도 하나의 행은 fragmentainer 안에 완전히 들어갔으며, fragmentainer 안에 들어가지 않는 첫 번째 행이 자유롭게 분할 가능하지 않은 경우, 사용자 에이전트는 overflow 지점 이전과 그 지점에 있는 행 사이에 일정한 세로 간격을 삽입하여 두 행이 형제 fragmentainer에 분리되어 배치되도록 해야 한다. 분할에 header와 footer의 반복이 필요하고 footer가 반복되는 경우, footer는 fragmentainer의 마지막 행 바로 뒤에 와야 하며, 세로 간격은 반복된 footer 뒤에 삽입되어야 한다.
현재 fragmentainer에 완전히 들어가는 행이 없거나 fragmentainer 안에 들어가지 않는 첫 번째 행이 자유롭게 분할 가능한 경우, 사용자 에이전트는 fragmentainer의 남은 높이를 모두 그 행의 셀들에 할당하고, 각 셀 안에 가능한 한 많은 콘텐츠를 독립적으로 맞춘 다음, 다음 fragment로 나누고 각 셀의 콘텐츠를 이전 fragment에서 중단된 위치부터 시작해야 한다 (계속되는 fragment에서는 위쪽 테두리를 다시 칠해서는 안 된다).
break-before 또는 break-after가 table-row-group 또는 table-row 박스에 적용되면, 사용자 에이전트는 나누기 지점의 앞과 뒤에 있는 행 사이에 일정한 세로 간격을 삽입하여 속성 값이 요구하는 대로 두 행이 형제 fragmentainer에 분리되어 배치되도록 해야 한다. 분할에 header와 footer의 반복이 필요하고 footer가 반복되는 경우, footer는 fragmentainer의 마지막 행 바로 뒤에 와야 하며, 세로 간격은 반복된 footer 뒤에 삽입되어야 한다.
6.2. 페이지 사이에서 header 반복
문서를 페이지 매체로 렌더링할 때, 사용자 에이전트는 페이지가 테이블의 fragmentainer이고, header/footer에 avoid break-inside가 적용되어 있으며, 이를 위해 필요한 높이가 페이지 높이의 2/4보다 작고 (header 행은 최대 1/4, footer 행은 최대 1/4), 그 페이지에서 어떤 행도 두 번 표시되지 않게 된다면, 테이블이 span하는 각 페이지에서 header 행과 footer 행을 반복해야 한다.
header 행이 반복될 때, 사용자 에이전트는 공간을 남겨 두고 필요한 경우 테이블 위쪽 테두리를 렌더링해야 한다. footer 행과 테이블 아래쪽 테두리에도 동일하게 적용된다.
사용자 에이전트는 이 동작을 더 많은 분할 컨텍스트로 확장하기로 결정할 수 있다. 예를 들어 페이지뿐 아니라 열 사이에서도 header/row를 반복할 수 있다. 정적 문서를 렌더링하는 사용자 에이전트가 이러한 동작을 채택할 가능성이 더 높지만, 명세상 필수는 아니다.
7. 보안 고려 사항
CSS Tables를 사용해도 완화해야 할 보안 위험은 발생하지 않는다.
8. 개인정보 보호 고려 사항
CSS Tables를 사용해도 완화해야 할 개인정보 보호 위험은 발생하지 않는다.
9. 추적 중인 버그 목록
이 절은 규범적이지 않다.
10. 부록
10.1. CSS 및 HTML 속성 간 매핑
HTML4의 기본 스타일 시트는 그 모델이 css 속성과 값에 어떻게 매핑되는지를 보여 준다:
table{ display : table} thead{ display : table-header-group} tbody{ display : table-row-group} tfoot{ display : table-footer-group} tr{ display : table-row} td, th{ display : table-cell} colgroup{ display : table-column-group} col{ display : table-column} caption{ display : table-caption} table, thead, tbody, tfoot, tr, td, th, colgroup, col, caption{ box-sizing : border-box; } thead, tfoot{ break-inside : avoid} table{ box-sizing : border-box; border-spacing : 2 px ; border-collapse : separate; text-indent : initial; } thead, tbody, tfoot, table > tr{ vertical-align : middle; } tr, td, th{ vertical-align : inherit; } td, th{ padding : 1 px ; } th{ font-weight : bold; } table, td, th{ border-color : gray; } thead, tbody, tfoot, tr{ border-color : inherit; } table[ frame=box i], table[ frame=border i], table[ frame=hsides i], table[ frame=above i], table[ frame=below i], table[ frame=vsides i], table[ frame=lhs i], table[ frame=rhs i] { border : 1 px solid inset; } table:is ([ rules=all i], [ rules=rows i], [ rules=cols i], [ rules=groups i], [ rules=none i]) { border-collapse : collapse; border-style : hidden; } table:is ([ rules=all i], [ rules=rows i], [ rules=cols i], [ rules=groups i], [ rules=none i]), table:is ([ rules=all i], [ rules=rows i], [ rules=cols i], [ rules=groups i], [ rules=none i]) >:is ( thead, tbody, tfoot) > tr >:is ( th, td) { border-color : black; } table[ border=$border] /* if(parseInt($border) > 0) */ { border : /*(parseInt($border) * 1px)*/ outsetrgb ( 128 , 128 , 128 ); } table[ border=$border] >:is ( thead, tbody, tfoot) > tr >:is ( th, td) /* if(parseInt($border) > 0) */ { border : 1 px insetrgb ( 128 , 128 , 128 ); } table[ rules=all i] >:is ( thead, tbody, tfoot) > tr >:is ( th, td) { border : 1 px solid grey; } table[ rules=rows i] >:is ( thead, tbody, tfoot) > tr >:is ( th, td) { border : 1 px solid grey; border-left : none; border-right : none; } table[ rules=cols i] >:is ( thead, tbody, tfoot) > tr >:is ( th, td) { border : 1 px solid grey; border-top : none; border-bottom : none; } table[ rules=none i] >:is ( thead, tbody, tfoot) > tr >:is ( th, td) { border : none; } table[ rules=groups i] >:is ( thead, tbody, tfoot) { border-top-width : 1 px ; border-top-style : solid; border-bottom-width : 1 px ; border-bottom-style : solid; } table[ rules=groups i] > colgroup{ border-left-width : 1 px ; border-left-style : solid; border-right-width : 1 px ; border-right-style : solid; } table[ frame=box i], table[ frame=border i], table[ frame=hsides i], table[ frame=above i], table[ frame=below i], table[ frame=vsides i], table[ frame=lhs i], table[ frame=rhs i] { border-style : outset; } table[ frame=below i], table[ frame=vsides i], table[ frame=lhs i], table[ frame=rhs i] { border-top-style : hidden; } table[ frame=above i], table[ frame=vsides i], table[ frame=lhs i], table[ frame=rhs i] { border-bottom-style : hidden; } table[ frame=hsides i], table[ frame=above i], table[ frame=below i], table[ frame=rhs i] { border-left-style : hidden; } table[ frame=hsides i], table[ frame=above i], table[ frame=below i], table[ frame=rhs i] { border-right-style : hidden; } table[ cellpadding=$x] >:is ( thead, tbody, tfoot) > tr >:is ( th, td) /* if(parseInt($x)>0) */ { padding : /*(parseInt($x) * 1px)*/ ; } table[ cellspacing=$x] /* if(parseInt($x)>0) */ { border-spacing : /*(parseInt($x) * 1px)*/ ; } table[ width=$w] /* if(parseInt($w) > 0) */ { width : /*(parseInt($w) * 1px)*/ ; } table[ width=$w] /* if($w matches /(+|-|)([0-9]+([.][0-9]+|)|([.][0-9]+))[%]/) */ { width : /*(parseInt($w) * 1px)*/ ; } table[ height=$h] /* if(parseInt($h) > 0) { height: /*(parseInt($h) * 1px)*/ ; } table[ height=$h] /* if($h matches /(+|-|)([0-9]+([.][0-9]+|)|([.][0-9]+))[%]/) */ { height : /*(parseInt($h) * 1px)*/ ; } table[ bordercolor=$color] { border-color : /*parseHTMLColor($color)*/ ; } table[ bordercolor] >:is ( tbody, thead, tfoot, tr, colgroup, col), table[ bordercolor] >:is ( tbody, thead, tfoot) > tr, table[ bordercolor] >:is ( tbody, thead, tfoot) > tr >:is ( td, th), table[ bordercolor] > tr >:is ( td, th) table[ bordercolor] > colgroup > col) { border-color : inherit; } table[ bgcolor=$color] { background-color : /*parseHTMLColor($color)*/ ; } table[ align=left i] { float : left; } table[ align=right i] { float : right; } table[ align=center i] { margin-left : auto; margin-right : auto; } caption[ align=bottom i] { caption-side : bottom; } :is ( thead, tbody, tfoot, tr, td, th)[ valign=top i] { vertical-align : top; } :is ( thead, tbody, tfoot, tr, td, th)[ valign=middle i] { vertical-align : middle; } :is ( thead, tbody, tfoot, tr, td, th)[ valign=bottom i] { vertical-align : bottom; } :is ( thead, tbody, tfoot, tr, td, th)[ valign=baseline i] { vertical-align : baseline; } :is ( thead, tbody, tfoot, tr, td, th)[ align=absmiddle i] { text-align : center; } :is ( colgroup, col, thead, tbody, tfoot, tr, td, th)[ hidden] { visibility : collapse; } :is ( td, th)[ nowrap] { white-space : nowrap; } :is ( td, th)[ nowrap][ width=$w] /* if(quirksMode && parseInt($w) > 0) */ { white-space : normal; }
테스트
11. (누락된 절을 위한 링크 위치)
12. 변경 사항
2019년 7월 27일 작업 초안 이후의 중요한 변경 사항:
- paged media 및 continuous media 용어를 [MEDIAQUERIES-5]에서 참조했다.
- :matches() 의사 클래스에 대한 언급을 :is()로 대체했다.
- 외부 table 요소가 자신의 outer display type에 따라 동작함을 명확히 했다.
- clip이 table-root 및 table-wrapper 박스에 적용될 수 있도록 허용했다.
- Web Platform Test 커버리지를 추가했다.