# How to make a table with fixed length and width, and the text with various length in it can automatically wrap

I want to create a table with fixed length and width, and the text with various length in it can automatically wrap and the text should be centered vertically and horizontally. I try many ways but no one is ok,anyone knows how to make it

Update 21.4.2020 added example 3 and 4

Example 1 - calstable

If you can live without the coloured rules, you can easily set such table using cals.

If you want to have a narrower table, not filling the whole line width, just put number <1 in the formula, i.e.

{\dimexpr(0.9\columnwidth)/34*4\relax}


If you want a different width of the columns, just change the other figures, and ensure that the figures sums up. For example, if you change the 34 to 30, you have to change the width of the columns so that the sum of all the columns also is 30. If not, the table will wider than the line width. For example:

\colwidths{{\dimexpr(\columnwidth)/30*4\relax}
{\dimexpr(\columnwidth)/30*10\relax}
{\dimexpr(\columnwidth)/30*5\relax}
{\dimexpr(\columnwidth)/30*5\relax}
{\dimexpr(\columnwidth)/30*6\relax}
}


Here, 4+1+5+5+6=30

calstables are multipage, but you then have to remove the table-environment:

\documentclass{article}
\usepackage{cals, caption}
\usepackage[svgnames]{xcolor}

\let\nc=\nullcell                          % Shortcuts
\let\sc=\spancontent

\begin{document}

\begin{table}                   % If table is multipage, remove the table environment
\caption{A table\label{tabelTable}}

\begin{calstable}[c]

% Defining columns relative to each other and relative to the margins
\colwidths{{\dimexpr(\columnwidth)/34*4\relax}
{\dimexpr(\columnwidth)/34*12\relax}
{\dimexpr(\columnwidth)/34*6\relax}
{\dimexpr(\columnwidth)/34*6\relax}
{\dimexpr(\columnwidth)/34*6\relax}
}
% The tabular fills the text area if sum of all columns is 34

% Set up the tabular
\makeatletter
\def\cals@framers@width{0.2pt}   % Outside frame rules, reduce if the rule is too heavy
\def\cals@framecs@width{0.2pt}
\def\cals@bgcolor{}
\def\cals@AtBeginCell{\vfil}             % Ensure that all cells is vertically centred

\def\lblue{\ifx\cals@bgcolor\empty     % "Switch" to turn on and off colour
\def\cals@bgcolor{LightSteelBlue}
\else \def\cals@bgcolor{} \fi}

% R1H1
\brow
\lblue\nc{lrt}
\nc{ltb}
\nc{tb}
\nc{lrt}
\erow
%R2H2
\brow
\nc{lrb}\alignC\sc{Text}
\cell{Subheading is long and that wraps}
\cell{Short}
\nc{lrb}\alignC\sc{Text}\lblue
\erow
\mdseries}
\tfoot{\lastrule\strut}
%R3B1
\brow
\alignC\cell{Wrapping text}
\cell{Horiz. and vertic. centred}
\cell{2}
\cell{3}
\cell{1}
\erow
%R3B1
\brow
\alignC\cell{1}
\cell{2}
\cell{2}
\cell{3}
\cell{1}
\erow
\makeatletter
\end{calstable}
\end{table}

\end{document}


Example 2 - longtable

You may also achieve your result using longtable (or tabular), but you have to load additional packages, like multirow, array and hhline. Since you use colour and rules, you may experience the "disappearing rules"-syndrome and white lines in multirow-cells. I have partly avoided that by using \hhline instead of \cline, but it is complicated to get the colour correct.

I have used fixed width columns, but you may calculate the columns as I did using cals. It is more complicated for longtable, because you have to take into consideration \tabcolsep and \arrayrulewidth in the calculation.

Of cause, you do not have to define new column types, as I have done. To have five columns of different width, it is perfectly OK to set up the preamble as:

\begin{longtable}[c]{|@{\extracolsep{\fill}}
>{\color{red}\centering\arraybackslash\hspace{0pt}}m{1.5cm}}
>{\color{red}\centering\arraybackslash\hspace{0pt}}m{3.5cm}}
>{\color{red}\centering\arraybackslash\hspace{0pt}}m{2.5cm}}
>{\color{red}\centering\arraybackslash\hspace{0pt}}m{2cm}}
>{\color{red}\centering\arraybackslash\hspace{0pt}}m{1.75cm}}


Just ensure that the table is not wider than the line width. Using the preamble above, the table is (10.75 cm + 10 \tabcolsep + 6 \arrayrulewidth) wide. The command

@{\extracolsep{\fill}}


ensure that the longtable will stretch to the full line width.

My example below assumes that some columns have the same widths:

