The single thing that makes a LaTeX table instantly recognisable as a LaTeX table is its rules. Lines drawn with \hline and | look glued to the letters — and that is measurable rather than impressionistic: \hline adds nothing to the row but its own 0.4pt of ink, with zero space above or below. The booktabs \midrule brings a 0.5pt line plus 4.52pt of white space with it. What separates a journal table from a default LaTeX table is exactly those few points of air. This page works through the standard \hline, \cline and \vline, then booktabs with \toprule / \midrule / \bottomrule, then hhline for the crossings neither of them reaches — with measured numbers throughout.
Why \hline, \cline and | look cramped
The answer is that they add no space at all. Measure a two-row tabular and it stands 24.0pt tall; put an \hline between the rows and it becomes 24.4pt. The growth is exactly \arrayrulewidth (0.4pt by default) — the thickness of the line itself and nothing else. No white space is inserted, which is why the rule appears to touch the letters. \cline is more extreme still: adding \cline{2-3} leaves the height at 24.0pt, an increase of precisely zero. The line does not push the rows apart; it is drawn inside the leading that was already there.
The tools themselves are straightforward. \hline, placed after a row’s \\ (or at the very top or bottom of the table), draws one line across the full width; two in a row, \hline\hline, give a double rule separated by \doublerulesep (2pt by default). To rule only part of a row, use \cline{i-j} — \cline{2-3} rules below columns 2 and 3, and disjoint spans are listed as \cline{1-1}\cline{3-4}. Vertical rules belong to the column specification, not the body: writing {|l|c|r|} puts a full-height line at each |, and || gives a double one. There is also \vline for a vertical rule inside a single cell. The thickness of every one of |, \hline and \vline is governed by \arrayrulewidth, so \setlength{\arrayrulewidth}{0.8pt} thickens all of them at once.
% every standard ruling feature at once -- and a specimen of what to avoid
\begin{tabular}{|l|c|r|}
\hline
Item & Qty & Price \\
\hline\hline
Apple & 3 & 380 \\
\cline{2-3}
Orange & 12 & 120 \\
\hline
\end{tabular}This boxes every column with |, double-rules below the header with \hline\hline, and part-rules the middle with \cline{2-3}. It exercises the whole standard repertoire — and is precisely a specimen of the over-ruling to avoid. In the typographic tradition a rule is not a cage around the data but a restrained device marking a logical division of it. Vertical rules build walls between columns that stop the eye; double rules weigh the page down for nothing in return. If you stay with plain \hline, at least do not box the table: rule below the header and at the top and bottom, and nowhere else. The booktabs package in the next section is that discipline turned into code.
How to use booktabs — \toprule, \midrule, \bottomrule
Write \usepackage{booktabs} in the preamble and replace \hline with three kinds of rule: \toprule at the top of the table, \midrule where the heading meets the body, \bottomrule at the foot. That alone gives you a journal table, with no vertical and no double rules. Two things are doing the work: it grades the rules into three thicknesses and it puts space above and below each rule. The numbers make the difference plain — the same three-row table measures 37.20pt tall with \hline and 47.14pt with booktabs. Identical content, about 10pt more white.
The defaults live in booktabs.sty: \heavyrulewidth=.08em (for \toprule and \bottomrule), \lightrulewidth=.05em (\midrule), \cmidrulewidth=.03em (\cmidrule). Measured in a 10pt document those are 0.80002pt, 0.50003pt and 0.29999pt — a set that brackets \hline’s 0.4pt from above and below. The elegance is in the unit: because they are given in em, a document set in 11pt gets a 0.876pt heavy rule and a 12pt document 0.94pt, so the rules thicken in proportion to the type. \arrayrulewidth stays a flat 0.4pt whatever the class, so on that count alone \hline is out of scale with its own text. For the space, \aboverulesep=.4ex (1.72218pt at 10pt) and \belowrulesep=.65ex (2.79857pt). A single \midrule therefore adds 0.5+1.72+2.80 = 5.02pt to the row — more than twelve times \hline’s 0.4pt.
\usepackage{booktabs}
% \toprule goes right after \begin{tabular}{...}; the rest follow a row's \\
\begin{tabular}{@{}llr@{}}
\toprule
\multicolumn{2}{c}{Fruit} \\
\cmidrule(lr){1-2}
Kind & Grade & Price \\
\midrule
Apple & premium & 380 \\
Orange & second & 120 \\
\addlinespace
Total & & 500 \\
\bottomrule
\end{tabular}The small gap before the totals row comes from \addlinespace. Placed after a row’s \\, it inserts \defaultaddspace (.5em, so 5pt in a 10pt document), and you can name an amount with \addlinespace[1ex]. It states the intent more clearly than stretching a row with \\[2pt], and next to a rule it controls the gap exactly. Only when you want to dictate thickness and the space above and below yourself do you reach for \specialrule{width}{above}{below} (all three arguments mandatory) — a command for unusual cases; the three ordinary rules normally suffice. Rules must sit at a row boundary: write \toprule in the middle of a cell and the run stops with ! Misplaced \noalign., because like \hline these commands operate inside \noalign.
| Command / length | Role | Default (measured in a 10pt document) |
|---|---|---|
\toprule | Rule at the very top of the table | \heavyrulewidth = .08em = 0.80002pt |
\midrule | Rule dividing heading from body | \lightrulewidth = .05em = 0.50003pt |
\bottomrule | Rule at the very bottom of the table | \heavyrulewidth = .08em = 0.80002pt |
\cmidrule(lr){a-b} | Partial rule spanning columns a–b only | \cmidrulewidth = .03em = 0.29999pt; trim \cmidrulekern = .5em = 5pt |
\aboverulesep | Space inserted above every rule | .4ex = 1.72218pt |
\belowrulesep | Space inserted below every rule | .65ex = 2.79857pt |
\addlinespace | Extra space between two rows | \defaultaddspace = .5em = 5pt |
\specialrule | Rule with thickness and both gaps given explicitly | All three arguments mandatory (no defaults) |
Incidentally, \heavyrulewidth calling the thickness a “width” is not a slip of English. booktabs.dtx carries a note on terminology explaining that in British typesetting a line is always called a rule, and that a rule’s thickness “is often referred to as its width” — where, as the author drily adds, just about everyone else would say depth or height of a horizontal rule. He carried the trade jargon straight into the command names. And one more thing: the version of booktabs shipped with TeX Live 2024 is 1.61803398 — φ, the golden ratio. A footnote on the title page of the .dtx says in the author’s own words that the version number is “converging to phi, the golden ratio”, one further digit per release. The abstract lists 1.618, 1.6180, 1.61803 and 1.618033, and a footnote records that those bug-fix releases were made by Danie Els in the absence of the author.
The difference between \cline and \cmidrule
The visible difference comes down to space and end treatment. Measured on the same two-row table, \cline{2-3} adds 0.0pt of height while \cmidrule{2-3} adds 4.82pt (0.29999pt of rule plus \aboverulesep 1.72218pt plus \belowrulesep 2.79857pt). That is why a \cline looks like it is biting into the letters. The other difference is the ends. By default a \cmidrule reaches the full width of its columns and will run into a neighbouring partial rule, so you give it a trim in parentheses: (l), (r) and (lr) pull the left, right or both ends back by \cmidrulekern (.5em = 5pt), and you can name the amount, as in (r{.75em}). The full syntax is \cmidrule, then an optional width in brackets, then a trim in parentheses, then {a-b}. As a working rule, a \multicolumn that groups column headings almost always wants a \cmidrule(lr){…} under it.
What you must not do is mix them. The author states plainly that the booktabs rules “are not guaranteed to work with \hline or \cline… I cannot foresee any reason to want to mix them.” In fact the rules are built so as not to connect with the | of a column specification, and the documentation calls that a feature. Only when you genuinely need a doubled partial rule at one height do you put \morecmidrules between two \cmidrules (\cmidrule{1-2}\morecmidrules\cmidrule{1-2}; the gap is \cmidrulesep, which defaults to the same 2pt as \doublerulesep). Since double rules are discouraged in the first place, this is not an everyday tool either.
Why you should never use vertical rules
The booktabs manual states this in the imperative and without hedging. You will not go far wrong, it says, if you remember two simple guidelines at all times: “1. Never, ever use vertical rules. 2. Never use double rules.” It goes on: “These guidelines may seem extreme but I have never found a good argument in favour of breaking them.” If the left half of a table differs from the right so much that you want a line between them, the author’s answer is that you should use two tables instead. Elsewhere he puts it more briefly still: you should not use vertical rules in tables, end of story.
The same document lists three further guidelines that the author prefaces as “generally not known outside the circle of professional typesetters and subeditors”, and they are quite practical. Put the units in the column heading, not in the body of the table. Always precede a decimal point by a digit — 0.1, not .1. Do not use ditto marks or any similar convention to repeat a value: a blank usually serves, and if it does not, repeat the value. The author is honest about the limits of his own rules, noting of the second guideline that he “worked for a publisher who insisted on a double light rule above a row of totals. But this would not have been my choice.” The guidelines are not absolutes; they are things you break for a reason.
hhline — specifying how rules cross
hhline draws the same horizontal rules as \hline, but lets you say, character by character, whether a vertical rule is cut by the crossing or runs straight through it. It is David Carlisle’s package from LaTeX’s tools bundle, loaded with \usepackage{hhline}. With a plain \hline\hline you cannot choose whether a vertical rule breaks at the double rule or passes through. Since booktabs tells you to use neither vertical nor double rules, hhline earns its place only where you cannot follow that advice — a journal template that mandates a format, a document you must reproduce, an accounting table. Outside those cases you will not need it.
The argument to \hhline{…} is a list of tokens that reads much like a column specification. For the horizontal side: = is a double rule the width of one column, - a single rule, ~ no rule in that column. For the vertical side: | is a vertical line that cuts through the rule, : one that is broken by it, and # a segment of double rule between two vertical lines. There are also t (the top half of a double-rule segment) and b (the bottom half) for building corners, so |t: is the top-left corner and :b| the bottom-right. The same *{n}{…} repeat form as in column specs is available. Note that writing a double vertical rule (|| or ::) breaks the horizontal rules at that point; to run one straight through, use # or drop the vertical specifiers altogether.
\usepackage{hhline}
% the example from the package documentation: t/b build the corners,
% ~ leaves a column unruled, # is a double-rule segment between verticals
\begin{tabular}{||cc||c|c||}
\hhline{|t:==:t:==:t|}
a & b & c & d \\
\hhline{|:==:|~|~||}
1 & 2 & 3 & 4 \\
\hhline{#==#~|=#}
i & j & k & l \\
\hhline{||--||--||}
w & x & y & z \\
\hhline{|b:==:b:==:b|}
\end{tabular}The first line, |t:==:t:==:t|, builds the top halves of the double rules together with the corners, and the last, |b:==:b:==:b|, the bottom halves, so the double-ruled frame joins cleanly with the vertical rules. The middle rows mix ~ (no rule) and # (a double-rule segment between verticals), changing row by row where the rules break and where they run through. One technical caveat to finish. An \hline is a single TeX \hrule, whereas an \hhline line is assembled from many small segments. Their positions in the DVI are exact, but some viewers and drivers do not line the segments up perfectly. The documentation suggests trying a different driver, or nudging \arrayrulewidth up slightly so the seams stop showing.
Which one to use
The conclusion is close to singular: make booktabs your default for ordinary tables. The three rules \toprule, \midrule and \bottomrule, plus a \cmidrule(lr){…} where a heading group needs one, give the spare, readable tables you see in journals. Follow “no vertical rules, no double rules” and ruling stops being something you deliberate over at all.
booktabs— first choice for nearly every table: horizontal rules only, thickness and spacing already tuned, publication quality.- Standard
\hline/\cline/|— handy because they need no package; fine for grid-style tables and quick drafts. Watch the over-ruling. hhline— only for the special case where you must control precisely how double and vertical rules cross. Not an everyday tool.- When you feel like adding a rule — first ask whether
\addlinespacecould mark the group of rows instead. White space is lighter than a rule and does the same job.
Before the rules, the arrangement and alignment of the columns set the skeleton of a table. For the basics of & and \\, and for reading Extra alignment tab and Misplaced \noalign, see “tabular basics”. For the fine detail of column specifications including p{width} and >{…}, see “Column spec, alignment & width”. Multi-level headings combining \multicolumn with \cmidrule are covered under “Merging cells”. Putting the table into a table environment and captioning it belongs to “Table placement & styling”.