11

I've been trying to achieve the following vertical sidebar effect in LaTeX for my resume, but turns out it's far more difficult than I thought (created easily in InDesign):

Sidebar

I've tried everything I could think of — sideways minipages, parboxes, tables, multirows, and on and on, but nothing's been able to replicate it. I've gotten close, but never managed to get the title flush along the top of the table (not to mention the centered horizontal rule). Any insight on implementing this?


For reference, here's my latest attempt at implementing this with a table and multirow (requires XeLaTeX):

\documentclass{article}
\usepackage{fontspec, multirow, rotating, tabularx, xunicode}
\def\Vhrulefill{\leavevmode\leaders\hrule height 0.7ex depth \dimexpr0.4pt-0.7ex\hfill\kern0pt}

\begin{document}
  \begin{tabularx}{\textwidth}{l X}
    & \textbf{Spoken Languages} \\
    & English, Hebrew (fluent in speaking, reading, and writing) \\
    & \\
    & \textbf{Programming Languages} \\
    & Objective-C, C, Ruby, Java, Python, HTML + CSS/SASS + JavaScript/CoffeeScript \\
    & \emph{Familiar with C++, Haskell, PHP} \\
    & \\
    & \textbf{Technologies} \\
    & OS X, iOS, Xcode, Unix/Linux Systems, LaTeX, Shell Scripting, Git, Vim, Jekyll \\
    & \emph{Familiar with Windows, Windows Server, MySQL} \\
    \multirow{-9}{*}{\begin{sideways}\Vhrulefill~skills\end{sideways}} &
\end{tabularx}
\end{document}

That produces the following output:

Sample


Update: Werner's answer is the one I think I'll go with since it fits my needs well; however, I've been trying to get it in a more general form so I can reuse it easily, and I've run into trouble.

I've created a new environment for this, but unfortunately, I can't get the label to align correctly along the top of the body text using the height of the text:

\documentclass{article}
\usepackage{graphicx, tabularx, xcolor}
\usepackage{environ}
\usepackage[margin=1in]{geometry}

