5

What I know

I know that it is possible to set the width for specific columns when using the tabularx environment. See minimal working example below. The preamble argument for the tabularx environment shown below was retrieved from the documentation of the tabularx package.

\documentclass{article}

\usepackage[showframe]{geometry}
\usepackage{tabularx}

\begin{document}
\noindent
\begin{tabularx}{\textwidth}{
  |>{\hsize=.2\hsize\linewidth=\hsize}X
  |>{\hsize=1.8\hsize\linewidth=\hsize}X|}
\hline
foo & foo \\ \hline
foo & foo \\ \hline
foo & foo \\ \hline
\end{tabularx}
\end{document}

enter image description here

I also know that it is possible to display images inside cells. In the minimal example below, I changed the width of the image to 2cm, because the default size exceeds the cell dimensions.

\documentclass{article}

\usepackage[showframe]{geometry}
\usepackage{tabularx}
\usepackage{graphicx}

\begin{document}
\noindent
\begin{tabularx}{\textwidth}{
    |>{\hsize=0.2\hsize}X
    |>{\hsize=0.8\hsize}X
    |
}
\hline
\includegraphics[width=2cm]{example-image} & foo \\ \hline
foo & foo \\ \hline
foo & foo \\ \hline
\end{tabularx}
\end{document}

enter image description here

I am now trying to make an image that is being displayed in a cell to occupy the entire width of the cell in which it is shown regardless of the width of the column. This means that if I change the width of the column, the image needs to adjust itself so that the image occupies the entire width.

Through trial and error, I was able to make the image occupy as much space as possible without exceeding the right limit. See code and screenshot below. However, this doesn't fullfil what I'm trying to accomplish because there's still space on the left side of the cell that is left blank.

\documentclass{article}

\usepackage[showframe]{geometry}
\usepackage{tabularx}
\usepackage{graphicx}

\begin{document}
\noindent
\begin{tabularx}{\textwidth}{
    |>{\hsize=0.2\hsize}X
    |>{\hsize=0.8\hsize}X
    |
}
\hline
\includegraphics[width=3.07cm]{example-image} & foo \\ \hline
foo & foo \\ \hline
foo & foo \\ \hline
\end{tabularx}
\end{document}

enter image description here

So my question is: How to make an image that is being displayed in a cell to occupy the entire width of the cell in which it is shown regardless of the width of the column?

What I've tried

From this answer, I was able to get the dimensions of the current cell. However, the width doesn't consider the padding of cells (e.g. the space between the content and the borders of the cell.) See minimal working example below.

\documentclass{article}

\usepackage[showframe]{geometry}
\usepackage{tabularx}

\makeatletter
\newcommand\mycellwidth{\TX@col@width}
\makeatother

\begin{document}
\noindent
\begin{tabularx}{\textwidth}{|X|X|}
\hline
\rule{\mycellwidth}{.1cm} & foo \\ \hline
foo & foo \\ \hline
foo & foo \\ \hline
\end{tabularx}
\end{document}

enter image description here

I also found this answer in a question on the similar topic which recommends using \setkeys{Gin}{width = \linewidth}. I tried it, but I noticed that there's space between the image and the left cell border and the right cell border

\documentclass{article}

\usepackage[showframe]{geometry}
\usepackage{tabularx}
\usepackage{graphicx}
\setkeys{Gin}{width=\linewidth}

\begin{document}
\noindent
\begin{tabularx}{\textwidth}{|X|X|}
\hline
\includegraphics{example-image} & foo \\ \hline
foo & foo \\ \hline
foo & foo \\ \hline
\end{tabularx}
\end{document}

enter image description here

Additional information

I understand that sometimes an image might not have the same dimension ratio (e.g. 16:9 or 4:3) than the ratio of the current cell. In such case, when the image occupies the entire width, it is possible that there's blank space at the top and the bottom between the image and the cell borders.

1
  • 1
    You appear to use both 0.8\hsize and 1.8\hsize for the second column specification. Please fix.
    – Mico
    Commented May 5 at 7:57

5 Answers 5

4

We need to find the absolute width of the first column. Let us work out the value of this length parameter from first principles. First, the instruction

\begin{tabularx}{\textwidth}{
  |>{\hsize=0.2\hsize\linewidth=\hsize}X
  |>{\hsize=1.8\hsize\linewidth=\hsize}X|}

