Plain tabular makes every column as wide as its natural content. So the moment you want a table to fit the text width exactly, or to line up equal-width columns of flowing prose, it fights you. The packages that solve this are **tabularx (stretch columns to hit a target width), tabulary (apportion width by how much content each column holds), and the increasingly standard tabularray** (the tblr environment — a modern package that controls everything about a table through key–value options). This page covers how the three differ, with a worked example of each.
The width problem
In tabular, the l, c, and r columns never wrap, and the p{width} column wraps but forces you to work out the width yourself. With three columns that should fill the text width \textwidth exactly, guessing p{0.3\textwidth} and so on leaves you off by the width of the rules and the inter-column space (\tabcolsep) — so the table overflows or comes up short.
So turn the problem around. Fix the width first and let the columns adapt — that is tabularx. Apportion the width automatically by how much content each column holds — that is tabulary. Both are long-standing packages by David Carlisle (the tabularx one ships in the tools bundle), loaded with \usepackage{tabularx} or \usepackage{tabulary}.
tabularx — the X column stretches to a fixed width
Unlike tabular, the tabularx environment takes the table’s target width as its first argument: \begin{tabularx}{width}{column spec}. The column spec may use the new column type **X**, a p-style column that automatically stretches or shrinks to fill the leftover width. When there are several X columns, they share the available width equally.
The mechanism is a little unusual: tabularx finds the widths by typesetting the table several times. It first sets the table with each X column at the full target width (so the table is too wide), divides the excess by the number of X columns, narrows each one by that much, and resets — iterating until it converges. In the end X is replaced by whatever column \tabularxcolumn defines; its default is:
\newcommand{\tabularxcolumn}[1]{p{#1}}So X is by default a top-aligned paragraph column. To center its contents vertically, redefine \renewcommand{\tabularxcolumn}[1]{m{#1}}. The contents of an X column are justified by default; to make them flush-left instead, prefix the column with **>{\raggedright\arraybackslash}X. The key here is \arraybackslash**: \raggedright, \centering, and \raggedleft redefine what \\ means and clash with the row-terminating \\ of a table, so you place \arraybackslash after those declarations to restore \\ as the row terminator.
If you reuse the same prefix, \newcolumntype lets you give it a one-letter alias for readability. The example below sets column 1 as a natural-width left column l and the remaining two as **equal-width, flush-left wrapping Y columns**, fitting the whole table to \textwidth.
\usepackage{tabularx}
\newcolumntype{Y}{>{\raggedright\arraybackslash}X}
% ...
\begin{tabularx}{\textwidth}{l Y Y}
\hline
項目 & 長所 & 短所 \\
\hline
tabular & 単純で速い & 幅を自分で調整する必要がある \\
tabularx & 表幅を固定でき、列が自動で伸縮する & 試し組みのぶん処理が遅い \\
\hline
\end{tabularx}This table spreads across the full text width (\textwidth); column 1 (“Item”) keeps the natural width of its short words, and columns 2–3 each take half of the remaining width, wrapping their longer descriptions at that width. Because we used Y (a flush-left X), each cell is set ragged-right. To weight the columns unequally, the coefficient syntax of tabularray (e.g. X[2]) shown below is handy — plain tabularx has no coefficient option.
One caveat: because the body is expanded several times, commands with side effects (stepping counters, writing to files, \verb, and so on) can misbehave inside tabularx. A cell that must contain a footnote or \verb typically needs to be wrapped in a box first.
tabulary — apportion width by content
tabularx divides space equally among its X columns. But when the columns hold very different amounts — say a short label in one and a long description in the other — equal shares look awkward. tabulary instead apportions width in proportion to the natural width of each column’s content, scaling the total to the width you ask for.
The syntax mirrors tabularx: \begin{tabulary}{width}{column spec}. There are four column types, all auto-width paragraph columns: **L left, C centered, R right, J** justified. You may mix in ordinary l, c, r, p{width}, etc., which are left out of the measurement (kept at natural width). Each measured column is weighted by the natural width of its widest cell and scaled so the table totals the requested width — but a column whose natural width is already smaller is left alone.
To curb extreme apportioning, two lengths bound a measured column: the **minimum \tymin** (default 10pt) and the **maximum \tymax** (default 2\textwidth). They help when a single very long entry would otherwise dominate a column’s width.
\usepackage{tabulary}
% ...
\begin{tabulary}{\textwidth}{L L}
\hline
用語 & 説明 \\
\hline
X 列 & 表幅から固定部分を引いた残りを、X 列どうしで均等に分け合う列。 \\
\hline
\end{tabulary}Both columns here are L (left), but column 1 (“Term”) is narrow because its content is short, while column 2 (“Description”) gets the wider share for its prose. With tabularx and X X the two columns would be equal width; tabulary follows the weight of the content, so a label-plus-text table comes out naturally proportioned. Note that tabulary also processes the body twice, so the same care over footnotes and counters as for tabularx applies.
tabularray — the modern tblr environment
tabularray is the most actively developed table package of recent years, written by Jianrui Lyu (lvjr)**. It discards the old \halign-based machinery and parses and typesets tables directly with LaTeX3 (expl3). Its headline feature is that it unifies into a single key–value interface what previously took several packages together — array, booktabs, multirow, colortbl, diagbox — for rules, color, cell spanning, paragraph formatting, and column widths. Load it with \usepackage{tabularray}; the main environment is **tblr**.
The structure of tblr differs slightly from tabular: before the body you give one argument of comma-separated key–value options (the inner specification), as in \begin{tblr}{ … inner spec … }. Column alignment is declared with the **colspec** key. You may use the familiar one-letter form colspec={lcr}, but its real power lies in **Q[…] (a generic column taking alignment, width, and other options in brackets) and X[…]** (an expanding column, like tabularx). X[c] is a centered expanding column; X[2,l] is a left-aligned one with coefficient 2 (twice the width of a plain X).
When you use X columns, give the width they expand into with the **width** key (default \linewidth if unset). Inter-row and inter-column spacing are the **rowsep and colsep** keys, defaulting in tblr to rowsep=2pt and colsep=6pt. Rules are declarative: **hlines / vlines draw every horizontal / vertical rule, and hline{n} / vline{n}** style a specific line, as in hline{2}={1pt,solid}. You never write \hline in the body.
Cell spanning is done in the body with **\SetCell**. \SetCell[c=2]{c} is a centered cell that spans 2 columns (the \multicolumn equivalent), and \SetCell[r=2]{c} spans 2 rows (the \multirow equivalent); c= and r= give the column/row span and the brace argument the cell’s alignment. To style whole rows or columns, use **\SetRow / \SetColumn**, e.g. \SetRow{cyan8} shades a row pale cyan (the names are the package’s built-in colors).
\usepackage{tabularray}
% ...
\begin{tblr}{
width = \textwidth,
colspec = {Q[l] X[c] X[2,l]},
rowsep = 3pt,
hline{1,Z} = {1pt,solid},
hline{2} = {0.5pt,solid},
row{1} = {font=\bfseries},
}
項目 & 区分 & 説明 \\
\SetCell[r=2]{l} 表環境 & 固定幅 & 表全体の幅を固定し、X 列が残りを分け合う。 \\
& 内容幅 & 各列の中身の量に応じて幅を配分する。 \\
注記 & --- & 罫線・色・結合をキーで一括指定できる。 \\
\end{tblr}This tblr fixes the table width to the text width with width=\textwidth. The three columns are Q[l] (a left basic column), X[c] (a centered expanding column), and X[2,l] (a left expanding column with coefficient 2), so the two X columns split the leftover width 1 : 2 and column 3 (“Description”) ends up widest. No \hline appears in the body — the rules come only from the hline{…} keys in the inner spec (Z is the special index for the last row). The first row is bold via row{1}={font=\bfseries}, and the column-1 cell “Table environment” spans two rows with \SetCell[r=2]{l}. Achieving all this without pulling in booktabs, multirow, and array is exactly the appeal of tabularray.
For tables that span pages there is the **longtblr** environment, with repeating header rows, captions, and footnotes; for a noted single-page table in the spirit of threeparttable there is **talltblr**. In these you put the caption, label, note{…}, and similar into the **optional […] argument (the outer specification)** before the body.
Which one to reach for
A rule of thumb: to fit a table to a fixed width with equal-width prose columns, use tabularx; to fix the width but apportion it naturally by how much each column holds, use tabulary; to handle rules, color, cell spanning, and column widths all through one system in new work, use tabularray.
tabularray is feature-rich and subsumes the width problem that tabularx / tabulary solve (via X columns plus the width key). By contrast tabularx and tabulary are mature, lightweight, and sit comfortably alongside existing tabular code. Think of it as: reach for the older packages to add width control to a short existing table, and for tabularray when you are building serious tables from scratch.
| Package | How width is set | Best for |
|---|---|---|
tabularx | Fixed total; X columns share equally | Equal-width prose columns fit to width |
tabulary | Fixed total; apportioned by content | Uneven label-plus-text tables |
tabularray | width key + X columns (with coefficients) | Modern tables with rules/color/spans unified |
The fine detail of column specs themselves (\multicolumn, the array package’s >{…}, and so on) lives on the “Column spec” page, the basics of merging cells on the “Merging cells” page, and very long page-spanning tables on the “longtable” page.