\documentclass{article}
\usepackage{array, caption, multirow, longtable, hhline}
\usepackage[svgnames, table]{xcolor}

\newcolumntype{M}{>{\color{red}\centering\arraybackslash\hspace{0pt}}m{3.5cm}}
\newcolumntype{N}{>{\color{red}\centering\arraybackslash\hspace{0pt}}m{2.5cm}}
\newcolumntype{O}{>{\color{red}\centering\arraybackslash\hspace{0pt}}m{2cm}}

\setlength{\tabcolsep}{0pt}
\arrayrulecolor{LightSteelBlue}
\setlength{\extrarowheight}{2pt}

\renewcommand{\arraystretch}{1.1}

\renewcommand{\multirowsetup}{\centering}
\newcommand{\cw}[1]{\textcolor{white}{\bfseries #1}}
\newcommand{\tr}[1]{\textcolor{red}{#1}}

\begin{document}

\begin{longtable}[c]{|@{\extracolsep{\fill}}O|M|N|N|O|}
\hline
\rowcolor{SteelBlue}&\multicolumn{3}{c|}{\cw{Long heading spanning three columns}} & \\
\hhline{|>{\arrayrulecolor{SteelBlue}}->{\arrayrulecolor{LightSteelBlue}}---|>{\arrayrulecolor{SteelBlue}}->{\arrayrulecolor{LightSteelBlue}}|}
\rowcolor{SteelBlue}\multirow{-2}{=}{\cw{Text}} & \cw{Subheading is long and that wraps} & \cw{Short} & \cw{Subheading that wraps} &\multirow{-2}{=}{\cw{Text}} \\
\hline
Wrapping text &Horiz. and vert. centred & 3 & 4 & 5 \\ \hline
1&2&3&4&5\\
\hline

\end{longtable}

\end{document}


Example 3 - xltabular

xltabular is a combination of longtable and tabularx, and will help you to calculate column width also in multipage tables. Please, read the manual for tabularx, xltabular and longtable.

In the example, I redefine X-columns from p- to m-columns, see tabularx manual for explanation. I also set the column widths relative to each other, also this is described in the manual. Make sure that the sum of the widths of all the X-columns is unchanged. In the example, the new widths still add up five standard X columns, 1.8 + (2 x 0.9) + (2 x 0.7).

For example, if you increase the width of the M-column to 1.9, you have to decrease either the O-column by 0.5, or the N- and O-column by 0.25.

If you need a wider table, you have to decrease the documents left and right margins. Use for example geometry.

\documentclass{article}
\usepackage{array, caption, multirow, xltabular, hhline}
\usepackage[svgnames, table]{xcolor}

\renewcommand{\tabularxcolumn}[1]{m{#1}}

\newcolumntype{M}{>{\color{red}\centering\arraybackslash\hspace{0pt}\hsize=1.8\hsize\linewidth=\hsize}X}
\newcolumntype{N}{>{\color{red}\centering\arraybackslash\hspace{0pt}\hsize=0.9\hsize\linewidth=\hsize}X}
\newcolumntype{O}{>{\color{red}\centering\arraybackslash\hspace{0pt}\hsize=0.7\hsize\linewidth=\hsize}X}

\setlength{\tabcolsep}{4pt}
\arrayrulecolor{LightSteelBlue}
\setlength{\extrarowheight}{2pt}

\renewcommand{\arraystretch}{1.1}

\renewcommand{\multirowsetup}{\centering}
\newcommand{\cw}[1]{\textcolor{white}{\bfseries #1}}
\newcommand{\tr}[1]{\textcolor{red}{#1}}

\begin{document}

\begin{xltabular}[c]{\linewidth}{|O|M|N|N|O|}

\caption{A caption}\\

\hline
\rowcolor{SteelBlue}&\multicolumn{3}{c|}{\cw{Long heading spanning three columns}} & \\
\hhline{|>{\arrayrulecolor{SteelBlue}}->{\arrayrulecolor{LightSteelBlue}}---|>{\arrayrulecolor{SteelBlue}}->{\arrayrulecolor{LightSteelBlue}}|}
\rowcolor{SteelBlue}\multirow{-2}{=}{\cw{Text}} & \cw{Subheading is long and that wraps} & \cw{Short} & \cw{Subheading that wraps} &\multirow{-2}{=}{\cw{Text}} \\
\hline
Wrapping text &Horiz. and vert. centred & 3 & 4 & 5 \\ \hline
1&2&3&4&5\\
\hline

\end{xltabular}

\end{document}


Example 4 - xltabular and individual column width

If you need column of different width, you may still use xltabular to calculate the relative width, so that the tabular fills the line width (or a fraction of it).

In this example, you give the relative width of the X-column as a parameter to the defined M-column. Remember that the sum of the fractions has to be the same as the number of M-columns. If you use four M-columns, the sum of the fractions also has to be four.

I have also defined an M-column that takes a fixed width. You may combine the two column types, see the example:

\documentclass{article}
\usepackage{array, caption, multirow, xltabular, hhline}
\usepackage[svgnames, table]{xcolor}

\renewcommand{\tabularxcolumn}[1]{>{\color{red}\centering\arraybackslash\hspace{0pt}}m{#1}}

\newcolumntype{M}[1]{>{\hsize=#1\hsize\linewidth=\hsize}X}
\newcolumntype{N}[1]{>{\color{red}\centering\arraybackslash\hspace{0pt}}m{#1}}

\setlength{\tabcolsep}{4pt}
\arrayrulecolor{LightSteelBlue}
\setlength{\extrarowheight}{2pt}

\renewcommand{\arraystretch}{1.1}

\renewcommand{\multirowsetup}{\centering}
\newcommand{\cw}[1]{\textcolor{white}{\bfseries #1}}
\newcommand{\tr}[1]{\textcolor{red}{#1}}

\begin{document}

\begin{xltabular}{\linewidth}{|M{0.5}|M{1.5}|M{0.75}|M{1.25}|N{2.5cm}|}

\caption{A caption}\\

\hline
\rowcolor{SteelBlue}&\multicolumn{3}{|c|}{\cw{Long heading spanning three columns}} & \\
\hhline{|>{\arrayrulecolor{SteelBlue}}->{\arrayrulecolor{LightSteelBlue}}---|>{\arrayrulecolor{SteelBlue}}->{\arrayrulecolor{LightSteelBlue}}|}
\rowcolor{SteelBlue}\multirow{-2}{=}{\cw{Text}} & \cw{Subheading is long and wraps} & \cw{Short} & \cw{Subheading that wraps} &\multirow{-2}{=}{\cw{Text}} \\
\hline
Wrapping text &Horiz. and vert. centred & 3 & 4 & 5 \\ \hline
1&2&3&4&5\\
\hline

\end{xltabular}

\end{document}

• Thanks. it works for me.But I have another trouble, if I want to modify the width of the table, I modify colwidths , when I rewrite the value in this code, the table widen to the right ,how could I make it widen to the left and right? And if I want to change the rule color to the RGB:221, 216, 195, how could I modify the code?@Sveinung Apr 15 '20 at 2:59
• I found the way to change rule color in the cals document , but it seems like there is no clue in it @Sveinung Apr 15 '20 at 6:16
• Sorry, I mean I have not found the way to colourise the rules. Do you have any idea?@ Sveinung Apr 15 '20 at 8:15
• @GuoFengWang No, it is explicitly stated in the documentation that colourised rules in not supported, therefore I started the answer with: "If you can live without ...". Apr 15 '20 at 8:19
• OK, I got it , thank you so much@Sveinung Apr 15 '20 at 8:21

For example something like this:

\def\tableline#1#2#3{%
\hbox{\onecolumn{5cm}{#1}\onecolumn{7cm}{#2}\onecolumn{4cm}{#3}}
}
\def\onecolumn#1#2{$\vcenter{ \leftskip=.3em plus1fill \rightskip=\leftskip \parindent=0pt \hsize=#1\relax \strut#2\strut}$%
}

\vbox{
\tableline{gd hd jvdhj gsd hksd fd cfg s5 esa dds s}
{dusids ksb}
{fhusd sb hjs suvsjf fudf vdu vdv}
\tableline{gf dssiw yisd yds d}
{dkd dsks hd dsgs gcg csgc lv jlcv f dhjs ksd dn hjd j hj}
{dghd}
}

\bye


This is an example for a table with three columns, first 5cm, second 7cm and third 4cm width. You can simply modify this macro for another columns configuration.

The core of the macro is using \vcenter primitive in math mode which does vertical alignment. The \hsize primitive register is set to the desired width of the paragraph. The \leftskip and righrskip are set in order to center the paragraph.

The trick was to pass the width argument as a macro and use collcell for the contents.

\documentclass{standalone}
\usepackage{array}
\usepackage{collcell}
\usepackage{blindtext}% MWE nly

\newcommand{\mycolumn}[1]{\parbox[c]{\myarg}{\centering #1}}
\newcolumntype{M}[1]{>{\def\myarg{#1}\collectcell\mycolumn}{l}<{\endcollectcell}}

\begin{document}
\begin{tabular}{r|M{4in}|}
center-- & \protect\blindtext
\end{tabular}%
\end{document}