5

I want to add a image as background of a single cell of a table, such that the background image is scaled to the actual size of the cell. However, I could not figure out how to do it. I tried using tcolorbox and minipages, but both without success.

Something like in the following example would be perfect.

\documentclass{article}

\begin{document}
Some text before.

\begin{tabular}{|p{2cm}|p{2cm}|p{2cm}|}
\hline
    1 & 2 & 3 \\\hline
    4 & \AddCellBackground{image} 5 & 6 \\\hline
    7 & 8 & 9 \\\hline
\end{tabular}
Some more text after the table.
\end{document}
W. Alpha
  • 347

4 Answers4

6

In your case, where the width of the table cell is given by the static width of a p-column you can use something like:

\documentclass{article}
\usepackage{mwe}
\usepackage{picture}
\newcommand*\AddCellBackground[4][\tabcolsep]{%
  \unskip\begin{picture}(0,0)
    \put(-#1,-\dp\strutbox){\includegraphics[width=\dimexpr
      #2+\dimexpr #1*2\relax\relax,height=#3]{#4}}%
  \end{picture}\ignorespaces
}
\begin{document}
Some text before.

\begin{tabular}{|p{2cm}|p{2cm}|p{2cm}|}
\hline
    1 & 2 & 3 \\\hline
  4 & \AddCellBackground{2cm}{\baselineskip}{example-image} 5 & 6 \\\hline
    7 & 8 & 9 \\\hline
\end{tabular}
Some more text after the table.
\end{document}

enter image description here

If the contents of the cell will also become an argument of \AddCellBackground several additional formatting could be done, e.g., for centering the cell contents. But in this case you also could use a new column type B (for background):

\documentclass{article}
\usepackage{mwe}
\usepackage{picture}
\usepackage{array}
\usepackage{ragged2e}
\newcolumntype{B}[4]{%
  >{%
    \RaggedRight
    \begin{picture}(0,0)
        \put(0,\dimexpr\ht\strutbox-#2\relax){\hskip-\tabcolsep\includegraphics[width=\dimexpr
        #1+2\tabcolsep\relax,height=#2]{#3}}%
    \end{picture}%
    \begin{minipage}[t]{#1}#4\strut\ignorespaces
    }%
    p{#1}%
  <{\unskip\strut\end{minipage}}
}
\begin{document}
\begin{tabular}{|p{2cm}|p{2cm}|p{2cm}|}
\hline
    1 & 2 & 3 \\\hline
  4 &
      \multicolumn{1}{B{2cm}{3\baselineskip}{example-image}{\RaggedRight}|}{some
      more than one word} & 6 \\\hline
   4 & \multicolumn{1}{B{2cm}{3\baselineskip}{example-image}{\Centering}|}{some
       more than one word} & 6 \\\hline
   4 &
       \multicolumn{1}{B{2cm}{3\baselineskip}{example-image}{\RaggedLeft}|}{some
       more than one word} & 6 \\\hline
   7 & 8 & 9 \\\hline
\end{tabular}
\end{document}

multiline example with different alignment

But if the cell width is not given by a static value, you would have to measure out the widest cell of the column (e.g. using \settowidth).

Schweinebacke
  • 26,336
3

Here is a version that can cope with multi-line cell contents. I used tikz overlay to put the picture in the background. The rest is scaling. I have assumed a fixed width of the cell, e.g. p{2cm}. If it is variable ther are some ways to find the width at Measure the column width of a table, but it becomes more complicated.

\documentclass{article}
\usepackage{tikz}
\usepackage{graphicx}
\usepackage{calc}
\newcommand\AddCellBackground[3]{% {width}{image}{contents}
  \sbox0{%
    \begin{tabular}[b]{p{#1}}\hline
      #3
    \end{tabular}}
  \tikz[overlay]{\node at (-\tabcolsep+0.5\wd0,-0.5\dp0+0.5\ht0-0.5\fboxrule){%
      \includegraphics[width=\wd0,height=\ht0+\dp0-0.5\fboxrule]{#2}};}%
  #3}

\begin{document}
Some text before.

\begin{tabular}{|p{2cm}|p{2cm}|p{3cm}|}
\hline
    1 & 2 & 3 \\\hline
    4 & 5 & \AddCellBackground{3cm}{example-image}{A longer cell contents that needs more space} \\\hline
    4 & \AddCellBackground{2cm}{example-image}{5} & 6 \\\hline
    7 & 8 & 9 \\\hline
\end{tabular}

Some more text after the table.
\end{document}

enter image description here

EDIT

If the cell contents should be centered it is best to define a new column type with the array package. Then a centered version of the \addCellBackground can be done:

\usepackage{array}
\newcolumntype{C}[1]{>{\centering\arraybackslash}m{#1}}
\newcommand\AddCellBackgroundCenter[3]{% {width}{image}{contents}
  \sbox0{%
    \begin{tabular}[b]{C{#1}}\hline
      #3
    \end{tabular}}
  \sbox1{#3}
  \tikz[overlay]{\node at (0.5\wd1,-0.5\dp0+0.5\ht0-0.5\fboxrule){%
      \includegraphics[width=\wd0,height=\ht0+\dp0-0.5\fboxrule]{#2}};}%
  #3}

Here the image is inserted just before the text so the width of the actual text also comes into play. That means that this version does not work for multi-row cell content. The table with centered cells become (where the two first columns are centered and the last left aligned):

\begin{tabular}{|C{2cm}|C{2cm}|p{3cm}|}
\hline
    1 & 2 & 3 \\\hline
    4 & 5 & \AddCellBackground{3cm}{example-image}{6} \\\hline
    4 & \AddCellBackgroundCenter{2cm}{example-image}{5} & 6 \\\hline
\end{tabular}

enter image description here

StefanH
  • 13,823
  • Your solution almost works, but in the case if the content is centered using \AddCellBackground{2cm}{example-image}{\centering 5} it is not working anymore. Any solutions? – W. Alpha Aug 04 '17 at 10:47
  • @W.Alpha I have added a version for centered cells. The centering should not be done using \centering, it is better to define a new column type with the array package. – StefanH Aug 04 '17 at 11:31
  • This works only, if the cell with the background is the highest cell in that table row. This is the reason I've not used measuring for the cell contents but a parameters for the width and the height in my answer. – Schweinebacke Aug 04 '17 at 12:57
  • @Schweinebacke, That makes it a bit more complicated. To say the least. – StefanH Aug 04 '17 at 13:08
  • @Schweinebacke, I could not figure out how to use your solution with multi-row or centered cell content. I would be glad to have a solution supporting both. – W. Alpha Aug 04 '17 at 13:18
  • @W.Alpha The example in your question does not show multi-row neither centered cell contents. – Schweinebacke Aug 04 '17 at 13:46
  • @W.Alpha If you want to comment my answer, please add the comment below my answer. – Schweinebacke Aug 04 '17 at 14:26
0

Below uses matrix of nodes to create table instead of tabular environment.

Here is another way using tikz.

\documentclass{article}
\usepackage{tikz}
\usepackage[skins]{tcolorbox}
\usetikzlibrary{matrix}

\begin{document}
    Some text before. 

    \tikzset{ 
        table/.style={
            matrix of nodes,
            row sep=-\pgflinewidth,
            column sep=-\pgflinewidth,
            nodes={
                rectangle,
                draw=black,
                align=center
            },
            nodes in empty cells,
            %%
            column 2/.style = {
                nodes={minimum width = 5em},
            },
        }
    }


    \begin{tikzpicture}
    \matrix (m) [table]{
        1 & 2 & 3 \\
        4 & 5 & 6 \\
        7 & 8 & 9 \\};
    \node[minimum width=5em, fill overzoom image=redblock] at (m-2-2){5};
    \end{tikzpicture}

    Some more text after the table.
\end{document}

table with one cell filled with image

Adarsh
  • 763
0

With {NiceTabular} of nicematrix, you can easily fill any zone of merged cells (that is to say any \Block) with one of the patterns provided by Tikz.

You can also fill the \Block with an image. In the following example, the image has been provided by the package mwe but it's possible to use a image which would be more 'pattern-like'.

\documentclass{article}
\usepackage{nicematrix}
\usepackage{tikz}
\usetikzlibrary{patterns}
\usepackage{mwe} % for the image "example-image"

\tikzset { image/.style = { path picture = { \node at (path picture bounding box.center) { \includegraphics{#1} } ; } } }

\begin{document}

\begin{NiceTabular}{cccc}[hvlines] one & two & three & four \ five & \Block[tikz={pattern=fivepointed stars}]{2-2}{} & & six \ seven & & & nine \end{NiceTabular}

\vspace{1cm}

\begin{NiceTabular}{cccc}[hvlines] one & two & three & four \ five & \Block[tikz={image=example-image}]{2-2}{} & & six \ seven & & & nine \end{NiceTabular}

\end{document}

You need several compilations (because of the PGF/Tikz nodes).

Output of the above code

F. Pantigny
  • 40,250