Why does “fill opacity” affect nodes in the same path?

With the following code

\documentclass[border=3mm,tikz]{standalone}

\begin{document}
\begin{tikzpicture}
\draw[fill=brown] (0,0) rectangle ++(1,1) node[above right]{B};
\draw[fill=brown, fill opacity=0.5] (2,0) rectangle ++(1,1) node[above right]{B};
\draw[fill=brown, fill opacity=0.5] (4,0) rectangle ++(1,1) node[above right, fill opacity=1]{B};
\end{tikzpicture}
\end{document}


the resulting figure is

As you can see, on the middle rectangle fill opacity=0.5 has been applied and the corresponding node is also affected by this option. If I want the result like in rightmost square, fill opacity=1 has to be explicitly applied in the node’s options.

Why does fill opacity on a path affect node contents in the same path?

• pgfmanual Section 23.2 on /tikz/fill opacity: In addition to filling operations, this opacity also applies to text and images. – salviati Mar 24 '15 at 10:39
• Each path command sets up a scope and node inherits some of these general settings. – percusse Mar 24 '15 at 10:59
• @percusse I understand that some path options are inherited by in-same-path-nodes (like drawing color) and others not (like filling color). fill opacity is inherited. Is there any technical reason? – Ignasi Mar 24 '15 at 11:00
• @Ignasi My best bet would be for setting up transparency groups Especially when the node is on the filled area and itself is filled with other colors. – percusse Mar 24 '15 at 11:10
• @Ignasi You could modify fill opacity to behave as you expect by fill opacity/.append style={text opacity=1} – Henri Menke Mar 24 '15 at 11:10

PGF manual Section 14:

Some options only apply to the path as a whole. For example, the color= option for determining the color used for, say, drawing the path always applies to all parts of the path. If several different colors are given for different parts of the path, only the last one (on the outermost scope) "wins".

fill opacity is one of such "global" styles; it is in effect for the entire path. That's why

\draw [fill=teal] rectangle ++ (1,-1)
[fill=brown] rectangle ++(1,1)
[fill=red] rectangle ++(1,-1);


yields three red squares because the last fill=red style wins.

PGF manual Section 23.2:

In addition to filling operations, this opacity (/tikz/fill opacity) also applies to text and images.

That's why the global fill opacity setting also affects the node text in the same path.

Finally, why the "global" style of fill opacity can be "locally" overridden in a node that appears in the same path? PGF manual Section 14 also mentions that

... the nodes are not part of the path in any way. Rather, after everything has been done with the path what is specified by the path options (like filling and drawing the path due to a fill and a draw option somewhere in the specification), the nodes are added in a post-processing step.

So the node is constructed in a different path with styles inheritted from the "parent" path, and these styles can be safely overridden without affecting the parent path.

P.S. You can also set text opacity=1 for opaque texts; it overrides the fill opacity setting for texts only.

• Many thanks for showing text opacity=1. – Sigur Apr 20 '18 at 23:13