3MW (HTML & CSS with {htmltools})

Guten Tag!

Many greetings from Munich, Germany. This week, we are finally starting to build the user interface for our dashboard that looks like a weather app. In case you forgot about it (or you joined the newsletter this week), here’s the user interface we want to build:

But before we start talking about how to build this from within R, let me give you my usual announcements.

Watch all the steps on YouTube

This is the spot where I normally advertise my newest YouTube video. Most of the time, the YT video is not directly related to what we want to do in this week’s newsletter. Today is not one of those days.

If you want to get a step-by-step guide and can’t wait until we have finished building out the UI over the next couple of weeks, here’s my newest YT video. It gives you all of the details in a concise 20-minute video tutorial.

Like every week, the code that you see in the code chunks can be found on GitHub. (INSERT URL)

HTML & CSS Background

The best way to create something with HTML & CSS from within R is the {htmltools} package. This one makes it pretty easy to create HTML & CSS code without worrying about how to set up an HTML document. For now, all you have to know about these two languages is that

  • HTML gives you a bunch of containers that are nested into one another and

  • CSS makes the containers look nice.

In case you want to get a little bit more knowledge about these two languages before we get started, you can check out my Quarto themes video. It will give you a short overview of how HTML & CSS works.

And watch out for my upcoming “WebDev for R Users” video series. Right now the playlist only contains the weather app video but I will upload new videos starting next week. This video series will give you all the WebDev tools you need (including HTML & CSS).

The anatomy of our UI

Given our current standpoint of “HTML is a bunch of containers” let’s decompose our user interface into containers. That way, we know how to structure the resulting HTML code. Here’s how our user interface looks.

Now, let us decompose this into sub-parts. Let’s do that visually first:

This means that the structure of our UI is as follows:

  • A container that looks like a rounded-off rectangle (the phone)

    • A container for the top bar

      • Time on the left

      • Icons on the right

    • A container for the location

      • Name of the location

      • Location icon

    • A container for the temperatures and forecasts

      • Current temperature

      • Weather (Rain, sunny, etc.)

      • Min/max temperature

    • A container for the big icon in the middle

    • A container for the next three days forecast

      • Container for row 1: Icon, day label, min/max temp

      • Container for row 2: Icon, day label, min/max temp

      • Container for row 3: Icon, day label, min/max temp

Sketching out the structure with {htmltools}

While sketching out this structure in a list of bullet points sounds way too simple, it’s actually pretty much the same as in HTML. You see, HTML is a language for structuring different kinds of containers. And the most basic containers are so-called div-tags.

With {htmltools} you can create such a container using the div() function. Hence, creating the layout with divs is just a matter of nesting the function calls to mimic the structure of the list that we’ve just created.

And the output looks pretty much the same:

Rendering the HTML code

As you’ve just seen, the output of these nested div() function calls is HTML code. This should hardly be surprising. After all, we do want to create just that. But it becomes hard to judge the code if we cannot see the output.

That’s exactly where the browsable() function comes in. Passing the outermost div to this function renders the HTML code and displays it in the Viewer window of RStudio.

Children and attributes

Right now, the output isn’t particularly pretty. The thing is: HTML is only a way to structure elements in some hierarchy. The output will be plain black and white if you don’t add any style instructions. To do that, you will have to insert the style attribute into tags that you want to style.

So this begs the question: How do we put attributes into a tag? Well, if we look at the documentation of the div() function, we see that it’s documented on the same page as many other tags and they all use the dot-dot-dot operator as first argument.

In R, that’s a kind of catch-all argument. So we have to investigate a bit further in the docs to figure out what the tag functions expect to be passed into this catch-all thingy.

AHA! The docs say that all named things become attributes (using the name as attribute) and everything else becomes a child of the tag. In HTML-speak, children are the tags that are nested into other tags. So everything that isn’t named in these function calls will become the content of the tag.

Consequently, we can use this new-found knowledge to set the style of the outermost div to have a certain width, height and background color.

The output still isn’t particularly nice. But at least we know how to style things now. At least in principle. Next week, we can dive into better style instructions. In the meantime, if you want to reach out to me, just reply to this mail or find me on LinkedIn.

See you next week,
Albert 👋

Enjoyed this newsletter and found something helpful? Here are other ways I can help you:


or to participate.