Styling each individual page in R Shiny with CSS

I've created an R shiny application and am in the process of adding styling to it. I've incorporated some HTML code and want to customize elements like the background color using CSS. After doing some research online, I learned that I should use the class attribute to separate my CSS. However, when I specify a class for each page, no CSS is displayed at all.

Below is a condensed version of my R shiny application. Any assistance on this matter would be highly appreciated.

library(shiny)

setwd("C:\\Users\\FRSAWG\\Desktop\\Application\\Shiny")

user <- shinyUI(navbarPage("",

tabPanel("Home Page",
       div(class="one",
         div(tags$style("#one body{background-color:blue;color:white;font-family:Arial}"),
            div(HTML("<h1><b><center>Home Page</center></b></h1>"))))),
tabPanel("Glossary",
       div(class="two",
           div(tags$style("#two body{background-color:red;color:white;font-family:Arial}"),
               div(HTML("<h1><b><center>Glossary</center></b></h1>")))))
))

serv <- shinyServer(function(input, output) {})

shinyApp(user, serv)

To clarify, I have assigned one and two as the class names for the respective pages.

Answer №1

UPDATE: A helper function was created using the shinyjs package by Dean Attali to modify CSS elements based on input from R syntax. This eliminates flickering that occurred when toggling the body class.

Below is a working example of how to modify CSS styles based on tab changes:

library(shiny)
library(shinyjs)

## Modify the CSS style of a given selector
modifyStyle <- function(selector, ...) {

  values <- as.list(substitute(list(...)))[-1L]
  parameters <- names(values)

  args <- Map(function(p, v) paste0("'", p,"': '", v,"'"), parameters, values)
  jsc <- paste0("$('",selector,"').css({", paste(args, collapse = ", "),"});")

  shinyjs::runjs(code = jsc)

}

# UI for the app
user <- shinyUI(
  navbarPage(title = "", id = "navtab",
             header = div(useShinyjs()),
             tabPanel("Home Page",
                      div(HTML("<h1><b><center>Home Page</center></b></h1>")),
                      "More text."
             ),

             tabPanel("Glossary",
                      div(HTML("<h1><b><center>Glossary</center></b></h1>")),
                      "More text."
             )
  )
)

# Server for the app
serv <- shinyServer(function(input, output, session) {

  observeEvent(input$navtab, {
    currentTab <- input$navtab # Name of the current tab

    if (currentTab == "Home Page") {
      modifyStyle("body", background = "blue", color = "white", 'font-family' = "Arial")
    }
    if (currentTab == "Glossary")  {
      modifyStyle("body", background = "red", color = "white", 'font-family' = "Arial")
    }
  })

})

shinyApp(user, serv)


The issue with CSS tags can be solved by changing #one to .one and correcting the syntax accordingly. Consider organizing your style tags within tags$head instead of spreading them throughout the code.

Updated example code below:

library(shiny)

user <- shinyUI(navbarPage(
  tags$head(
    tags$style(HTML(".one {background-color: blue; color: white; font-family: Arial}")),
    tags$style(HTML(".two {background-color: red;  color: white; font-family: Arial}"))
  ),

  tabPanel("Home Page", class = "one",
      div(HTML("<h1><b><center>Home Page</center></b></h1>")),
      "More text."
  ),

  tabPanel("Glossary", class = "two",
      div(HTML("<h1><b><center>Glossary</center></b></h1>")),
      "More text."
  )
))

serv <- shinyServer(function(input, output) {})

shinyApp(user, serv)

A solution using the shinyjs package to update the class of the <body> dynamically when tabs change has also been provided. Please refer to the code snippet for implementation details.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Why is the oninput function in JavaScript not functioning properly?

After following a practical video tutorial step by step, I tried to implement the code provided (in HTML and JS) but nothing seems to be working! The code snippet from the tutorial includes: var $count = document.getElementById("count"), $textarea = ...

Update a JQuery function for an input field following an innerHTML command

Using JQuery to check the file size and name from an html file input field can be a useful tool. The input field in question looks like this: <div id="uploadFile_div"> <input name="source" id="imageFile" type="file" style ="border: 1px solid ...

CSS3 variables causing issues

I want to streamline my CSS file by setting up generic variables that can be used throughout to ensure consistency and organization. For example: @shadow: 6px 6px 10px rgba(0,0,0,0.2); .shadow { box-shadow: @shadow inset; } However, when I try to a ...

Attempting to ensure that the social media icons are perfectly centered in between the separators on the page

