25

I want to put some small boxes around certain words in a paragraph. The boxes will never contain more than one word.

The \ovalbox command described in the fancybox documentation is close to what I need. However, I found some problems:

  • The rounded corners do not line up with the sides perfectly.
  • Text to the left and right in the paragraph are pushed away.
  • The spacing between lines in the paragraph is increased vertically.

I would like to create boxes which:

  • Adjust horizontally to fit the width of the text inside.
  • Have rounded or beveled corners.
  • Can be filled with a solid color.
  • Will not cause any text inside or around the box to move.
  • Will not impact the vertical spacing of lines.
3

4 Answers 4

36

You can use TikZ with the overlay option and a correct anchor. That would look like this:

\documentclass{article}
\usepackage{tikz}
\newcommand\mybox[2][]{\tikz[overlay]\node[fill=blue!20,inner sep=2pt, anchor=text, rectangle, rounded corners=1mm,#1] {#2};\phantom{#2}}
\begin{document}
   \noindent
   this is some text \mybox[fill=blue!20]{box} text\\
   this is some text box text
\end{document}

You can specify extra options (like I have done here for the color). By using the overlay option and the text anchor we ensure correct placement and no influence on spacing. The phantom is added to get the normal spacing for the content of the box. This is the result of the example code:

TikZ text box

Edit: To show that the vertical spacing is not affected either, consider the following:

\documentclass{article}
\usepackage{tikz}
\newcommand\mybox[2][]{\tikz[overlay]\node[fill=blue!20,inner sep=2pt, anchor=text, rectangle, rounded corners=1mm,#1] {#2};\phantom{#2}}
\begin{document}
  \begin{minipage}{0.4\textwidth}
    \noindent
    this is some text \mybox[fill=blue!20]{box} text\\
    this is some text box text
  \end{minipage}
  \begin{minipage}{0.4\textwidth}
    \noindent
    this is some text box text\\
    this is some text box text
  \end{minipage}    
\end{document}

Which results in:

TikZ text box vertical spacing

14
  • 2
    \def\mybox[#1]#2 would force the "optional" argument, so \newcommand\mybox[2][] would be better. Commented Nov 28, 2011 at 14:27
  • @MartinScharrer: You are absolutely correct. I have modified the answer to reflect this. The [fill=blue!20] is now of course also optional on the \mybox command. Commented Nov 28, 2011 at 14:33
  • 1
    @Herbert: With vertical spacing I was referring to the vertical space between lines as the OP mentions. The vertical size of the box is indeed dependent on what is inside. If this is unwanted you could add text depth=0pt as an option to the node. This does not fix it entirely though. There are multiple options, the easiest is to set text height=1.5ex. This way you will have uniform box height. Commented Nov 28, 2011 at 16:07
  • 1
    Like it says in the answer: "The phantom is added to get the normal spacing for the content of the box". Basically, because the node is placed in 'overlay mode', it has 0 size when being placed. But we don't want the next word to overlap, so we add a phantom to take up the space that the word would normally take up without actually printing the word. Try removing the phantom and see what happens. (It's been a while since I used any of this, just saw your comment. So I'm really hoping this is actually true... Pretty sure it is :)) Commented Dec 1, 2015 at 9:41
  • 1
    @MedVall, the #1 takes the value of the optional arguments. In the example I use fill=blue!20, which is superfluous because I already set it in the node command. Anyway, this value for #1 is added in the optional part of the node command. So you can give it a set of comma-separated arguments that the node command understands. Commented Feb 10, 2016 at 12:50
12

My solution needs no special macros. No TikZ, no PSTricks. Only \pdfliteral primitive is used. And you can define \def\pdfliteral#1{\special{pdf:literal #1}} if \pdfliteral isn't available (for example in XeTeX).

\def\mybox#1{\leavevmode \setbox0=\hbox{#1}%
   \dimen0=\wd0 \edef\posxA{\expandafter\ignorept\the\dimen0 \space}%
   \hbox{\kern3pt\pdfliteral{q .8 .8 1 rg .8 .8 1 RG .9963 0 0 .9963 0 0 cm 1 j 1 J 6 w
                             0 0 m 0 5 l \posxA 5 l \posxA 0 l 0 0 l B Q}%
         \box0 \kern3pt}%
}
{\lccode`\?=`\p \lccode`\!=`\t  \lowercase{\gdef\ignorept#1?!{#1}}}

This is a \mybox{test} of my \mybox{box}.

\bye

roundbox

3
  • Where/How do you define the colors? For example, what would be the settings for light gray?
    – JPMD
    Commented Sep 27, 2021 at 13:04
  • The color is defined in RGB color model in my example: 0.8 red, 0.8 green, 1 blue. For fills (rg) and the same for strokes (RG), see ".8 .8 1 rg .8 .8 1 RG". If you want light gray, then you can use GRAY color model (g for fills, G for strokes), for example ".9 g .9 G".
    – wipet
    Commented Sep 28, 2021 at 18:13
  • Cool! thank you!
    – JPMD
    Commented Sep 29, 2021 at 15:26
10

This kind of boxes can be done with extrude option from tcolorbox. A little example adapted from tcolorbox documentation:

\documentclass{article}
\usepackage[most]{tcolorbox}

\newtcbox{\mybox}[1][]{enhanced, colframe=blue, colback=blue!15, 
       frame style={opacity=0.25}, interior style={opacity=0.25}, 
       nobeforeafter, tcbox raise base, shrink tight, extrude by=1mm, #1}

\begin{document}
Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
Ut \mybox[extrude bottom by=2cm]{purus} elit, vestibulum ut, \mybox{placerat} ac, 
\mybox[extrude top by=2mm]{adipiscing} vitae, \mybox[extrude left by=5mm, extrude 
bottom by=2mm]{felis}. Curabitur dictum gravida mauris. \mybox{Nam} arcu libero,    
nonummy eget, consectetuer id, vulputate a, magna.
\end{document}

enter image description here

4

Basically similar to the solution given by Roelof Spijker. I suggest handling the optional argument differently, and use a \strut to ensure consistent box size while not changing the line spacing:

\documentclass{article}

\usepackage{tikz}

\newcommand\mmybox[2][fill=blue!20]{%
    \tikz[baseline]\node[%
        inner ysep=0pt, 
        inner xsep=2pt, 
        anchor=text, 
        rectangle, 
        rounded corners=1mm,
        #1] {\strut#2};%
}

\begin{document}
   \noindent
   this is some text \mmybox{Box} text\\
   this is some text box text
\end{document}

The results:

Sample of boxed text

You must log in to answer this question.

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