library(htmltools)
div(
style = css(
display = 'flex',
flex_wrap = 'wrap',
justify_content = 'space-around',
width = '300px',
height = '300px',
background = 'lightgrey'
),div(
style = css(
width = '100px',
height = '100px',
border = '1px solid #333333',
background = 'red'
)
),div(
style = css(
width = '100px',
height = '100px',
border = '1px solid #333333',
background = 'red'
)
),div(
style = css(
width = '100px',
height = '100px',
border = '1px solid #333333',
background = 'red'
)
),div(
style = css(
width = '100px',
height = '100px',
border = '1px solid #333333',
background = 'red'
)
)|>
) div(style = 'all: initial', br()) |>
browsable()
WebDev4R: CSS Grid
flexbox
and grid
. Both of them are really useful to know. In this blog post, I’ll show you how grid
works.
There are two major systems to align things in CSS. These are flexbox
and grid
layout. Both of them are really useful to know to have any chance to make nice websites or app. And today we’re going to focus on flexbox
. And as always, if you want to see the video version of this blog post, you can find it on my YouTube channel:
What is grid
?
As the name suggests, grid
is a system to align things in a grid-like manner. This means that it’s a two-dimensional system, meaning that you can align things both horizontally and vertically. As we have seen in the previous blog post, flexbox
is a one-dimensional system, meaning that you can only align things in one direction but with flex-wrap
you can get similar results as with grid
. Here’s how that looked last week:
But with grid
these kinds of use cases are much easier to handle. All you have to do is to replace the flexbox
display with the grid
display.
div(
style = css(
display = 'grid', ## Change here
width = '300px',
height = '300px',
background = 'lightgrey'
),div(
style = css(
width = '100px',
height = '100px',
border = '1px solid #333333',
background = 'red'
)
),div(
style = css(
width = '100px',
height = '100px',
border = '1px solid #333333',
background = 'red'
)
),div(
style = css(
width = '100px',
height = '100px',
border = '1px solid #333333',
background = 'red'
)
),div(
style = css(
width = '100px',
height = '100px',
border = '1px solid #333333',
background = 'red',
flex_shrink = 0
)
)|>
) div(style = 'all: initial', br()) |>
browsable()
Well, that was a bust. There’s one more thing that you have to specify and that is the grid-template-columns
and grid-template-rows
. First, let’s have a look at the grid-template-columns
.
div(
style = css(
display = 'grid',
grid_template_columns = '100px 100px', ## Change here
grid_template_rows = '100px 100px', ## Change here
width = '300px',
height = '300px',
background = 'lightgrey'
),div(
style = css(
border = '1px solid #333333',
background = 'red'
)
),div(
style = css(
border = '1px solid #333333',
background = 'red'
)
),div(
style = css(
border = '1px solid #333333',
background = 'red'
)
),div(
style = css(
border = '1px solid #333333',
background = 'red'
)
)|>
) div(style = 'all: initial', br()) |>
browsable()
Notice how I have removed the individual width
and height
properties from the squares. That’s because the grid-template-columns
and grid-template-rows
properties specify the width and height of the columns and rows. All the containers that are inside the grid are automatically adjusted to these dimensions.
So here we have specified that we want to have two columns with a width of 100px each. We could also use a relative unit that is based on the size of the parent container. For example, we could use fr
which stands for “fraction of the available space”.
div(
style = css(
display = 'grid',
grid_template_columns = '1fr 2fr', ## Change here
grid_template_rows = '1fr 1fr', ## Change here
width = '300px',
height = '300px',
background = 'lightgrey'
),div(
style = css(
border = '1px solid #333333',
background = 'red'
)
),div(
style = css(
border = '1px solid #333333',
background = 'red'
)
),div(
style = css(
border = '1px solid #333333',
background = 'red'
)
),div(
style = css(
border = '1px solid #333333',
background = 'red'
)
)|>
) div(style = 'all: initial', br()) |>
browsable()
Well look at that our grey square is completely filled out now. And the second column in our grid is twice as large as the first one. That’s because inside grid-template-columns
we have used 1fr 2fr
. This means that the first column gets one fraction of the available space and the second column gets two fractions of the available space. Similarly, the rows are equally sized because we have used 1fr 1fr
inside grid-template-rows
.
Gap
Usually grids look nicer if there is a bit of space between the content in rows and columns. So let’s specify the column-gap
and row-gap
as well.
div(
style = css(
display = 'grid',
grid_template_columns = '1fr 2fr',
grid_template_rows = '1fr 1fr',
column_gap = '10px', ## Change here
row_gap = '10px', ## Change here
width = '300px',
height = '300px',
background = 'lightgrey'
),div(
style = css(
border = '1px solid #333333',
background = 'red'
)
),div(
style = css(
border = '1px solid #333333',
background = 'red'
)
),div(
style = css(
border = '1px solid #333333',
background = 'red'
)
),div(
style = css(
border = '1px solid #333333',
background = 'red'
)
)|>
) div(style = 'all: initial', br()) |>
browsable()
We could also add a padding between the outer borders of the grid and the parent container.
div(
style = css(
display = 'grid',
grid_template_columns = '1fr 2fr',
grid_template_rows = '1fr 1fr',
padding = '10px', ## Change here
row_gap = '10px',
column_gap = '10px',
width = '300px',
height = '300px',
background = 'lightgrey'
),div(
style = css(
border = '1px solid #333333',
background = 'red'
)
),div(
style = css(
border = '1px solid #333333',
background = 'red'
)
),div(
style = css(
border = '1px solid #333333',
background = 'red'
)
),div(
style = css(
border = '1px solid #333333',
background = 'red'
)
)|>
) div(style = 'all: initial', br()) |>
browsable()
And for more complicated layouts you can also use the grid-template-areas
property. But don’t forget to set the grid-area
property for each container inside the grid.
div(
style = css(
display = 'grid',
width = '300px',
height = '300px',
padding = '10px', ## Change here
row_gap = '10px',
column_gap = '10px',
background = 'lightgrey',
grid_template_areas = '
"a a ."
"b c ."
". d d"' ## Change here
),div(
style = css(
grid_area = 'a',
border = '1px solid #333333',
background = 'red'
)
),div(
style = css(
grid_area = 'b',
border = '1px solid #333333',
background = 'red'
)
),div(
style = css(
grid_area = 'c',
border = '1px solid #333333',
background = 'red'
)
),div(
style = css(
grid_area = 'd',
border = '1px solid #333333',
background = 'red'
)
)|>
) div(style = 'all: initial', br()) |>
browsable()
Use grid with {bslib}
The bslib
makes it pretty easy to create cards (nothing but containers) and align them in a grid-like manner. Currently, you can only make all cards use the same width.
library(bslib)
layout_column_wrap(
card('Card 1'),
card('Card 2'),
card('Card 3'),
card('Card 4')
)
But by injecting a bit of custom CSS, you can make the cards use different widths. All of that is based on the grid layout.
layout_column_wrap(
card('Card 1'),
card('Card 2'),
card('Card 3'),
card('Card 4'),
style = 'grid-template-columns: 1fr 2fr;'
)
Conclusion
There’s a whole lot more you can learn about grid
but for now this should give you a good start. Have a great day and see you next time. And if you found this helpful, here are some other ways I can help you:
- 3 Minute Wednesdays: A weekly newsletter with bite-sized tips and tricks for R users
- Insightful Data Visualizations for “Uncreative” R Users: A course that teaches you how to leverage
{ggplot2}
to make charts that communicate effectively without being a design expert.