means that the usable widths of columns 1 and 2 -- which we'll label as w1 and w2 -- are as 0.2 to 1.8, or 1 to 9. Put differently, w2=9*w1. Second, since there are two columns (with whitespace in the amount of \tabcolsep, or T, on either side) and three vertical rules (with width \arrayrulewidth, or A), we have

\textwidth = A + T + w1 + T + A + T + 9*w1 + T + A

or

10*w1 = \textwidth - 4\tabcolsep - 3\arrayrulewidth

To obtain the full width of column 1, WW, we need to add back 2\tabcolsep to w1:

WW = (\textwidth - 4\tabcolsep - 3 \arrayrulewidth)/10 + 2\tabcolsep 

(Aside: if the ratio of usable widths were 1:3 instead of 1:9, one would have to divide by 1+3=4 instead of by 10. Etc.)

With these results in hand, we are ready to generate the table.

enter image description here

\documentclass[12pt]{article} % '10pt', '11pt, or whatever

\usepackage[showframe]{geometry}
\usepackage{tabularx,graphicx}
\usepackage{calc}
\newlength\WW
\setlength\WW{(\textwidth-4\tabcolsep-3\arrayrulewidth) / 10 + 2\tabcolsep}
% next, the vertical adjustment factor
\newlength\ZZ
\makeatletter
\setlength\ZZ{-\fpeval{\f@size*0.375}pt} % 0.375 obtained by trial and error...
\makeatother

\begin{document}
\noindent
\begin{tabularx}{\textwidth}{%
    |>{\hsize=0.2\hsize}X|>{\hsize=1.8\hsize}X|}
\hline
\multicolumn{1}{|@{}p{\WW}@{}|}{\raisebox{\ZZ}{% 
    \includegraphics[width=\linewidth]{example-image}}}
    & bar \\ \hline
foo & bar \\ \hline
foo & bar \\ \hline
\end{tabularx}
\end{document}
4
  • if you are going to precompute the width, you don't even need tabulars. Commented May 5 at 14:13
  • @JohnKormylo - Sorry, I'm not sure I understand what you're trying to get at.
    – Mico
    Commented May 5 at 14:39
  • @JohnKormylo - Absolutely: If the OP knows ex ante what the total width (not just the usable width) of the first column has to be, then this piece of information can and should be used directly. My impression, though, is that this is not known in advance. Instead, if all that's known is that the ratio of the usable column widths should be as 1 to 9, performing some additional calculations is going to be pretty much unavoidable, no?
    – Mico
    Commented May 5 at 14:54
  • @JohnKormylo - I don't calculate \XX separately in my answer. Having started with a perfectly good tabularx specification and having derived \WW, I feel no particular urge to perform still more work in order to replace the estabilished tabularx specification with \begin{tabular}{|p{\XX}|p{9\XX}|}. Or am I missing something?
    – Mico
    Commented May 5 at 21:03
2

Note that I do not recommend this from a typographical perspective. See booktabs manual for an explanation.

Caveat emptor

You cannot easily get a perfect match because calculations in TeX are only approximate. Hence, any dimension you calculate will be subject to inaccuracies. Even storing a dimension only typically stores a value approximately equal to the one specified.

If you need more precision, you can get it, but since you have to then turn the results over to TeX when constructing the page, you'll introduce approximations eventually.

You can, however, set things up to calculate the approximate dimension using an accurate formula. \tabcolsep is the dimension you need to add. To avoid the space on the left, you need to replace the default padding with none using @{}.

So, for example, I think the following is correct:

\documentclass{article}

\usepackage[showframe]{geometry}
\usepackage{calc}
\usepackage{tabularx}
\usepackage{graphicx}

\begin{document}
\noindent
\begin{tabularx}{\textwidth}{
    |>{\hsize=0.2\hsize}X
    |>{\hsize=0.8\hsize}X
    |
  }
  \hline
  \multicolumn{1}{|@{}p{.2\hsize+\tabcolsep}@{}|}{\includegraphics[width=\linewidth]{example-image}} & foo \\ \hline
  foo & foo \\ \hline
  foo & foo \\ \hline
\end{tabularx}
\end{document}

The image sits on the baseline, just like the text on the right. I can't make images due to a bug, but if you compile, you can see the baseline of the image is aligned with the baseline of the text foo in the right hand column. The gap beneath is the space allowed for descenders in words such as foggy. If you wished, you could raise the image by a negative dimension in order to lower it relative to the baseline.

\documentclass{article}