\newlength{\sectionheight}
\newlength{\tablewidth}
\NewEnviron{rsection}[3]{%
  \setlength{\tablewidth}{#2}
  \addtolength{\tablewidth}{-1ex}
  \settoheight{\sectionheight}{\begin{tabularx}{\tablewidth}{l #3}\BODY\end{tabularx}}

  \begin{tabularx}{\tablewidth}{l #3}
    \BODY \\
    \raisebox{\normalbaselineskip}{\smash{\rotatebox{90}{%
      \color{black!33}\rule[.5ex]{\sectionheight}{.4pt}\llap{\colorbox{white}{\color{black!66}#1}}
    }}} &
  \end{tabularx}
}

\begin{document}
  \begin{rsection}{education}{0.5\textwidth}{X}
    & \textbf{Binghamton University, State University of New York} \\
    & B.S. — Computer Science · Expected 2016 \\
    & \\
    & Binghamton University Scholars Program \\
    & Binghamton President's Scholars Program
  \end{rsection}
  \begin{rsection}{skills}{0.5\textwidth}{X}
    & \textbf{Spoken Languages} \\
    & English, Hebrew (fluent in speaking, reading, and writing) \\
    & \\
    & \textbf{Programming Languages} \\
    & Objective-C, C, Ruby, Java, Python, HTML, CSS, SASS, JavaScript, CoffeeScript \\
    & \emph{Familiar with C++, Haskell, PHP} \\
    & \\
    & \textbf{Technologies} \\
    & OS X, iOS, Xcode, Unix/Linux Systems, LaTeX, Shell Scripting, Git, Vim, Jekyll \\
    & \emph{Familiar with Windows, Windows Server, MySQL}
  \end{rsection}
\end{document}

For some reason, \settoheight{\sectionheight}{\begin{tabularx}{\tablewidth}{l #3}\BODY\end{tabularx}} doesn't return the right height for the text, so the result looks like this:

Result

I'm expecting the label to look right, and for the tables to align next to each other. Any idea what's going wrong?

4
  • The document cannot be compiled using Latex. It requires Luatex or Xelatex.
    – Vivi
    Commented Nov 19, 2012 at 3:34
  • @Vivi That's true — I use XeLaTeX. Is that an issue? Commented Nov 19, 2012 at 3:40
  • I don't think it is an issue in terms of your question, but when other people try to compile your document they will not be able to unless they use Xelatex or Luatex. I am only saving them the trouble of having to find that out. Sorry, I am not able to help you with your question...
    – Vivi
    Commented Nov 19, 2012 at 3:52
  • Awesome first question! I remember having trouble with sideways stuff in tables some time ... don't think I figured it out.
    – doncherry
    Commented Nov 19, 2012 at 7:11

2 Answers 2

3

Here is a very manual attempt at obtaining the result. Since the vertical rule + text spans 12 rows of the table (in my example), I draw a \rule of length 12\normalbaselineskip, and then rotate it into position:

enter image description here

\documentclass{article}
\usepackage{graphicx, tabularx, xcolor}% http://ctan.org/pkg/{graphicx,tabularx,xcolor}

\begin{document}
  \begin{tabularx}{\textwidth}{l X}
    & \textbf{Spoken Languages} \\
    & English, Hebrew (fluent in speaking, reading, and writing) \\
    & \\
    & \textbf{Programming Languages} \\
    & Objective-C, C, Ruby, Java, Python, HTML + CSS/SASS + JavaScript/CoffeeScript \\
    & \emph{Familiar with C++, Haskell, PHP} \\
    & \\
    & \textbf{Technologies} \\
    & OS X, iOS, Xcode, Unix/Linux Systems, LaTeX, Shell Scripting, Git, Vim, Jekyll \\
    \smash{\rotatebox{90}{%
      \color{black!20}\rule[.5ex]{12\normalbaselineskip}{.4pt}\llap{\colorbox{white}{\color{black!75}skills}}%
      }} & 
      \emph{Familiar with Windows, Windows Server, MySQL}
\end{tabularx}
\end{document}

graphicx provides \rotatebox{<degrees>}{<stuff>} while xcolor allows for changing the text/rule colours. I have foregone multirow since \smash removes the vertical height of its argument.


It is also possible to use zref's savepos module to identify the start/end of the rsection, and insert a rule accordingly:

enter image description here

\documentclass{article}
\usepackage{graphicx, tabularx, xcolor, environ}% http://ctan.org/pkg/{graphicx,tabularx,xcolor,environ}
\usepackage{zref-savepos}% http://ctan.org/pkg/zref
\usepackage[margin=1in]{geometry}% http://ctan.org/pkg/geometry

\makeatletter
% Taken from http://tex.stackexchange.com/a/69076/5764
% \zsaveposx/y is defined since 2011/12/05 v2.23 of zref-savepos
\@ifundefined{zsaveposy}{\let\zsaveposy\zsavepos}{}

\newlength{\tablewidth}
\newcounter{@rsection}
\NewEnviron{rsection}[3]{%
  % #1 = label
  % #2 = tabularx width
  % #3 = column specification
  \setlength{\tablewidth}{#2}%
  \stepcounter{@rsection}% Mark labels top/bottom based on rsection counter
  %
  \noindent\begin{tabularx}{\tablewidth}{l #3}
    \zsaveposy{rsection-top-\the@rsection}% Store top y-position
    \BODY \\[-\normalbaselineskip]% Place content
    \zsaveposy{rsection-bot-\the@rsection}% Store bottom y-position
    \zref@refused{rsection-top-\the@rsection}%
    \zref@refused{rsection-bot-\the@rsection}%
    \smash{\rotatebox{90}{%
      \color{black!33}%
        \rule[.5ex]{\dimexpr\normalbaselineskip+\zposy{rsection-top-\the@rsection}sp-\zposy{rsection-bot-\the@rsection}sp}{.4pt}%
        \llap{\colorbox{white}{\color{black!66}#1}}
    }} &
  \end{tabularx}%
}
\makeatother

\begin{document}
  \begin{rsection}{education}{0.5\textwidth}{X}
    & \textbf{Binghamton University, State University of New York} \\
    & B.S. — Computer Science · Expected 2016 \\
    & \\
    & Binghamton University Scholars Program \\
    & Binghamton President's Scholars Program
  \end{rsection}%
  \begin{rsection}{skills}{0.5\textwidth}{X}
    & \textbf{Spoken Languages} \\
    & English, Hebrew (fluent in speaking, reading, and writing) \\
    & \\
    & \textbf{Programming Languages} \\
    & Objective-C, C, Ruby, Java, Python, HTML, CSS, SASS, JavaScript, CoffeeScript \\
    & \emph{Familiar with C++, Haskell, PHP} \\
    & \\
    & \textbf{Technologies} \\
    & OS X, iOS, Xcode, Unix/Linux Systems, LaTeX, Shell Scripting, Git, Vim, Jekyll \\
   & \emph{Familiar with Windows, Windows Server, MySQL}
  \end{rsection}
\end{document}

In the above example, the labels rsection-bot-\the@rsection and rsection-top-\the@rsection store the y-position (in scaled points/sps) of the table bottom & top, respectively. An appropriate \dimexpr calculates the height of the table and inserts the rule (as before) in the first column.

4
  • I like this answer a lot; it's concise and fits my needs. I've been trying to generalize it though, and I've run into trouble. I've updated my question; any chance you could help? Commented Nov 19, 2012 at 16:27
  • @ItaiFerber: I'll hopefully be able to tackle this later tonight (at work now).
    – Werner
    Commented Nov 19, 2012 at 19:21
  • Hate to be a bother, but just wondering if you could take a stab at it in your spare time. I'd definitely grant you the correct answer... :) Commented Nov 26, 2012 at 6:58
  • @ItaiFerber: I've updated my answer with a zref-style answer, which should work with xelatex. Let me know if this is not sufficient.
    – Werner
    Commented Nov 28, 2012 at 1:20
9

Here's an automated solution, allowing page breaks (in the case the table spans several pages); all you have to do is to enclose the table using the tikzborder environment, providing as mandatory argument the label:

\documentclass{article}
\usepackage{fontspec, tabularx,xunicode}
\usepackage{longtable}
\usepackage{atbegshi}
\usepackage{refcount}
\usepackage{tikz}
\usetikzlibrary{calc}
\usepackage{lipsum}

\newcounter{bordercntr}
\newcounter{borderpages}

\newcommand\tikzmark[1]{%
  \tikz[overlay,remember picture] \node (#1) {};}

\newenvironment{tikzborder}[1]
{%
  \gdef\bordertitle{#1}
  \stepcounter{bordercntr}%
  \tikzmark{start-border}\label{start-border\thebordercntr}%
  \ifnum\getpagerefnumber{start-border\thebordercntr}=\getpagerefnumber{end-border\thebordercntr} \else
    \begin{tikzpicture}[overlay, remember picture]
    \draw [ultra thick,gray]
      let \p1 = (start-border.south), \p2 = (end-border), \p3 = (current page.center) in%
         ( $ (\x3,\y1) + (-.55\textwidth,2pt) $ ) --  ( $ (\x3,\y3) + (-0.55\textwidth,-0.5\textheight-15pt) $ );
    \end{tikzpicture}%
  \begin{tikzpicture}[overlay, remember picture]
    \path let \p1 = (start-border.south), \p2 = (current page.center) in%
node[rotate=90,fill=white,anchor=east,font=\color{black!70}\sffamily] at ( $ (\x2,\y1) + (-.55\textwidth,2pt) $ ) {\bordertitle};
  \end{tikzpicture}
    \setcounter{borderpages} {\numexpr\getpagerefnumber{end-border\thebordercntr}-\getpagerefnumber{start-border\thebordercntr}}\theborderpages
    \ifnum\value{borderpages}>1
      \AtBeginShipoutNext{\tikzborderpage}%
    \fi
  \fi%
}
{\tikzmark{end-border}\label{end-border\thebordercntr}
  \ifnum\getpagerefnumber{start-border\thebordercntr}=\getpagerefnumber{end-border\thebordercntr}
    \begin{tikzpicture}[overlay, remember picture]
    \draw [ultra thick,gray]
      let \p1 = (start-border.south), \p2 = (end-border), \p3 = (current page.center) in
      ( $ (\x3,\y1) + (-.55\textwidth,2pt) $ ) --  ( $ (\x3,\y2) + (-.55\textwidth,10pt) $ );
    \end{tikzpicture}%
  \begin{tikzpicture}[overlay, remember picture]
    \path let \p1 = (start-border.south), \p2 = (current page.center) in%
node[rotate=90,fill=white,anchor=east,font=\color{black!70}\sffamily] at ( $ (\x2,\y1) + (-.55\textwidth,2pt) $ ) {\bordertitle};
  \end{tikzpicture}
  \else
    \begin{tikzpicture}[overlay, remember picture]
    \draw [ultra thick,gray]
      let \p1 = (start-border.north), \p2 = (end-border), \p3 = (current page.center) in
      ( $ (\x3,\y3) + (-.55\textwidth,.5\textheight-6pt) $ ) -- ( $ (\x3,\y2) + (-.55\textwidth,20pt) $ );
    \end{tikzpicture}%
  \fi%
}

\newcommand\tikzborderpage{%
  \begin{tikzpicture}[overlay, remember picture]
    \draw [ultra thick,gray]
      let \p1 = (current page.center) in
      ( $ (\x1,\y1) + (-.55\textwidth,0.5\textheight-15pt) $ ) -- ( $ (\x1,\y1) + (-.55\textwidth,-0.5\textheight) $ );
  \end{tikzpicture}
  \addtocounter{borderpages}{-1}%
  \ifnum\value{borderpages}>1
    \AtBeginShipoutNext{\tikzborderpage}%
  \fi%
}

\begin{document}


\begin{tikzborder}{skills}

\noindent\begin{tabularx}{\textwidth}{X}
     \textbf{Spoken Languages} \\
     English, Hebrew (fluent in speaking, reading, and writing) \\
     \\
     \textbf{Programming Languages} \\
     Objective-C, C, Ruby, Java, Python, HTML + CSS/SASS + JavaScript/CoffeeScript \\
     \emph{Familiar with C++, Haskell, PHP} \\
     \\
     \textbf{Technologies} \\
     OS X, iOS, Xcode, Unix/Linux Systems, LaTeX, Shell Scripting, Git, Vim, Jekyll \\
     \emph{Familiar with Windows, Windows Server, MySQL} \\
\end{tabularx}
\end{tikzborder}

\begin{tikzborder}{expertise}
\begin{longtable}{p{.7\textwidth}}
     \textbf{Spoken Languages} \\
     English, Hebrew (fluent in speaking, reading, and writing) \\
     \\
     \textbf{Programming Languages} \\
     Objective-C, C, Ruby, Java, Python, HTML + CSS/SASS + JavaScript/CoffeeScript \\
     \emph{Familiar with C++, Haskell, PHP} \\
     \\
     \textbf{Technologies} \\
     OS X, iOS, Xcode, Unix/Linux Systems, LaTeX, Shell Scripting, Git, Vim, Jekyll \\
     \emph{Familiar with Windows, Windows Server, MySQL} \\

     \textbf{Spoken Languages} \\
     English, Hebrew (fluent in speaking, reading, and writing) \\
     \\
     \textbf{Programming Languages} \\
     Objective-C, C, Ruby, Java, Python, HTML + CSS/SASS + JavaScript/CoffeeScript \\
     \emph{Familiar with C++, Haskell, PHP} \\
     \\
     \textbf{Technologies} \\
     OS X, iOS, Xcode, Unix/Linux Systems, LaTeX, Shell Scripting, Git, Vim, Jekyll \\
     \emph{Familiar with Windows, Windows Server, MySQL} \\

     \textbf{Spoken Languages} \\
     English, Hebrew (fluent in speaking, reading, and writing) \\
     \\
     \textbf{Programming Languages} \\
     Objective-C, C, Ruby, Java, Python, HTML + CSS/SASS + JavaScript/CoffeeScript \\
     \emph{Familiar with C++, Haskell, PHP} \\
     \\
     \textbf{Technologies} \\
     OS X, iOS, Xcode, Unix/Linux Systems, LaTeX, Shell Scripting, Git, Vim, Jekyll \\
     \emph{Familiar with Windows, Windows Server, MySQL} \\

     \textbf{Spoken Languages} \\
     English, Hebrew (fluent in speaking, reading, and writing) \\
     \\
     \textbf{Programming Languages} \\
     Objective-C, C, Ruby, Java, Python, HTML + CSS/SASS + JavaScript/CoffeeScript \\
     \emph{Familiar with C++, Haskell, PHP} \\
     \\
     \textbf{Technologies} \\
     OS X, iOS, Xcode, Unix/Linux Systems, LaTeX, Shell Scripting, Git, Vim, Jekyll \\
     \emph{Familiar with Windows, Windows Server, MySQL} \\

     \textbf{Spoken Languages} \\
     English, Hebrew (fluent in speaking, reading, and writing) \\
     \\
     \textbf{Programming Languages} \\
     Objective-C, C, Ruby, Java, Python, HTML + CSS/SASS + JavaScript/CoffeeScript \\
     \emph{Familiar with C++, Haskell, PHP} \\
     \\
     \textbf{Technologies} \\
     OS X, iOS, Xcode, Unix/Linux Systems, LaTeX, Shell Scripting, Git, Vim, Jekyll \\
     \emph{Familiar with Windows, Windows Server, MySQL} \\

     \textbf{Spoken Languages} \\
     English, Hebrew (fluent in speaking, reading, and writing) \\
     \\
     \textbf{Programming Languages} \\
     Objective-C, C, Ruby, Java, Python, HTML + CSS/SASS + JavaScript/CoffeeScript \\
     \emph{Familiar with C++, Haskell, PHP} \\
     \\
     \textbf{Technologies} \\
     OS X, iOS, Xcode, Unix/Linux Systems, LaTeX, Shell Scripting, Git, Vim, Jekyll \\
     \emph{Familiar with Windows, Windows Server, MySQL} \\

     \textbf{Spoken Languages} \\
     English, Hebrew (fluent in speaking, reading, and writing) \\
     \\
     \textbf{Programming Languages} \\
     Objective-C, C, Ruby, Java, Python, HTML + CSS/SASS + JavaScript/CoffeeScript \\
     \emph{Familiar with C++, Haskell, PHP} \\
     \\
     \textbf{Technologies} \\
     OS X, iOS, Xcode, Unix/Linux Systems, LaTeX, Shell Scripting, Git, Vim, Jekyll \\
     \emph{Familiar with Windows, Windows Server, MySQL} \\
\end{longtable}
\end{tikzborder}

\end{document}

enter image description here

1
  • I like this solution because it's automated, but unfortunately, it doesn't align along the text like I need it to. It's a bit overkill for my needs, but I appreciate it! Commented Nov 19, 2012 at 16:19

You must log in to answer this question.

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