# tikzpicture / How do I increase the vertical spacing between 2 Rectangles when the text is outside?

I'm trying to make a bar graph with the text above its corresponding rectangle but I'm not able to change the vertical spacing between each rectangle.

Here's the code snippet:

\documentclass{standalone}

\RequirePackage{tikz}

\definecolor{white}{RGB}{255,255,255}
\definecolor{mainblue}{HTML}{0E5484}
\definecolor{maingray}{HTML}{B9B9B9}

\begin{document}

\newcommand\skills[1]{
\renewcommand{\skills}{
\begin{tikzpicture}
\foreach [count=\i] \x/\y in {#1}{
\draw[fill=maingray,maingray] (0,\i) rectangle (6,\i+0.4);
\draw[fill=white,mainblue](0,\i) rectangle (\y,\i+0.4);
\node [above right] at (0,\i+0.4) {\x};
}
\end{tikzpicture}
}
}

\skills {{C++ / 4}, {JavaScript, HTML, CSS / 4}, {Java / 6}}
\skills % Needed to output the text

\end{document}


Basically what I'm trying to do is have a for-each loop for every skill (e.g. Java) since I have more than those 3 and typing it in manually takes forever.

The problem now is that the rectangles are drawn by \draw and the node is the text.

I've tried some shenanigans with:

\usetikzlibrary{positioning} and \begin{tikzpicture}[node distance = 1cm] ...


but that's exclusively for nodes, so not my rectangles but only the text.

The best idea would be probably to make the rectangle become a node as well, including the text, but I don't know how to do that.

If anyone knew how to add some spacing I would appreciate it!

Welcome to TeX.SE!


Note: don't forget to type C\# for a skill such as C#, because the # character is special for TeX (it is used for parameter tokens and can't be input as is in text).

For the positioning of labels relatively to the “skills bars”, I use anchor=base west which ensures that the vertical distance from a label baseline to the corresponding skill bar doesn't depend on whether the label text contains descenders (letters like p, q or j that extend below the baseline). That wouldn't be the case with your above right. Also, I added inner sep=0, otherwise there is horizontal and vertical padding around the node text (the horizontal padding implies that the node text wouldn't be quite left-aligned with the bar—this is clearly visible on your screenshot).

# Basic solution that keeps your rectangle commands

This is close to your code, but has the few improvements mentioned above.

\documentclass{article}
\usepackage{tikz}
\usepackage{xcolor}

\definecolor{mainblue}{HTML}{0E5484}
\definecolor{maingray}{HTML}{B9B9B9}

% Make sure no loaded package defines \skills
\newcommand{\skills}{}

\newcommand*{\declareskills}[1]{%
\renewcommand*{\skills}{#1}%
}

\newcommand*{\skillstretchfactor}{1.2} % vertical positioning

\newcommand{\typesetskills}{%
\begin{tikzpicture}
\foreach [count=\i] \name/\score in \skills {
\pgfmathsetmacro{\vpos}{-\skillstretchfactor*\i}
\filldraw[maingray] (0,\vpos) rectangle (6,\vpos+0.4);
\filldraw[mainblue] (0,\vpos) rectangle (\score,\vpos+0.4);
\node[inner sep=0, anchor=base west] at ([yshift=0.8ex]0,\vpos+0.4) {\name};
}
\end{tikzpicture}%
}

\begin{document}

\declareskills{{C++ / 4}, {JavaScript, HTML, CSS / 4}, {Java / 6}}
\typesetskills % Print the skills diagram

\end{document}


# Solution with the rectangle split shape

In this second solution, each rectangle is a node of shape rectangle split, consisting of two parts (the first filled with mainblue, the second with maingray, as you guessed). The width and height of the skill bars can be configured with \skillbarwidth and \skillbarheight, the maximal score (corresponding to 100% of a skill bar width) with \skillmaxscore.

\documentclass{article}
\usepackage{xcolor}
\usepackage{tikz}
\usetikzlibrary{shapes.multipart}

\definecolor{mainblue}{HTML}{0E5484}
\definecolor{maingray}{HTML}{B9B9B9}

\newdimen\scorewidth
\newlength{\skillbarwidth}
\newlength{\skillbarheight}

% Make sure no loaded package defines \skills
\newcommand{\skills}{}

\newcommand*{\declareskills}[1]{%
\renewcommand*{\skills}{#1}%
}

\newcommand*{\skillstretchfactor}{1.2} % vertical positioning
\setlength{\skillbarwidth}{6cm}
\setlength{\skillbarheight}{12pt}
\newcommand*{\skillmaxscore}{6}

\newcommand*{\oneskill}[3]{%
% The 'rectangle split' (with two parts)
\node[skillstyle={#2}] (skill-\i) at (0, -\skillstretchfactor*#3)
{
% Length of the score rectangle. It needs to be set globally if one wants
% to use it after \nodepart{second} (the current group will be finished).
\global\scorewidth=\dimexpr \skillbarwidth*(#2)/\skillmaxscore\relax
\phantom{\rule{\scorewidth}{\skillbarheight}}%
% Complementary width for the second part
\nodepart{second}\kern\dimexpr\skillbarwidth - \scorewidth\relax
};
% The label
\node[inner sep=0, anchor=base west] at ([yshift=0.8ex]skill-\i.north west)
{#1};
}

\newcommand{\typesetskills}{%
\begin{tikzpicture}[skillstyle/.style={
inner sep=0,
rectangle split, rectangle split horizontal, rectangle split parts=2,
rectangle split ignore empty parts,
rectangle split part fill={mainblue, maingray}
}]

\foreach [count=\i] \name/\score in \skills {
\oneskill{\name}{\score}{\i}
}
\end{tikzpicture}%
}

\begin{document}

\declareskills{{C++ / 4}, {JavaScript, HTML, CSS / 4}, {Java / 6}}
\typesetskills % Print the skills diagram

\end{document}


The output is the same as in the above screenshot.

• That's exactly what I was looking for, thank you very much! – RaCara Jul 23 '19 at 18:00
• Glad to hear that. I've simplified the code in both examples, swapped them to start with the simpler one, and added \skillbarwidth and \skillbarheight length parameters to the example that uses the rectangle split shape. – frougon Jul 23 '19 at 20:08