Introduction to Sass

Timothy Mastny

2018-08-14

CSS styling for R Markdown and Shiny allows users to completely customize the appearance of their documentations and dashboards.

However, for some Shiny apps and R packages like gt, styling needs to be dynamically generated based on user input.

The sass R package facilitates dynamic styling by compiling the CSS extension language Sass, which allows CSS to be parameterized with variables, functions, and calculations.

This article will briefly demonstrate how to compile custom CSS in a live Shiny to change styling in response to user input.

Variables

Sass variables are key to generating dynamic CSS, because they define the components of the styling that can be changed during compilation.

It is best practice to define your variables separately, and then import them into the main Sass file. For example, we’ll define a color variable and use it to set the body’s background color.

/* _variables.scss */
$color: #FFFFFF;
/* new-style.scss */
@import 'variables';
body {
  background-color: $color;
}

The following shiny app will demonstrate this example. We’ll use Dean Attali’s colourpicker to choose a color and write it to _variables.scss.

Then the app compiles new-style.scss and renders the new style.

Functions

If we choose a background color that is too dark, we won’t be able to read the title. Therefore, the font color must depend on the background color.

Sass offers many built-in functions that help with dynamic styling, and you can always write your own.

/* _variables.scss */
$color: #FFFFFF;
/* new-style.scss */
@import 'variables';
body {
  background-color: $color;
}

/* https://stackoverflow.com/a/3943023/6637133 */
@function font-color($color) {
  @return if(
    red($color) * 0.299 + green($color) * 0.587 + blue($color) * 0.114 > 186,
    #000000, #ffffff
  );
}

h1 {
  color: font-color($color);
}

In this shiny example app, the font color now depends on the background color, switching between black and white as necessary.

Resizing

Since Sass is fully CSS compatible, any styling option is available, including dimensions like height and width.

In this example app we’ll change the width of the image based on a slider:

/* _variables.scss */
$color: #FFFFFF;
$width: 100;
/* new-style.scss */
@import 'variables';
body {
  background-color: $color;
}

// https://stackoverflow.com/a/3943023/6637133
@function font-color($color) {
  @return if(
    red($color) * 0.299 + green($color) * 0.587 + blue($color) * 0.114 > 186,
    #000000, #ffffff
  );
}

h1 {
  color: font-color($color);
}

.shiny-plot-output {
  max-width: percentage($width / 100);
}

CSS Formatting

Sass can also format the CSS output with different indentation styles.

Here we’ll convert the readable Sass to minified CSS.

new_style <- "
  $color: #FFFFFF;
  $width: 100;

  body {
    background-color: $color;
  }

  // https://stackoverflow.com/a/3943023/6637133
  @function font-color($color) {
    @return if(
      red($color) * 0.299 + green($color) * 0.587 + blue($color) * 0.114 > 186,
      #000000, #ffffff
    );
  }

  h1 {
    color: font-color($color);
  }

  .shiny-plot-output {
    max-width: percentage($width / 100);
  }
"
library(sass)
sass(new_style, options = sass_options(output_style = "compressed"))
body{background-color:#fff}h1{color:#000}.shiny-plot-output{max-width:100%}