# Grid - problem with ItemSize being ignored

Bug introduced in 7.0 or earlier and persisting through 10.0.2 or later

I have run into another problem with Grid today.
An explicitly specified ItemSize is being ignored:

dot = Graphics[{Pink, Disk[]}, ImageSize -> 40];

tab = {{"Type", "Name", \[SpanFromLeft], \[SpanFromLeft],
Item[dot, ItemSize -> 2.7],
Item["Esculap",
Alignment ->
Left], \[SpanFromLeft], \[SpanFromLeft]}, {\[SpanFromAbove],
"Dia.", "Spec", \[SpanFromLeft], \[SpanFromAbove],
Item[8.3 "mm", ItemSize -> {3.5, 2.7}, Alignment -> Right],
Item[11, Alignment -> Right], "6.3"}, {Item[dot, ItemSize -> 2.7],
Item["Flycatcher",
Alignment -> Left], \[SpanFromLeft], \[SpanFromLeft],
Item[dot, ItemSize -> 2.7],
Item["Apus",
Alignment ->
Left], \[SpanFromLeft], \[SpanFromLeft]}, {\[SpanFromAbove],
Item[6.9 "mm", ItemSize -> {3.5, 2.7}, Alignment -> Right],
Item[17, Alignment -> Right], "9.8", \[SpanFromAbove],
Item[7.8 "mm", ItemSize -> {3.5, 2.7}, Alignment -> Right],
Item[8, Alignment -> Right], "6.7"}};

Grid[tab,
Spacings -> {Automatic, {{0, -1.1}}},
Alignment -> {Center, Center},
Dividers -> All
]


Please note Item[8.3 "mm", ItemSize -> {3.5, 2.7}, Alignment -> Right] where a vertical ItemSize is explicitly specified, yet it is ignored in the layout.

If the "Spec" cell is not spanned this does not happen:

tab[[2, 4]] = "X";

Grid[tab,
Spacings -> {Automatic, {{0, -1.1}}},
Alignment -> {Center, Center},
Dividers -> All
]


• Is this another bug in Grid?

• Is it still present in version 8?

• How can I best work around it?

-
I can confirm that the output of your code looks just the same in MMA ver. 8.0.4. – m_goldberg Oct 21 '12 at 15:14
@m_goldberg Thanks. I have only recently tried to set up a nice looking Grid with spanned cells and I must say I'm finding it an aggravating experience. – Mr.Wizard Oct 21 '12 at 15:24
Is the title misleading? Can you be sure ItemSize is causing the problem? Would something like "Grid -- nested spanning causing problem" be better? – m_goldberg Oct 21 '12 at 15:58
My point is that ItemSize is being ignored. If you leave out ItemSize then the bottom (twin) row looks like the top one. I was trying to keep the title distinct from this one. – Mr.Wizard Oct 21 '12 at 16:04
Can it be due to your Spacings setting? I find that Spacings -> {Automatic, {{0}, -1.3}} gets me a much better layout. You have to cut away a bit of vertical spacing in the last row only, not in all other rows. – Sjoerd C. de Vries Oct 21 '12 at 19:37

The usual quick-and-dirty workaround when ItemSize does not do what is expected is to wrap contents into an invisible frame. One can use Framed with FrameStyle->None to hide the frame or Pane. In both cases, a magic number is required to convert between line-height of Grid and printers points of Framed/Pane - it is highly platform-specific (see here). The simplified example with Pane:

dot = Graphics[{Pink, Disk[]}, ImageSize -> 40];

magic = 10;

tab = {
{"Type", "Name", \[SpanFromLeft], \[SpanFromLeft], dot,
"Esculap", \[SpanFromLeft], \[SpanFromLeft]},
{\[SpanFromAbove], "Dia.",
"Spec", \[SpanFromLeft], \[SpanFromAbove], 8.3 "mm",
Pane[11, {Automatic, 2.7*magic}, Alignment -> Center], "6.3"},
{dot, "Flycatcher", \[SpanFromLeft], \[SpanFromLeft], dot,
"Apus", \[SpanFromLeft], \[SpanFromLeft]},
{\[SpanFromAbove], 6.9 "mm", 17, "9.8", \[SpanFromAbove], 7.8 "mm",
Item[8, ItemSize -> {Automatic, 2.7}], "6.7"}
};

Grid[tab, Spacings -> {Automatic, {{0, -1.1}}},
Alignment -> {Center, Center}, Dividers -> All]


One can get rid of the overhang (gap with missing dividers) by wrapping Item around the cell:

Item[Pane[11, {Automatic, 2.7*magic}, Alignment -> Center]]


This issue of gaps is only present in version 8. My guess is that as ContentPadding -> True was added to Pane in version 8 only, in version 7 a different behaviour is the default for padding inside Pane that does not introduce these gaps. However, calling the above example with ContentPadding -> False in v8 does not remove the gaps contradily to my expectations.

An almost identical result can be obtained if given cell is wrapped in Framed (note the horizontal increase in size of the cell):

