303

I have the following table:

\begin{table}[htb]
\begin{tikzpicture}
\node (table) [inner sep=0pt] {
\begin{tabular}{ l | l }
  {\bf Symptom} & {\bf Metric} \\
\hline
Class that has many accessor methods and accesses a lot of external data & ATFD is more than a few\\
Class that is large and complex & WMC is high\\
Class that has a lot of methods that only operate on a proper subset of the instance variable set & TCC is low\\
\end{tabular}
};
\draw [rounded corners=.5em] (table.north west) rectangle (table.south east);
\end{tikzpicture}
\caption{God class symptoms}
\label{tbl:god_class}
\end{table}

Now I want to force the width of the table to be the same as the \textwidth, either by linewrapping of table text or by scaling. How can I achieve that?

1
  • 19
    You should not use {\bf <text>} but \textbf{<text>} or \bfseries instead! Same is true for \it and \tt or how they are called. They are all deprecated. Please see the l2tabu document for this and other things. Feb 8, 2011 at 0:16

12 Answers 12

242

You can use the tabularx package. It allows you to set the width of the table and provides the X column type, which fills out the rest of the space. It can be used for several columns, which then share the rest of the width equally.

Example:

\usepackage{tabularx} % in the preamble
% ....
\begin{tabularx}{\textwidth}{X|l}
  \textbf{Symptom} & \textbf{Metric} \\
\hline
Class that has many accessor methods and accesses a lot of external data & ATFD is more than a few\\
Class that is large and complex & WMC is high\\
Class that has a lot of methods that only operate on a proper subset of the instance variable set & TCC is low\\
\end{tabularx}

In general it is also possible to set the width of a column using p{<width>} instead of l as column type. Then it will be formatted as a paragraph and can include line breaks. Replace <width> with the required width.

5
  • 22
    If you're considering tabularx you might also consider its less well known (but sometimes better behaved) sibling tabulary May 19, 2012 at 17:03
  • 3
    How can we adjust the width of the columns?
    – prince
    Dec 9, 2014 at 5:47
  • 22
    I think this method does work when the table is small and you need to adjust it to fit the text width. However, it does not work when you have a large table that is overflowing the margins and you need it to be compressed.
    – deps_stats
    Nov 14, 2015 at 22:07
  • 2
    This does not work on two columns and exceeds the page. @Martin Scharrer♦
    – alper
    Feb 25, 2019 at 17:07
  • 5
    Use >{\centering\arraybackslash}X instead of just X to center the text in the column.
    – winklerrr
    Mar 29, 2020 at 11:59
196

Just to mention an additional method: the tabular* environment. Suppose you have a table with 6 center-aligned columns. You can force it to take up the full width of the text block by setting it up as follows:

\setlength\tabcolsep{0pt}
\begin{tabular*}{\linewidth}{@{\extracolsep{\fill}} cccccc }
...
\end{tabular*}

Unlike the tabularx and tabulary environments, which work by expanding the width of some or all of the table's columns, the tabular* environment works by expanding the intercolumn whitespace. Incidentally, when employing tabular* environments with the @{\extracolsep{\fill}} expansion device, one should NOT employ vertical rules in the table.

The directive \setlength\tabcolsep{0pt} is technically optional. However, it's frequently very useful if the tabular material would exceed \linewidth by a bit if the default value of \tabcolsep (usually, but not always, 6pt) is employed.

Speaking for myself, I suspect it's the need to remember to insert @{\extracolsep{\fill}} that has kept the popularity of this approach somewhat subdued...

7
  • 15
    This answer is the most elegant one. Nov 27, 2018 at 14:14
  • 4
    This does not work for left/right alignment for me
    – G M
    Apr 6, 2020 at 16:39
  • 2
    Sorry I did not want to upset you I thought to downvote because it did not behave properly in my case and it was not written in the answer this exception. The alignment I am referring is for instance when I want the text of each cell to be align right or left e.g. llllll or rrrrrr I would not know how to explain better so I wrote mwe in overleaf overleaf.com/2294366948nstbmgcjhbrw
    – G M
    Apr 6, 2020 at 17:48
  • 3
    +1 for not using other environments.
    – ka3ak
    Dec 19, 2020 at 17:40
  • 2
    @amitoz - Unless one sets \setlength\tabcolsep{0pt}, there is a rather significant difference. Please compare the outputs of \noindent \begin{tabular*}{\textwidth}{@{\extracolsep{\fill}}cccc} \hline dflas & djsaf & djasf & adfaj \\ \hline \end{tabular*} and \noindent \begin{tabular*}{\textwidth}{c@{\extracolsep{\fill}}ccc} \hline dflas & djsaf & djasf & adfaj \\ \hline \end{tabular*}. Incidentally, I do recommend setting \setlength\tabcolsep{0pt} when working with tabular* environments.
    – Mico
    Dec 24, 2021 at 11:20