\usepackage[showframe]{geometry}
\usepackage{calc}
\usepackage{tabularx}
\usepackage{graphicx}
\newlength \mylength

\begin{document}
\noindent  
\settodepth \mylength {gy}%
\begin{tabularx}{\textwidth}{
    |>{\hsize=0.2\hsize}X
    |>{\hsize=0.8\hsize}X
    |
  }
  \hline
  \multicolumn{1}{|@{}p{.2\hsize+\tabcolsep}@{}|}{\raisebox{-\mylength-1pt}{\includegraphics[width=\linewidth]{example-image}}} & foo foggy \\ \hline
  foo & foo \\ \hline
  foo & foo \\ \hline
\end{tabularx}
\end{document}

The 1pt is a guess based on the dimension tabularx reports adding to the height for the first table in the documentation. I assume the author adjusted the height in a way which produced symmetry above and below the text. The result looks about right, given the inaccuracies involved.

Using an m type column in place of the p will half the size of the discrepancies, at the cost of doubling their number.

\multicolumn{1}{|@{}m{.2\hsize+\tabcolsep}@{}|}{\raisebox{-\mylength-1pt}{\includegraphics[width=\linewidth]{example-image}}} & foo foggy \\ \hline

But, as mentioned earlier, professional-quality tables would not be typeset like this so, unless you're using 'invisible' tables simply for alignment (in which case, there are easier methods), this isn't the best approach irrespective of TeX's inaccuracies.

2
  • 2
    Congrats on the upcoming crossing of the 200k rep points mark!
    – Mico
    Commented May 5 at 19:31
  • @Mico Possibly ;).
    – cfr
    Commented May 5 at 19:47
2

With {NiceTabular} of nicematrix and TikZ to place the image after the construction of the array.

\documentclass[12pt]{article}
\usepackage{geometry}
\usepackage{showframe}
\renewcommand*\ShowFrameColor{\color{red}}
\renewcommand\ShowFrameLinethickness{0.25pt}
\usepackage{nicematrix,tikz}
\usetikzlibrary{calc}

\begin{document}

\noindent
\begin{NiceTabular}{XX[9]}[hvlines]
\rule[-1cm]{0pt}{3cm} % reservation of vertical space in the first row for the image
       & bar \\ 
foo    & bar \\ 
foo    & bar \\ 
\CodeAfter
  \tikz 
  \path let \p1 = (1) , \p2 = (2) 
        in node at (1.5-|1.5) {\includegraphics[width =\dimexpr\x2-\x1]{example-image}} ; 
\end{NiceTabular}

\end{document}

You need several compilations.

Output of the above code

1

This version uses an ordinary tabular. Once you compute the width needed for an X column, you can use an p{} column instead. The overlap is achieved using \makebox. valign is used to match the baseline. (see adjustbox manual).

\documentclass[12pt]{article} % '10pt', '11pt, or whatever

\usepackage[showframe]{geometry}
\usepackage[export]{adjustbox}% for valign
\usepackage{graphicx}

\newlength\WW
\setlength\WW{\dimexpr \textwidth-4\tabcolsep}% note no \arrayrulewidth
\divide\WW by 10

\begin{document}
\noindent
\begin{tabular}{|p{\WW}|p{9\WW}|}
\hline
\makebox[\WW]{\includegraphics[width={\dimexpr \WW+2\tabcolsep}, valign=t]{example-image}}
    & bar \\ \hline
foo & bar \\ \hline
foo & bar \\ \hline
\end{tabular}
\end{document}
1

You asked for a tabularx cell, but note that you could also use tblr in which case you don't need to worry about computing the right dimensions because tblr already handles that for you.

enter image description here

\documentclass{article}

\usepackage[a4paper, showframe]{geometry}
\usepackage{tabularray}
\usepackage{lipsum}
\usepackage{graphicx}
\usepackage[export]{adjustbox}

\begin{document}

\noindent
\begin{tblr}{
  colspec = {X[c,0.3\textwidth]X[l]},
  column{1} = {leftsep=0pt, rightsep=0pt},
  rowsep = 0pt,
  rowspec = {Q[m]Q[m]Q[m]},
  hlines = 0.25pt,
  vlines = 0.25pt,
  vspan = even
}
  \includegraphics[width=\linewidth, valign=c]{example-image} & Paragraph no. 1 \\
  \includegraphics[width=\linewidth, valign=c]{example-image} & \lipsum[1] \\
  foo & foo \\
\end{tblr}

\end{document}

You must log in to answer this question.

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