Imola’s main goal it to give you the tools to work with CSS Flex and CSS Grid directly from R as an alternative to bootstrap’s columns
and rows
.
Using imola can be as simple as using a template in your dashboard, or as deep as building a fully custom layout, complete with different views for different screen sizes.
In addition to the convenient wrapper functions for CSS Flex and CSS Grid, imola also includes support for dealing with different screen sizes as well as saving and reusing layouts via the concept of breakpoint systems
and templates
.
Usage
The bread and butter of imola are the gridPanel()
and flexPanel()
functions.
They allow you to replace any HTML tag that serves as a container (div
, section
, main
, nav
, …) with a tag using one of the CSS layout systems (grid or flex).
While in depth knowledge of CSS Flexbox and CSS Grid is not required to get started, it is recommended to at least be somewhat familiar with them. I recommend this article to get you up to speed.
If you are looking for more information on a specific system in imola, make sure to check the following vignettes for an in depth view:
-
vignette("imola-flexbox")
for details onflexPanel()
andflexPage()
. -
vignette("imola-grid")
for details ongridPanel()
andgridPage()
. -
vignette("imola-templates")
for information on using imola’s templating engine. -
vignette("imola-breakpoints")
for information on using imola’s breakpoint systems.
Using grid vs flex
Picking between grid and flex might seem tricky. In general flex and Grid serve different purposes and are both incredibly useful. Picking between them typically depends on your use case:
Use Flex when:
- Content sets the size
- Need horizontal or vertical alignment
- Layout is one-dimensional
- Need better older browser support
Use Grid when:
- Things need a set width regardless of content
- Layout is two-dimensional
- Elements need to overlap
A common rule of thumb is to use Grid for full page layouts and Flex for everything else, or to consider whether the component you plan to build is one-dimensional (Flex) or two-dimensional (Grid).
This means if you are looking for fine control over columns and rows, you should aim at using grid, if you only care about one of the dimensions, flex will most likely work just fine.
Grid
The grid
function family focuses on providing support for the CSS Grid standard.
In imola you can find 2 functions that allow you to create a new grid component. gridPanel()
and gridPage()
. With gridPage()
being a full page version of gridPanel()
allowing you to create a full page UI to use with shiny.
If you’re interested in more information from the CSS side, I recommend this article to get you started.
gridPanel(
...,
template = NULL,
areas = NULL,
rows = NULL,
columns = NULL,
gap = NULL,
align_items = "stretch",
justify_items = "stretch",
auto_fill = TRUE,
breakpoint_system = getBreakpointSystem(),
id = generateID()
)
For more on grid with imola, check vignette("imola-grid")
.
Flex
The flex
function family focuses on providing support for the CSS flex standard.
In imola you can find 2 functions that allow you to create a new flex component. flexPanel()
and flexPage()
. With flexPage()
being a full page version of flexPanel()
allowing you to create a full page UI to use with shiny.
If you’re interested in more information from the CSS side, I recommend this article to get you started.
flexPanel(
...,
template = NULL,
direction = "row",
wrap = "nowrap",
justify_content = "flex-start",
align_items = "stretch",
align_content = "flex-start",
gap = 0,
flex = c(1),
grow = NULL,
shrink = NULL,
basis = NULL,
breakpoint_system = getBreakpointSystem(),
id = generateID()
)
For more on flex with imola, check vignette("imola-flex")
.
Breakpoint systems
CSS breakpoints are a way of assigning a website specific css style rules according to the device width, allowing you to show the best possible layout to the user no matter their screen size.
CSS breakpoints are also often called media query breakpoints, as they are used with the @media
css rule.
Different CSS frameworks usually have their own breakpoints baked in, these are usually hidden behind a css class or a name that identifies a specific screen size.
If you are familiar with base shiny or other css based frameworks, you might have even used these systems without realizing;
For example, using the fluidRow()
function will trigger layout changes to your columns()
at specific screen sizes, based on bootstrap 3 breakpoints (The base CSS framework in shiny).
While its great to have this done automatically, it also comes with many constrains and does not allow for fine control of these layout changes.
Very often for more complex layouts, you may often find yourself writing additional CSS to add new behavior for specific elements or screen sizes.
Imola takes a slightly different approach to breakpoints:
- Out of the box it uses the same breakpoint system as base shiny (bootstrap 3).
- You can change the default breakpoint system at the application level, but also at a component level.
- For each
grid
andflex
function named attribute you are able to pass either avalue
for that attribute or anamed list of different values
for different breakpoints.
Names that can be used in function attributes depend on what breakpoint names are available, we can use getBreakpointSystem()
to see the active breakpoint system:
Imola Breakpoint System: bootstrap3
Name: No description
description
Breakpoints (name) Minimum screen size (px) Maximum screen size (px)
Available ----------------------------- ------------------------- -------------------------
NULL 575
xs NULL 767
sm NULL 991
md NULL 1199
lg 1200 NULL
xl -----------------------------
Lets say we have the following grid areas in a gridPanel():
# as a gridPanel() argument
areas = c(
"area1 area1 area1",
"area2 area3 area3",
"area2 area3 area3"
)
In out case, we want to use the default breakpoint system and target small devices, so we target these via xs
, and build our areas
argument as a named list instead.
We can use default
as a name for our default value for the areas
argument. Think of default
as the value used for screen sizes where no other value can be applied.
default
is a reserved keyword in imola, so keep in mind not to use it when editing or creating a custom breakpoint system.
# as a gridPanel() argument
areas = list(
default = c(
"area1 area1 area1",
"area2 area3 area3",
"area2 area3 area3"
),
xs = c(
"area1",
"area2",
"area3"
)
)
For more about breakpoints systems, including changing the active system and creating your own, check vignette("imola-breakpoints")
.
Templates
Often during development it is common that multiple elements share the same layout. In order to easily reuse any layout you create, imola also includes a simple template engine.
Templates can be used via the template
argument on any of the panel or page functions by providing either the name of a registered template, or a template object created with gridTemplate()
.
Registered templates are templates that are either bundled with imola, or have been added to the global template list by using registerTemplate()
on a template object.
You can view all registered templates by using listTemplates()
.
Similar to grid
and flex
functions, templates
also support breakpoint systems.
Lets say we would like to save our previous areas as a template, and use it in different components. We could use gridTemplate()
to generate a template object:
#in global.R
# create a template object
mytemplate <- gridTemplate("myareas", "grid", areas = list(
default = c(
"area1 area1 area1",
"area2 area3 area3",
"area2 area3 area3"
),
xs = c(
"area1",
"area2",
"area3"
)
))
We can then use this template object as an argument in grid panels:
#in ui.R
gridPanel(
id = "somePanel"
template = mytemplate
area1 = div("area 1 content"),
area2 = div("area 2 content"),
area3 = div("area 3 content")
)
We can also register this template for global usage. In that case we need to register it after defining it:
#in global.R
# register it globally
registerTemplate(mytemplate)
In this case we can simply use the name of the registered template instead of the object:
#in ui.R
gridPanel(
id = "somePanel"
template = "myareas"
area1 = div("area 1 content"),
area2 = div("area 2 content"),
area3 = div("area 3 content")
)
You can view all registered templates with listTemplates()
. For a demo on all templates bundled with imola, you can view a demo here
You can register as many templates as you want, but keep in mind that each type + name combo must be unique. You can also remove templates using unregisterTemplate()
if needed.
For more on templates with imola, check vignette("imola-templates")
.