27

Here is a simple way:

\newlength\q
\setlength\q{\dimexpr .5\textwidth -2\tabcolsep}
\noindent\begin{tabular}{p{\q}p{\q}}
alfa & bravo \\
charlie & delta
\end{tabular}
5
  • 8
    +1 for (a) subtracting 2\tabcolsep from the column width parameter and (b) not including any vertical rules. :-)
    – Mico
    Oct 19, 2016 at 4:48
  • 2
    This solution also allows the full colouring of the row as at the interval specified with \rowcolour and \multicolumn...
    – HelloWorld
    Apr 23, 2019 at 9:25
  • 1
    The downside of this is that it only works if alll coumns of the table are paragraphs.
    – FooBar
    Oct 29, 2020 at 11:45
  • The comment by @FooBar may have been accurate at the time it was written. However, the array package has been expanded (some time in the past two years, if memory serves me correctly) to provide the w column type, which also takes a length as one of its arguments. E.g., one could replace \begin{tabular}{p{\q}p{\q}} with \begin{tabular}{w{l}{\q} w{r} p{\q}} to get two fixed-width columns with usable width \q, the first set to left-align its contents, the second set to right-align its contents.
    – Mico
    Apr 29, 2021 at 6:48
  • This is great. I wanted the left column narrower, so I used: \newlength\lw \setlength\lw{\dimexpr .4\textwidth -2\tabcolsep} \newlength\rw \setlength\rw{\dimexpr .6\textwidth -2\tabcolsep}
    – user4417
    Apr 14 at 14:32
26

Disclaimer: Although tabu might still work in cases it’s development is kind of stuck and it is better to not use it (for new documents). See also Is the tabu package obsolete?

One can use tabu (e.g). It will set the table to a given width without needing to calc the ration by hand.

\documentclass{article}

\usepackage{tabu}
\usepackage{booktabs}% for better rules in the table

\begin{document}
\begin{tabu} to \textwidth {XXXX}
   \toprule
   xx & 1 & 2 & 3 \\
   \bottomrule
\end{tabu}
\end{document}

tabu comes with the new column type X which sets its width automatically. It has an optional argument taking l, r, c to adjust the alignment inside the cell or a numer to set uneven widths of columns. For example two columns, the first on right, the second one left aligned and twice the width of the first one, will be X[r]X[2] (l and 1 will be set by default). The part between to and {<cols>} can be any width, and the full part can be omitted to, i.e. \begin{tabu}{<cols>}.

tabu is compatible with longtable with the new environment {longtabu}.


Adding showframeand some text (lipsum) to the above example shows that the table has exactly the width of the text. On may notice that a table without a float environment is set inline and gets indented as every normal text, too. Use \noindent to prevent that.

table

\documentclass{article}

\usepackage{tabu}
\usepackage{booktabs}% for better rules in the table
\usepackage{showframe,lipsum}

\begin{document}
\lipsum[4]

\noindent
\begin{tabu} to \textwidth {XXXX}
   \toprule
   xx & 1 & 2 & 3 \\
   \bottomrule
\end{tabu}
\end{document}
6
  • 2
    Thanks! But I think the table is still somewhat wider than the text width of the page (compared with \hrulefill).. Oct 22, 2013 at 9:06
  • 2
    @HåkonHægland: As you can see in my edit, the table has exactly the same width as the text …
    – Tobi
    Oct 22, 2013 at 9:39
  • 3
    Indeed but read tex.stackexchange.com/q/121841/4918 before falling in love to deeply ;-)
    – Tobi
    Nov 1, 2013 at 21:22
  • 1
    @HåkonHægland: '\hrulefill' doesn't have text width.
    – Spenhouet
    Jun 30, 2016 at 7:56
  • 1
    The tabu package is long unmaintained and it breaks things that other packages depend on. So unless someone takes over maintenance of it, I don't think it is a usable solution. Apr 28, 2020 at 1:34
17

You can also use the graphicx package - I found this solution from the following online Table generator: http://www.tablesgenerator.com/

