Skip to main content
AI in Production 2026 is now open for talk proposals.
Share insights that help teams build, scale, and maintain stronger AI systems.
items
Menu
  • About
    • Overview 
    • Join Us  
    • Community 
    • Contact 
  • Training
    • Overview 
    • Course Catalogue 
    • Public Courses 
  • Posit
    • Overview 
    • License Resale 
    • Managed Services 
    • Health Check 
  • Data Science
    • Overview 
    • Visualisation & Dashboards 
    • Open-source Data Science 
    • Data Science as a Service 
    • Gallery 
  • Engineering
    • Overview 
    • Cloud Solutions 
    • Enterprise Applications 
  • Our Work
    • Blog 
    • Case Studies 
    • R Package Validation 
    • diffify  

How to customise the style of your {shinydashboard} Shiny app

Author: Mandy Norrbo

Published: March 16, 2023

tags: r, shiny

Using {shinydashboard} is great for creating dashboard prototypes with a header-sidebar-body layout. You can quickly mock up a professional looking dashboard containing a variety of outputs, including plots and tables.

However, after a while, you’ll probably have had enough of the “50 shades of blue” default theme. Or, you might have been asked to to follow company branding guidelines, so you need to replace the default colours with custom ones.

This blog will take you through three different options when customising a {shinydashboard}. First, we’ll look at using the colour and theme options available in the package. Then, we’ll show you how to use the {fresh} package to be able to use completely custom colour palettes. Finally, we will look at using custom CSS to give you even more control of the overall style of your dashboard.

Do you require help building a Shiny app? Would you like someone to take over the maintenance burden? If so, check out our Shiny and Dash services.

The {shinydashboard} package

Before we get started with styling our dashboard, let’s do a quick refresher of what {shinydashboard} is and how to use it. {shinydashboard} is a package which provides a simple dashboard layout consisting of a header, sidebar, and body. The code below creates an empty dashboard, using the main layout functions from {shinydashboard}: dashboardHeader(), dashboardSidebar(), and dashboardBody(), all wrapped inside of dashboardPage().

library("shinydashboard")
library("shiny")

ui = dashboardPage(
  dashboardHeader(),
  dashboardSidebar(),
  dashboardBody()
)

server = function(input, output, session) {
  
}

shinyApp(ui, server)

An empty shiny dashboard.

The package is really good at this basic type of layout, and includes ways to enhance it — for example by adding tabs to your app using the menuItem() function, as well as the addition of the box(), infoBox(), and valueBox() functions, offering ways of storing outputs in different kinds of containers.

Sticking to quite a rigid layout is what makes {shinydashboard} so great - you don’t have to fiddle around with adjusting the width and height of divs, deciding if you want a sidebar and which side the sidebar should be on etc. Instead, you can just use the default layout which is enough for most dashboards.

However, this rigidity is also the main weakness of {shinydashboard}. If you want to move beyond the basic layout, it may require hacky solutions and can sometimes be downright impossible.

Despite this, it is possible to customise {shinydashboard} using built-in functions and arguments. Let’s take a look at how using an example dashboard which displays and compares some summary statistics for rental properties in the Bay Area of California, US. All code used in this blog post can be found on our GitHub

Using built-in colours and skins

Our example app currently uses the {shinydashboard} default colours. The only styling I have done is set the fill colour of my bar chart to match the colour of the value boxes.

Example app without styling. Dashboard of rental property prices withgrey and light blue colouring.

The first thing we can customise is the dashboard “skin”, which is the colour of the dashboard header at the top of the app. The skin argument in dashboardPage() can be one of “blue” (the default), “black”, “purple”, “green”, “red”, or “yellow”. We will set the skin to be “purple”:

dashboardPage(
  skin = "purple",
  ...
)

which gives us

Colouring dashboard header with skin argument. Text says “Bay AreaRent Prices” on a purple background.

The other main thing we might want to change the colour of is the value boxes. There is a color argument in the valueBox() function, which has slightly more colour choices than for the skin (15 instead of 6). Luckily, there is a purple in the list of valid colours. For all 6 of the value boxes in the app, we will need to add color = "purple" as an argument:

valueBox(
  color = "purple",
  ...
)

which gives us:

Using the built-in colours and skins in {shinydashboard}, thecolouring is now purple and grey.

Using the {fresh} package

The {fresh} package is an add-on package which helps you style your {shiny} apps, including apps built with {shinydashboard}.

{shinydashboard} is built using AdminLTE, an open source dashboard and control panel theme built on top of Bootstrap. Therefore, functions in {fresh} used to customise {shinydashboard} themes follow the pattern adminlte_*. We will use the adminlte_color() to customise our default colours.

At the top of our app, we need create a new theme my_theme using the create_theme() function. In our theme, we are going to change the default adminLTE colour called “light-blue” to use our company colour instead:

my_theme = create_theme(
  adminlte_color(
    light_blue = "#4898a8"
  )
)

We then need to tell {shinydashboard} to use this theme, by placing a call to use_theme() in the dashboard body.

dashboardBody(
  use_theme(my_theme),
  ...
)

Now, if we change our value boxes to have color = 'light-blue', and remove any skin argument in dashboardPage, we end up with this:

Using the {fresh} package to style {shinydashboard}. The samescreenshot of prices but now with a teal background on information boxesand title.