After adding new menu separators, the alignment of my social media icons has been thrown off and I need them to be centered. I'm not sure why this happened or how to fix it. I attempted to add some CSS but had no success. My website can be found at . ...

Attaching a CSS file to a personalized WordPress widget

After much searching and struggling due to language barriers or lack of PHP knowledge, I couldn't figure out how to achieve this: public function widget( $args, $instance ) { ?> <div style="padding: 0 0 14% 0"> <div class="m ...

What is the best way to add "m" to the URL for redirecting mobile devices?

Having already installed a mobile detecting plugin for WordPress, my next step is to create a script that can direct users to the mobile version of the site. My idea is to replicate every desktop page on the mobile subdomain and simply add "m" at the begi ...

Is it possible to enable CSS margins to collapse across a fieldset boundary in any way?

One interesting CSS behavior is that adjacent vertical margins typically collapse into one another. In other words, the space between elements will be equal to the larger margin instead of the sum of both margins. Interestingly, fieldset elements do not f ...

Incorporating fresh JSON information into an established database

I'm currently facing an issue with adding new data (from JSON) to an existing table using jQuery. Within my HTML, there's a sample table structure like this: <table data-role="table" data-mode="columntoggle" class="ui-responsive" data-column ...

Add a new class to an element located in a separate div using JavaScript

$(document).ready(function() { $('.btn').click(function() { $(this).parent().addClass('show'); }); }) <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div clas ...

I am wondering how to use the value assigned to a variable's textContent as an argument for player input in my JavaScript code

i am currently developing a JavaScript project to create a user interface for my rock, paper, scissors game. Currently, the game only runs in the console and prompts the player for input. So far, I have implemented three buttons (one each for rock, paper, ...

Inquiries regarding jQuery's functionality and efficiency

I was wondering about the best way to improve performance? Would it be more efficient to have two images written in HTML, one visible and one hidden, and then use jQuery to toggle their display (hiding the visible one and showing the hidden one)? <img ...

Having trouble with input functionality on iPad due to a CSS, LI, div, or clipping issue?

https://i.sstatic.net/muMSG.png One challenge I am facing is related to several inputs housed within an LI and div that are sortable using jQuery. The problem arises specifically on the iPad when attempting to click into the inputs to enter information - ...

Is there a way for me to generate a placeholder that relies on a specific number of past values from a different variable?

Is there a way to create a new variable that depends on all previous values of another variable, with the number of previous values being arbitrary? Here is an example of the data: library(data.table) dt <- data.table(from = as.Date(c("20020101", "200 ...

What is the difference in speed between drawing on a transparent canvas and determining if a point is transparent compared to determining if a point is within a complex polygon?

I'm curious if anyone has done research on adding event support to a game engine. Specifically, I am working on incorporating pixel-perfect hover over 2D object event support into my own game engine. I am exploring different ways of achieving this eff ...

Access an HTML page programmatically using JavaScript

Make sure to have a confirmation window pop up before submitting the form, and after confirming submission (by clicking OK), redirect to a confirmation page. Here's an example code snippet: <button type="submit" value="Save" id="Save" onclick="cl ...

What could be causing the page to automatically scroll to the bottom upon loading?

My experience with this bootstrap/jquery page in Firefox (v39, latest updates installed) has been unusual as it always seems to jump to the bottom of the page upon clicking. Upon inspecting the code, I couldn't find any JavaScript responsible for thi ...

Submitting the form with a target of _blank will result in the form being submitted on both a

I am currently working on a form that includes both a "Submit" button and a "Preview" button. While the submit button is functioning correctly, I am experiencing an issue with the Preview button. When clicked, it opens up a new page with the preview as in ...

Issue with syntax when transferring an HTML element from the #div to the body

Attempting to duplicate an element and remove the original because of a z-index issue in IE. Planning to use conditional comments: <!--[if lte IE 7]> <script type="text/javascript"> $(document).ready(function() { var callCenter ...

Customizing data from AJAX responses

Using PHP, I am receiving data as an object and passing it through a mustache template to create a table. My inquiry is about controlling the row breaks for my data. Is there a way to insert a <tr> after every 3 <td> without using JavaScript? ...

Avoid altering the Summernote HTML WYSIWYG editor page due to content CSS

We are currently utilizing the Summernote wysiwyg editor to review and preview html content, some of which contains external stylesheet references. This css not only affects Summernote itself but also alters the styling of the parent page where Summernote ...