Customize CSS in ggiraph



This post explains how to use the ggiraph package to create interactive graph and how to customize it with additional CSS, with reproducible code and explanations.

For an introduction to ggiraph, check the dedicated post

Interactive section Data to Viz

Libraries and dataset


First we need to load the ggiraph and ggplot2 libraries.

The input dataset is about consumer confidence in 9 different countries at differente dates:

# library
library(ggplot2)
library(ggiraph)
library(tidyverse)

# Create data
data <- read.csv("https://raw.githubusercontent.com/holtzy/R-graph-gallery/master/DATA/dataConsumerConfidence.csv") %>%
  mutate(date = lubridate::my(Time)) %>%
  select(-Time) %>%
  pivot_longer(!date, names_to = "country", values_to = "value") %>%
  na.omit() %>%
  mutate(country = as.factor(country))

Simple line chart with ggiraph


The ggiraph package in R is an extension of the ggplot2 package, designed to simplify the process of creating interactive charts.

It offers a set of function to add interactivity such as geom_point_interactive() for an interactive version of geom_point(), geom_sf_interactive() for an interactive version of geom_sf() etc.

Let’s start with a simple interactive version of this line chart. It uses the geom_line_interactive() function to replace the geom_line() one and make it interactive.

plot <- data %>%
  ggplot(mapping = aes(
    x = date,
    y = value,
    color = country,
    tooltip = country,
    data_id = country
  )) +
  geom_line_interactive(hover_nearest = TRUE) +
  theme_classic()

interactive_plot <- girafe(ggobj = plot)
htmltools::save_html(interactive_plot, "HtmlWidget/geom-line-interactive-1.html")

Change CSS


Although CSS is primarily used for styling web pages, it can also be relevant in customizing visuals in R, especially when dealing with web-based outputs like interactive charts or Shiny applications.

CSS code has the following structure: a property named (such as font-size), a colon (:), and the value of that property (such as 14px). Each element is then separated by a ;.

The easiest way to add CSS in ggiraph is to use the girafe_options() function.

Then we use opts_hover(css = "fill:#ffe7a6;stroke:black;cursor:pointer;") to fill the lines on hover with a given color and change the color of the lines to black.

plot <- data %>%
  ggplot(mapping = aes(
    x = date,
    y = value,
    color = country,
    tooltip = country,
    data_id = country
  )) +
  geom_line_interactive(hover_nearest = TRUE) +
  theme_classic()

interactive_plot <- girafe(ggobj = plot)

interactive_plot <- girafe_options(
  interactive_plot,
  opts_hover(css = "fill:#ffe7a6;stroke:black;cursor:pointer;"),
  opts_selection(type = "single", css = "fill:red;stroke:black;"),
  opts_toolbar(saveaspng = FALSE)
)
htmltools::save_html(interactive_plot, "HtmlWidget/geom-line-interactive-2.html")

Highlight a specific line


When displaying multiple lines in a single chart, it’s easy to end up with a cluttered spaghetti chart. One effective way to enhance readability is by implementing a hover effect that elegantly fades out non-hovered lines while highlighting the selected line.

This can be achieved using CSS with the following properties:

  1. stroke: Change the color of the hovered line (e.g., stroke: #69B3A2;)
  2. stroke-width: Increase the width of the hovered line for emphasis
  3. transition: Add a smooth transition effect (e.g., transition: all 0.3s ease;)
  4. opacity: Reduce the opacity of non-hovered lines (e.g., opacity: 0.5;)
  5. filter: Apply a grayscale effect to non-hovered lines (e.g., filter: grayscale(90%);)
library(hrbrthemes) # for the `theme_ipsum()`

plot <- data %>%
  ggplot(mapping = aes(
    x = date,
    y = value,
    color = country,
    tooltip = country,
    data_id = country
  )) +
  geom_line_interactive(hover_nearest = TRUE) +
  theme_ipsum()

interactive_plot <- girafe(ggobj = plot)

interactive_plot <- girafe_options(
  interactive_plot,
  opts_hover(css = "stroke:#69B3A2; stroke-width: 3px; transition: all 0.3s ease;"),
  opts_hover_inv("opacity:0.5;filter:saturate(10%);"),
  opts_toolbar(saveaspng = FALSE)
)
htmltools::save_html(interactive_plot, "HtmlWidget/geom-line-interactive-3.html")

More advanced usage


plot <- data %>%
  ggplot(mapping = aes(
    x = date,
    y = value,
    color = country,
    tooltip = country,
    data_id = country
  )) +
  geom_line_interactive(hover_nearest = TRUE) +
  theme_classic()

interactive_plot <- girafe(ggobj = plot)

hover_css <- "
  fill: #ffe7a6;
  fill-opacity: 0.5;
  stroke: black;
  stroke-width: 7px;
  stroke-dasharray: 5,5;
  transition: fill-opacity 0.5s, stroke-width 0.5s, stroke-dasharray 0.5s, filter 0.5s;
  filter: drop-shadow(0 0 5px rgba(0,0,0,0.5));
"

interactive_plot <- girafe_options(
  interactive_plot,
  opts_hover(css = hover_css),
  opts_toolbar(saveaspng = FALSE)
)
htmltools::save_html(interactive_plot, "HtmlWidget/geom-line-interactive-4.html")

Combine CSS with other ggiraph features


Since CSS provides an infinite number of possibilities, you can use it to create very original charts!

Hover CSS:

Tooltip CSS:

plot <- data %>%
  ggplot(mapping = aes(
    x = date,
    y = value,
    color = country,
    group = country,
    tooltip = paste("Country:", country, "<br>Date:", date, "<br>Value:", round(value, 2)),
    data_id = country
  )) +
  geom_line_interactive(size = 1.2, hover_nearest = TRUE) +
  geom_point_interactive(aes(size = value), alpha = 0.7) +
  scale_color_viridis_d() +
  scale_size_continuous(range = c(1, 2)) +
  theme_minimal(base_size = 14) +
  labs(
    title = "Interactive Country Data Visualization",
    subtitle = "Try to hover and click on the lines!",
    caption = "R-Graph-Gallery.com",
    x = "Date",
    y = "Consumer Confidence"
  ) +
  theme(
    plot.title = element_text(hjust = 0.5, size = 20, face = "bold"),
    plot.subtitle = element_text(hjust = 0.5, size = 16, face = "italic"),
    legend.position = "none",
    panel.grid.minor = element_blank(),
    panel.background = element_rect(fill = "ivory", color = NA),
    plot.background = element_rect(fill = "ivory", color = NA)
  )

interactive_plot <- girafe(ggobj = plot)

hover_css <- "
  stroke: black;
  stroke-width: 1px;
  r: 8px;
  transition: all 0.3s ease;
"

tooltip_css <- "
  background-color: #2C3E50;
  color: #ECF0F1;
  padding: 10px;
  border-radius: 5px;
  font-family: 'Arial', sans-serif;
  font-size: 14px;
  box-shadow: 0px 0px 10px rgba(0,0,0,0.5);
"

interactive_plot <- girafe_options(
  interactive_plot,
  opts_hover(css = hover_css),
  opts_tooltip(css = tooltip_css, use_fill = TRUE),
  opts_selection(type = "multiple", only_shiny = FALSE),
  opts_zoom(min = 0.5, max = 2),
  opts_toolbar(saveaspng = TRUE, position = "topright", pngname = "country_data_plot"),
  opts_sizing(rescale = TRUE)
)
htmltools::save_html(interactive_plot, "HtmlWidget/geom-line-interactive-5.html")

Going further


You might be interested in:

Related chart types


Grouped and Stacked barplot
Treemap
Doughnut
Pie chart
Dendrogram
Circular packing



❤️ 10 best R tricks ❤️

👋 After crafting hundreds of R charts over 12 years, I've distilled my top 10 tips and tricks. Receive them via email! One insight per day for the next 10 days! 🔥