Being able to use any custom colours is definitely a step up from relying on the built-in colour choices of {shinydashboard}. However, let’s take it even one step further and fully customise the look of our {shinydashboard} using CSS.

Using CSS

CSS (Cascading Style Sheets) is the language used to style HTML elements on any webpage. Normally when you build Shiny apps you don’t have to worry about CSS, which is one of the reasons why Shiny is so easy to get started with. But at some point you’re going to want more control of how your Shiny app looks, and then it’s probably time to learn some CSS.

The main way of including CSS in your Shiny app is by creating a CSS file (a file with the .css extension) and placing it in a folder called www/ in the same folder where your Shiny app lives. We will call this file styles.css by convention.

We are going to use this CSS file to modify two things:

  1. The font of the app: We want to use a custom font Prompt
  2. The colour of the input slider bar: We want it to match the colour of the rest of the app

Once we have identified the elements and the associated properties we want to modify, our CSS file ends up looking like this:

@import url('https://fonts.googleapis.com/css2?family=Prompt&display=swap');

.irs--shiny .irs-bar, .irs--shiny .irs-single {
  border: #4898a8;
  background: #4898a8;
}

body, h2, .main-header .logo {
  font-family: 'Prompt', sans-serif;
}

The first line imports our custom font called Prompt from Google Fonts.

The next four lines select the elements of the slider we want to change, and set the border colour as well as background colour to be our company colour (#4898a8).

The last four lines select the body text, our H2 heading, as well as the header text in the top left corner and set the font to be our custom font.

Finally, for a {shinydashboard}, you will need to reference the CSS file in the dashboard body (similar to where we called use_theme() in the {fresh} example). With a stylesheet called “styles.css”, it would look like this:

dashboardBody(
  includeCSS("www/styles.css"),
  ...
)

Now our input slider has gone from this:

An unstyled slider input. A slider for number of bedrooms going from0-8 which fills in blue and with a blue label showing thenumber.

To this:

Slider input styled with brand colour. A slider for number of bedroomsgoing from 0-8 which fills in teal and with a teal label showing thenumber.

And our font from this:

{shinydashboard} with default font. Bay area rent prices and summarybox with default font styling.

To this:

{shinydashboard} with custom Prompt font. Bay Area rent prices withstyling as described with the CSS edits.

Conclusion

There are many ways to customise a {shinydashboard} Shiny app. If you are content with a few different colours, you can stick to the default colour palettes, but if you want to use custom colours you should consider using the {fresh} package. If you want full control of the look and feel of your dashboard, you might want to consider learning CSS and creating your own stylesheet! Although, if you wanted to create a very custom-looking dashboard, you might be better off not using {shinydashboard} at all…


Jumping Rivers Logo

Recent Posts

  • Start 2026 Ahead of the Curve: Boost Your Career with Jumping Rivers Training 
  • Should I Use Figma Design for Dashboard Prototyping? 
  • Announcing AI in Production 2026: A New Conference for AI and ML Practitioners 
  • Elevate Your Skills and Boost Your Career – Free Jumping Rivers Webinar on 20th November! 
  • Get Involved in the Data Science Community at our Free Meetups 
  • Polars and Pandas - Working with the Data-Frame 
  • Highlights from Shiny in Production (2025) 
  • Elevate Your Data Skills with Jumping Rivers Training 
  • Creating a Python Package with Poetry for Beginners Part2 
  • What's new for Python in 2025? 

Top Tags

  • R (236) 
  • Rbloggers (182) 
  • Pybloggers (89) 
  • Python (89) 
  • Shiny (63) 
  • Events (26) 
  • Training (23) 
  • Machine Learning (22) 
  • Conferences (20) 
  • Tidyverse (17) 
  • Statistics (14) 
  • Packages (13) 

Authors

  • Amieroh Abrahams 
  • Aida Gjoka 
  • Tim Brock 
  • Shane Halloran 
  • Theo Roe 
  • Colin Gillespie 
  • Russ Hyde 
  • Gigi Kenneth 
  • Osheen MacOscar 
  • Sebastian Mellor 
  • Myles Mitchell 
  • Keith Newman 
  • Pedro Silva 

Keep Updated

Like data science? R? Python? Stan? Then you’ll love the Jumping Rivers newsletter. The perks of being part of the Jumping Rivers family are:

  • Be the first to know about our latest courses and conferences.
  • Get discounts on the latest courses.
  • Read news on the latest techniques with the Jumping Rivers blog.

We keep your data secure and will never share your details. By subscribing, you agree to our privacy policy.

Follow Us

  • GitHub
  • Bluesky
  • LinkedIn
  • YouTube
  • Eventbrite

Find Us

The Catalyst Newcastle Helix Newcastle, NE4 5TG
Get directions

Contact Us

  • hello@jumpingrivers.com
  • + 44(0) 191 432 4340

Newsletter

Sign up

Events

  • North East Data Scientists Meetup
  • Leeds Data Science Meetup
  • Shiny in Production
British Assessment Bureau, UKAS Certified logo for ISO 9001 - Quality management British Assessment Bureau, UKAS Certified logo for ISO 27001 - Information security management Cyber Essentials Certified Plus badge
  • Privacy Notice
  • |
  • Booking Terms

©2016 - present. Jumping Rivers Ltd