Framed[11, ImageSize -> {Automatic, 2.7*magic}, FrameStyle -> None]


-
This works somewhat better than the workaround I came up with using Spacer. +1 – Mr.Wizard Oct 22 '12 at 8:44
If going this route it may be somewhat cleaner to use Pane[11, {All, 2.7 magic}, Alignment -> Center] – Mr.Wizard Oct 22 '12 at 8:49
True that, I forgot about Pane. Actually one (being fool enough) could try to reimplement Grid by using only Pane, Framed and similar constructs. This would be a hell of a task getting all the boxes to align to each other... – István Zachar Oct 22 '12 at 8:51
My fallback if I cannot wrestle Grid into submission is to construct a Graphics object with Text, Inset, etc. I'm hoping to avoid that. – Mr.Wizard Oct 22 '12 at 8:53
BTW if you look very closely at the example you'll see that the white frame overlaps the divider. It would be better to use FrameStyle -> None I believe. – Mr.Wizard Oct 22 '12 at 8:56

I don't have a real answer, but here are two work-arounds. I don't have any real expectation that you will like either ;-)

Work-around 1

The idea here is that since there are actually two Spec values, the lengend should also have two fileds, each telling the viewer what one of each of the parameters represents.

dot = Graphics[{Pink, Disk[]}, ImageSize -> 40];

tab = {{"Type", "Name", \[SpanFromLeft], \[SpanFromLeft],
Item[dot, ItemSize -> 2.7], Item["Esculap", Alignment -> Left],
\[SpanFromLeft], \[SpanFromLeft]},
{\[SpanFromAbove], "Dia.", "Spec 1", "Spec 2", \[SpanFromAbove],
Item[8.3 "mm", ItemSize -> {3.5, 2.7}, Alignment -> Right],
Item[11, Alignment -> Right], "6.3"},
{Item[dot, ItemSize -> 2.7], Item["Flycatcher", Alignment -> Left],
\[SpanFromLeft], \[SpanFromLeft], Item[dot, ItemSize -> 2.7],
Item["Apus", Alignment -> Left], \[SpanFromLeft], \[SpanFromLeft]},
{\[SpanFromAbove], Item[6.9 "mm", ItemSize -> {3.5, 2.7},
Alignment -> Right],
Item[17, Alignment -> Right], "9.8", \[SpanFromAbove],
Item[7.8 "mm", ItemSize -> {3.5, 2.7}, Alignment -> Right],
Item[8, Alignment -> Right], "6.7"}};

Grid[tab, Spacings -> {Automatic, {{0, -1.1}}},
Alignment -> {Center, Center}, Dividers -> All]


This outputs

Work-around 2

The idea here is that, given there is only one legend slot, all the other sub-tables should have only one corresponding slot. The two values shown in the combined slots should be shown separated by a suitable delimiter.

makeStr = (StringJoin @@ ToString /@ {##}) &;

dot = Graphics[{Pink, Disk[]}, ImageSize -> 40];

tab = {{"Type", "Name", \[SpanFromLeft], Item[dot, ItemSize -> 2.7],
Item["Esculap", Alignment -> Left], \[SpanFromLeft]},
{\[SpanFromAbove], "Dia.", "Spec", \[SpanFromAbove],
Item[8.3 "mm", ItemSize -> {3.5, 2.7}, Alignment -> Right],
makeStr[11, ", ", 6.3]},
{Item[dot, ItemSize -> 2.7], Item["Flycatcher", Alignment -> Left],
\[SpanFromLeft], Item[dot, ItemSize -> 2.7],
Item["Apus", Alignment -> Left], \[SpanFromLeft]},
{\[SpanFromAbove], Item[6.9 "mm", ItemSize -> {3.5, 2.7},
Alignment -> Right],
makeStr[7, ", ", 9.8], \[SpanFromAbove],
Item[7.8 "mm", ItemSize -> {3.5, 2.7}, Alignment -> Right],
makeStr[8, ", ", 6.7]}};

Grid[tab, Spacings -> {Automatic, {{0, -1.1}}},
Alignment -> {Center, Center}, Dividers -> All]


This outputs

-
These are, unsurprisingly, the two options I am aware of. I'm holding my vote for now as I am hoping for some other answer, but it's good that you've documented them. Incidentally you could use makeStr = Row@{##} &;. – Mr.Wizard Oct 21 '12 at 20:26
No, I'm not surprised you were aware of these work-arounds, but I felt they should be explicitly put on the table. You did ask for work-arounds. – m_goldberg Oct 21 '12 at 22:19
Did you actually try your version of makeStr? It was the first thing I thought of, but it didn't work for me. – m_goldberg Oct 21 '12 at 22:22
Indeed I did, and it appears to work in version 7 for this example. How does it fail for you? – Mr.Wizard Oct 21 '12 at 22:26
I have figured out what I did wrong. My version, because of bad typing was makeStr = (Row@{#})&. – m_goldberg Oct 21 '12 at 23:01