Skip to content

legend.key.spacing change the distance between the key and the label #6366

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
Breeze-Hu opened this issue Mar 19, 2025 · 6 comments
Open

Comments

@Breeze-Hu
Copy link

Breeze-Hu commented Mar 19, 2025

Hi!
Currently ggplot provides identity-detailed options for adjusting the properties of each element of the legend. The following options for legend.key.spacing{x/y}, which adjusts the distance of each mini group, and legend.text both work as expected.
ggplot2 3.5.0: Legends - Spacing and margins

(p <- ggplot(mpg, aes(displ, hwy, colour = class)) +
  geom_point() +
  guides(colour = guide_legend(ncol = 2)) 
)

p+  
  theme(
    legend.key.spacing.x = unit(20, "pt"))
Image

But I have a doubt about the legend.key.spacing:

p+
  theme(legend.key.spacing = unit(20, "pt"))
Image

From the result, it looks like the key and label spacing has changed. As legend.text = element_text (margin = margin (l = ...)) has been changed.

Should the distance between key and label change when using legend.key.spacing? I'm not quite sure if this is an intentional feature or a bug.

Best wishes,
Hu

@teunbrand
Copy link
Collaborator

teunbrand commented Mar 19, 2025

Thanks for the report! If memory serves, this was to have the margin correspond to some spacing metric of the legend. I'm not sure that there is a more natural choice than the key spacing metric, but I'll happily entertain alternatives.

Note that the default margin for the legend text is margin(0, 0, 0, 0) and we only set the 'spacing' margin if the user didn't specify these themselves. For example, using legend.text = element_text(margin = margin(0, 0, 0, 0)) will obey those margins.

In addition, for historic reasons, the legend.key.spacing.y isn't adapted when setting legend.key.spacing. If it would adapt, then perhaps the spacing logic for the text margins might make more intuitive sense.

@Breeze-Hu
Copy link
Author

Thanks. These functions (legend.key.spacing.x, legend.key.spacing.y, legend.text and legend.title) already provide very detailed positional control.

In my attempts with the user-specified legend.text parameter you mentioned, I noticed that the ‘spacing’ of legend.title also changed due to the legend.key.spacing adjustment.

p+
  theme(legend.key.spacing = unit(50, "pt"),
        legend.text = element_text(margin = margin(0,0,0,0)))

@teunbrand
Copy link
Collaborator

Yeah that's right, the gap between the title and the rest of the legend is also determined by legend.key.spacing by default. I suppose if you want to set both the x and y spacing without affecting text placement, you should set both the legend.key.spacing.x and legend.key.spacing.y. But is the automatic determination of the text margin something that should be independent of legend.key.spacing, and if so: what would you propose? If not, I may have misunderstood the issue and perhaps a clarification will help.

@Breeze-Hu
Copy link
Author

Breeze-Hu commented Mar 19, 2025

SORRY. indeed I was a bit confused earlier.

Let me summarise some of my thoughts:
Firstly, it is clear that using legend.key.spacing has some unexpected results: legend.key.spacing.x, legend.text, and legend.title are all affected. From the starting case, only legend.key.spacing.y is unchanged (as you mentioned). This doesn't feel very appropriate to me. Personally, I think that once the user has used the function (legend.key.spacing), it is likely that the specific function (legend.key.spacing.x, legend.text, and legend.title) will have to be called again subsequently to make adjustments. legend.key.spacing brings aesthetic 'chaos', as the case may be. : (

For the result expected by legend.key.spacing, from my limited knowledge it could be something like the following:

1. The most straightforward way from the user's point of view is that legend.text, and legend.title are independent. Only legend.key.spacing.x and legend.key.spacing.y are adjusted by this function.

2. A path closer to the current result: all four positions are changed (maybe three at the moment): legend.key.spacing.x and legend.key.spacing.y are directly affected. The margins of legend.text and legend.title will be at a multiple of the adjusted value (derived from the ratio of the user-defined UNIT value to the default position?) to keep the aesthetics consistent.

I hope the content is clearly expressed, and thanks for your work!

Suddenly I realised that the legend.key.spacing command doesn't seem to have anything to do with either legend.key.spacing.x and legend.key.spacing.y... It is used to adjust the relationship between the text (label and title) and the key.😳

It also seems to be a result of the realisation of unity. It seems that I was misled by the theme's help documentation. The three of them were placed together, and I thought it was it to uniformly modify the legend.key.spacing.{x/y}... Sorry about that.😰 (It would be nice if the help documentation was clearer.

@teunbrand
Copy link
Collaborator

the legend.key.spacing command doesn't seem to have anything to do with either legend.key.spacing.x and legend.key.spacing.y

That is not entirely how it works. The legend.key.spacing element is the parent of legend.key.spacing.{x/y}, so the children acquire the parent's value. For historical reasons, guide_legend() overrides legend.key.spacing.y so that the inheritance appears obscured. In contrast, for example legendry::guide_legend_base() does not have this historical constraint and inheritance works as expected.

In addition, it also informs the default text margin for legend.text and legend.title. Is that what you suggest is added to the documentation?

@Breeze-Hu
Copy link
Author

Breeze-Hu commented Mar 19, 2025

Wow, I see!
In that case, I think there needs to be a reminder or encouragement to users in the documentation to try using legend.key.spacing.{x/y}, legend.text and legend.title to avoid unexpected situations.
The legend.key.spacing that can inform the user may have some invisible (or not yet effective) adjustments (legend.key.spacing.{x/y}) that are not explicitly set.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants