I'm working on a webmap with R, using Leaflet and Shiny. The map has an absolutePanel in the top right corner, and I would like to position the legend so that it's not all the way in the topright corner, but to the left of the absolutePanel.
Leaflet only accepts one of the four corners as a valid input for the "position" attribute in the addLegend tag. I have previously added custom css tags to the header of the UI page, and I've been exploring the css documentation for formatting the legend, but I'm unable to come up with the proper script to actually override the legend position created by Leaflet. As far as I can tell, the position is set somewhere in the .leaflet .legend
script.
I would prefer to resolve this within the R script, rather than having to modify the web documents produced by it. Haven't seen this issue addressed anywhere else yet. Can anyone better-versed in css and shiny than I cook up a solution for this?
A simplified, reproducible sample script, with an (incorrect) attempt at assigning an absolute position to the legend:
library(shiny)
library(leaflet)
data = data.frame(x = c(1,2,3), y = c(1,2,3))
ui <- fluidPage(
tags$head(tags$style(
type = "text/css",
"#controlPanel {background-color: rgba(255,255,255,0.8);",
".leaflet .legend {
position = absolute;
top = 10px;
right = 100px;}"
)),
leafletOutput(outputId = "map", width="100%"),
absolutePanel(top = 10, right = 10, height = 100, id = "controlPanel",
strong("Put Legend To the Left of Me"))
)
server <- function(session, input, output) {
output$map <- renderLeaflet({
leaflet() %>%
addMarkers(data = data, lat = data$x, lng = data$y) %>%
addLegend(colors = data$x, labels = data$y, title = "Legend")
})
}
shinyApp(ui, server)
There is some simple CSS to correct your placement, but this is highly constructed.
First off, your CSS in the snippet was invalid (no closing curly bracket in the first rule). But the placement in itself would have been hard to maintain, I guess, as absolute positions always are. You can, however, adjust the margins (right, and also top if you want) to shift the corresponding panels over. Be aware that this will always be absolutely pixel based. Your controlPanel
and the legend panel will never be in the same div
, so will never adjust to each other in a natural way. That is why you'd better fix your widths on the contentPanel
to avoid overlaps that could occur when, e.g. you have a different font-sizes.
library(shiny)
library(leaflet)
data = data.frame(x = c(1,2,3), y = c(1,2,3))
ui <- fluidPage(
tags$head(tags$style(
type = "text/css",
"#controlPanel {background-color: rgba(255,255,255,0.8);}",
".leaflet-top.leaflet-right .leaflet-control {
margin-right: 210px;
}"
)),
leafletOutput(outputId = "map", width="100%"),
absolutePanel(top = 10, right = 10, height = 100, width=210, id = "controlPanel",
strong("Put Legend To the Left of Me"))
)
server <- function(session, input, output) {
output$map <- renderLeaflet({
leaflet() %>%
addMarkers(data = data, lat = data$x, lng = data$y) %>%
addLegend(colors = data$x, labels = data$y, title = "Legend")
})
}
shinyApp(ui, server)