I'm using fontawesome icons throughout my Shiny app via the icon
function.
I've downloaded the pro version of fontawesome, and used the instructions here: shinydashboard some Font Awesome Icons Not Working to replace the free version that Shiny is using by default (inside shiny\www\shared\font-awesome
) with my paying version. This works very well locally, and all the pro icons show in my app.
However, when I deploy to shinyapps.io
, it seems like Shiny goes back to using the default version. I did try including my pro directory inside the /www/
folder of my app, but without success. Seems like there is no way to tell the icon()
function to look at a local version of fontawesome, something like icon(...,lib=local)
, or icon(...,lib=path_to_fa)
...
Any help would be very welcome.
The simplest and most reliable way to do this is to:
Put the font-awesome files in a subdirectory of the app, www/fontawesome/
Add the following somewhere to the UI code:
htmlDependency(
name = "font-awesome", version = "99.0",
src = "./www/fontawesome",
stylesheet = "css/all.min.css"
)
Here's an example app that illustrates:
shinyApp(
ui = fluidPage(
"This is a Font-Awesome Pro-only icon: ", icon("acorn"),
htmlDependency(
name = "font-awesome", version = "99.0",
src = "./www/fontawesome", stylesheet = "css/all.min.css"
)
),
function(input, output, session) { }
)
One potential issue with the other method is that if the ui
component contains a call to icon()
, and then there is some dynamically-rendered UI (via renderUI()
and uiOutput()
) which contains a call to my_icon()
that uses an icon that's only in Font-Awesome Pro, then that Pro icon will not show up. The method I showed here will not have that problem.
Here's why the other method will have that problem: When the static ui
for an application is rendered to HTML, it looks for htmlDependency
objects in the ui
, and the newest version of an htmlDependency
for a given name (in this case "font-awesome") "wins". So if there's just a call to icon()
in the code (and no call to my_icon()
, or the explicit htmlDependency()
in my example), then the htmlDependency for Font-Awesome that wins is the one that comes with Shiny, 5.13.0 as of this writing. The browser will request that version of Font-Awesome.
Later, if a renderUI()
inserts a my_icon()
with a Pro icon, the HTML will be sent to the browser along with an htmlDependency
object for Font-Awesome Pro. However, at that point, the browser already has loaded Font-Awesome, and it will not know to load this newer version of it -- Shiny currently is not able to replace the already-loaded version of Font-Awesome with a newer one.
Adding the custom htmlDependency
to the static ui
object makes it so it can be resolved at initial page render time, and the browser knows to load the newer version from the start. The version I used, 99.0
, ensures that this custom version will "win" over any other version of a Font-Awesome htmlDependency
.
The trick was, inside the htmlDependency
call (in icon()
function), to remove package = "shiny"
and replace "www/shared/fontawesome"
by the absolute path to my FA folder (I also updated the version number).
EDIT: to be more precise, below is the (very slightly) modified icon function:
my_icon = function (name, class = NULL, lib = "font-awesome") {
prefixes <- list(`font-awesome` = "fa", glyphicon = "glyphicon")
prefix <- prefixes[[lib]]
if (is.null(prefix)) {
stop("Unknown font library '", lib, "' specified. Must be one of ",
paste0("\"", names(prefixes), "\"", collapse = ", "))
}
iconClass <- ""
if (!is.null(name)) {
prefix_class <- prefix
#if (prefix_class == "fa" && name %in% font_awesome_brands) {
# prefix_class <- "fab"
#}
iconClass <- paste0(prefix_class, " ", prefix, "-", name)
}
if (!is.null(class))
iconClass <- paste(iconClass, class)
iconTag <- tags$i(class = iconClass)
if (lib == "font-awesome") {
htmlDependencies(iconTag) <- htmlDependency("font-awesome",
"5.7.2", "./www/shared/fontawesome/",
stylesheet = c("css/all.min.css"))
}
htmltools::browsable(iconTag)
}
Besides commenting some lines out, the only part I changed is the htmlDependency
call. In the original function, it was:
htmlDependency("font-awesome", "5.3.1", "www/shared/fontawesome", package = "shiny",
stylesheet = c("css/all.min.css", "css/v4-shims.min.css")
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With