You just need to add a "resizebox" command that rescales the tabular, see the following:

% Please add the following required packages to your document preamble:
% \usepackage{graphicx}

\begin{table}[htb]
\resizebox{\textwidth}{!}{% use resizebox with textwidth
\begin{tabular}{ l | l }
  {\bf Symptom} & {\bf Metric} \\
\hline
Class that has many accessor methods and accesses a lot of external data & ATFD is more than a few\\
Class that is large and complex & WMC is high\\
Class that has a lot of methods that only operate on a proper subset of the instance variable set & TCC is low\\
\end{tabular}% close resizebox
}
\end{table}

Note: that this will scale the whole table, including the font.

2
  • 4
    use of resizebox is not recommended. using it you will lost control on the font size used in table.
    – Zarko
    Oct 4, 2018 at 11:20
  • 1
    In the question it was said that scaling was accepted, so I think having a scaled font will be acceptable. Anyway, thanks for pointing this out, I will add a note to the answer :)
    – BlueCoder
    Oct 4, 2018 at 11:56
15

After trying the suggestions made in this stackexchange I found a different and fancy solution (without loading any other packages etc.). The key is define the width of each column.

   \begin{table}[ht!]
     \centering
     \caption{Caption text} 
     \begin{tabular}{|p{5cm}|p{9cm}|}
        Text column 1 & long long long long long long long text that should break \\
        \hline
      \end{tabular}
    \end{table}
2
  • 5
    So for the above example you'd need a text block that has width 5cm+9cm+(a bunch of other tabular measurements to make sure the table fits exactly)... you don't really specify this latter measurement. There is no real guarantee this will fit within the text block.
    – Werner
    Jan 26, 2016 at 21:44
  • 1
    How do you center the text with your solution? Oct 10, 2021 at 5:01
5

With ConTeXt, from the reference manual, section 16.5 TeX-figures (svnversion 329, September 27, 2013) :

\startbuffer[table]
\startTABLE
% fill your table here
\stopTABLE
\stopbuffer

\placefigure[none]{}{\externalfigure[table.buffer][width=\textwidth]}
4

I was having the same issue,

This is how I got to fix it. You can use "m" for the middle, "b" for the bottom and "p" you will need to play a little to get the desired results.

\begin{tabular}{|p{2cm}| p{3cm} | p{2.5cm} |}

2
  • 5
    what is fixed with your answer? how is selected column widths in your answer related to the text width?
    – Zarko
    Mar 24, 2019 at 20:50
  • 2
    Unless somehow \textwidth=7.5cm+6\tabcolsep+4\arrayrulewidth, this setup will not succeed in making the width of the tabular environment equat to the width of the text block.
    – Mico
    Nov 30, 2019 at 10:25
3

It’s easy peasy to make \textwidth tables with tblr environment of the new LaTeX3 package tabularray:

\documentclass{article}
\usepackage{tabularray}
\begin{document}
\begin{tblr}{|X[2,l]|X[3,l]|X[1,r]|X[r]|}
\hline
 Alpha & Beta & Gamma & Delta \\
\hline
\end{tblr}
\end{document}

enter image description here

You can also set negative coefficients in X columns, just as tabu package.

2

As @deps_stats points out, tabularx may work when the table size is small and you need to adjust it to fit the text width, but it does NOT work when a large table overflows the margins.

Perhaps a better choice is using resizebox. A sample is shown below.

\begin{table}[htb]
  \resizebox{\textwidth}{!}{
    \begin{tabular}{ l | l }
     ...
    \end{tabular}
  }
\end{table}
2

You can use the colspec function in the tabularray package. Then, use colspec = {X[1]X[2]} to specify the ratio of the width of the table.

x

Alternatively, you could use Q column method.

Here's a sample code which incorporate setting line color, forcing table into page width, and cell alignment:

\documentclass[a4paper]{article}
\usepackage{tabularray,lipsum,xcolor}

\begin{document}
\begin{tblr}{
  colspec = {Q[1,c,m]Q[5,l,m]},
  hlines = {gray!75!white},
  vlines = {gray!75!white},
}
ABC & \lipsum[1] \\
DEF & \lipsum[2] 
\end{tblr}
\end{document}

enter image description here

1

Once you have made the table, between \begin{table} add \begin{tabular} enter this:

\makebox[size of the table in cm]{put the tabular environment here}

This works for me. Please try this.

1
  • Thanks, this worked like a charm. Oct 12, 2021 at 10:15

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .