How to add color to cell borders in an HTML Rmarkdown document using R

I have a dataframe named df and I am utilizing html format within Rmarkdown to generate a table. However, due to varying cell sizes, the background color does not accurately fill each cell, leaving white spaces in between.

Here is the code I am using:


df = structure(list(projects = c("Restaurant, Pizzeria and Pasta House Works for  New York",
                                "London Project - New Restaurant  Project", 
                                "Athens - Beautiful Lands for Aigaleo City Project",
                                "Berlin City - Exhibition  near the airport with restaurants",
                                "Pizzeria Buenos Aires New italian restaurant - pasta, tartufo and vino",
                                "area mean value", "total mean value"), 
                    happiness.and.joyfullness = c(3.5,4, 3, 3.2, 4, 5, 3), 
                    joy.for.children = c(3, 5, 3, 4, 5,4, 4), 
                    area = c(3, 5, 3, 3, 3, 4, 4), 
                    damages.from.environment = c(2,4, 2, 3, 3, 5, 5), 
                    approach  = c(3, 1, 5,3, 5, 5, 4), 
                    expensive = c(3, 5, 3, 4, 5, 5, 5), 
                    safety.comes.first = c(5,5, 5, 5, 5, 5, 4),
                    hungry = c(3, 5, 2, 4, 5,5, 5)), 
               row.names = c(NA, -7L), 
               class = c("tbl_df", "tbl","data.frame"))






set_background_color  = function(x, color = "white") {
  kableExtra::cell_spec(x,
                        bold = TRUE,
                        align = "center",
                        color = "black", 
                        background = color,
                        extra_css ="align-items: center;
      justify-content: center;margin: -5px; padding: 15px; display: flex;",
                       background_as_tile = FALSE
      )}

set_custom_background  = function(x, color = "black") {
  kableExtra::cell_spec(x,
                        bold = TRUE,
                        color="black", 
                        background = color,
                        extra_css ="align-items: center;
      justify-content: center;margin: -5px; padding: 10px; display: flex;",
                        background_as_tile = FALSE)
}



df %>%

  dplyr::mutate( across(projects, \(x) case_when(projects == "area mean value" ~set_custom_background(x, "yellow") ,
                                              projects == "total mean value" ~set_custom_background(x, "yellow"),
                                              TRUE ~ projects)))%>%
  dplyr::mutate( 
    across(happiness.and.joyfullness:hungry, \(x)
           case_when(
             x <= 3.5  ~ set_background_color(x, "lightblue"),
             x > 3.5  & x <= 4.5  ~ set_background_color(x, "pink"),
             x > 4.5  & x <= 5    ~ set_background_color(x, "purple"),
             TRUE ~ set_background_color(x))))%>%
  kableExtra::kbl(align = "c",position = "center",caption = "Project Scoring Table", escape=FALSE)%>%
  kableExtra::kable_paper()%>%
  kableExtra::row_spec(0,color = "white", background = "grey")%>%
  kableExtra::column_spec(1:9, 
                          bold = TRUE,
                          border_left  = TRUE,
                          border_right = TRUE)%>%
  kableExtra::row_spec(0:7, align = "center",extra_css = "vertical-align:middle;")

This resulted in: https://i.sstatic.net/YpXCI.png

How can I resolve this issue in R for my html Rmarkdown document? I have been experimenting with padding and margin but the problem persists when rendered to html via rmarkdown.

Answer №1

Reasons for the Issue

An examination of the HTML output created by kableExtra reveals that the cell contents are enclosed within span tags.

<td style="text-align:center;font-weight: bold;border-left:1px solid;border-right:1px solid;text-align: center;vertical-align:middle;">
    <span style="font-weight: bold; color: black !important;padding-right: 4px; padding-left: 4px; background-color: pink !important; align-items: center; justify-content: center; margin: -5px; padding: 15px; display: flex; text-align: center;">
        4
    </span>
</td>

The issue arises from how HTML tables treat rows and cells, where the span struggles to determine its parent cell's height. Setting the height to 100% does not solve this problem. Alternatively, fixing the height at a specific value like 150px may cause overflowing content in cells with lengthy text.

Solution Approach

Aligning an inner span to fill its table cell proves to be challenging, as acknowledged in previous inquiries on similar topics. A straightforward approach could involve applying position: relative to each td element and position: absolute to every span. By setting the top, right, bottom, and left attributes of the spans to 0, they overlay the entire cell.

Based on the provided HTML code, the styles specified in extra_css in kableExtra::cell_spec (within the set_background function) apply to the span. The styles defined in kableExtra::row_spec impact all td elements. Thus, adjusting the positioning for both tds and spans is achievable using row_spec and cell_spec correspondingly.

Implementation Steps

To grant relative positioning to each td element, modify the extra_css parameter in the row_spec function call at the end.

kableExtra::row_spec(
    0:7,
    align = "center",
    extra_css = "
        vertical-align: middle;
        position: relative;
    "
)

For absolute positioning of the spans, update the extra_css section in the cell_spec call within your set_background function. Also, eliminate the negative margin.

set_background  = function(x, color = "white") {
    kableExtra::cell_spec(
        x,
        bold = TRUE,
        align = "center",
        color = "black", 
        background = color,
        extra_css = "
            align-items: center;
            justify-content: center;
            padding: 15px;
            display: flex;
            position: absolute;
            left: 0;
            right: 0;
            top: 0;
            bottom: 0;
        ",
        background_as_tile = FALSE
    )
}

These adjustments yield the presented outcome:

https://i.sstatic.net/IxiZH9lW.png

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The arrows on the Slick Slider appear cropped on ios devices like the iphone 8, however, they display perfectly when tested on Chrome and Firefox

I am currently facing an issue with my slick slider setup at https://www.labtag.com/shop/product/clear-cryogenic-labels-for-frozen-vials-1-75-x-1-aha-224/. It is configured for 4 slides on desktop and 2 slides on mobile devices (768px breakpoint). The pr ...

Enhancing an image with a hover-activated overlay

I'm trying to enhance the setup of my page with three images in columns by adding an extra overlay on top of the main image but beneath the hover effects. However, I seem to be encountering some difficulties while working on it. Take a look at my cod ...

Adjusting the size of content with CSS

I've been attempting to get an image to cover the entire screen on a device using CSS, but so far I haven't had any success. The image is within an :after pseudo element and content tag. Since it needs to be laid over the HTML, I can't use t ...

Tips on ensuring CSS is properly loaded on a Django HTML page

Despite numerous attempts, I cannot get my CSS to render properly on any of the HTML pages within a Django project. I've tried various solutions from Stack Overflow, such as adding the following code snippet: <link rel="stylesheet" href=& ...

A paragraph styled with line numbers using CSS

I struggle with writing long, never-ending paragraphs and need a way to visually break them up by adding line numbers next to each paragraph. While I'd prefer a solution using only CSS for simplicity's sake, JavaScript works too since this is jus ...

Is there a substitute for image cropping aside from the CSS clip property?

Looking to create an image gallery where thumbnails are cropped to 150px x 150px, but struggling with non-square rectangular images of various sizes. Adjusting width and height distorts the images. Are there alternative CSS or jQuery options for cropping ...

Too much gap between the span and the border's bottom

Occasionally, there seems to be an odd gap between the span and the bottom border. This issue is particularly noticeable on mobile devices. You can view a screenshot of the problem here: Code .heading { text-align: center; border-bottom: 2px solid ...

Can javascript be used to swap out the folder in my URL?

I have been searching for solutions on how to change the language of my website using jQuery, but so far I have not found anything that works for me. Let's take my website as an example: www.domain.com I have separate folders for different languages. ...

Utilize a specific component to enclose particular words within a contenteditable div in an Angular project

I have a task at hand where I need to manipulate text input from a contenteditable division, use regex to identify specific words, and then wrap those words within an angular component. Although I have managed to successfully replace the text with the com ...

I can't seem to get the Font Awesome icons to display properly. What could be the issue?

How can I get Fontawesome icons to display properly in the footer? Despite having my CSS and HTML files in the same directory, the icons remain invisible. Additionally, the page seems to be loading slower than usual. I have provided all necessary informati ...

Develop a custom extension for Videojs 4.0

I have developed a custom plugin for version 4.0 and above. function myCustomPlugin(options) { this.on('play', function(e) { console.log('Playback has started!'); }); vjs.NewPlayButton = vjs.Component.extend({ ...

Modify SQL table to alter the timestamp value

I am currently utilizing PHP to showcase an SQL table. Once a user selects a row on the table and clicks a button, I aim for it to update the timestamp to the present time and reflect on the displayed table within the webpage. The SQL query that I have wor ...

Ways to transform a poster into a clickable link in an HTML video

I am currently working on embedding an mp3 audio file in a browser, along with an accompanying image and a URL for redirection upon clicking. To achieve this, I have placed the mp3 file within a video tag and designated the image as a poster using the foll ...

Validation of forms in JavaScript, submission only occurs if the data is deemed to be

I am currently working on a JavaScript validation for a Perl form. The validation script is working correctly to display errors when data is missing. However, I am facing an issue where the form still submits after displaying the error messages. I believe ...

Is there a way to incorporate a circular list style into a bulleted list within RichTextBox?

Encountering a problem when trying to use a "circle" bullet style in my list. I have attempted coding it into a WebBrowser object and then passing it into the RTB, as well as using richtextbox.rtf with no success. In the HTML section, I tried: WebBrowser ...

Is there a way to decrease the size of the content within this iFrame?

Is there a way to display 6 cameras on a single webpage without them taking up the entire screen within iframe windows? Can the content be shrunken to fit the iframe window? <!doctype html> <html> <head> <meta charset="utf-8"> &l ...

Is the JavaScript click event ineffective for <select> <option>s?

It seems like there's a problem with the code below that is causing it to not work as expected. I'm trying to figure out why the onclick events on the <option>s are not triggering, but everything else seems fine. function displayInput() ...

CSS - using !important alongside a variable

Is there a way to dynamically add an important tag to the CSS height property of #content located on line 7 in the code snippet below? I need to use the variable $newHeight to ensure flexibility. Can anyone provide guidance on how to append an !important ...

Is there a way for me to duplicate a complex element multiple times within the same page?

As an illustration, let's say I have a social tab located in my header that I would like to duplicate in the footer. This tab is comprised of various buttons with SVG images on top, event listeners linked to button IDs, and CSS styling. One option is ...

The form submission is not affected by the jQuery dialog buttons and will proceed to submit as

I'm struggling with a form and JavaScript code interaction. In my code, when the validateDialogForm() function is called, a jQuery dialog appears under certain conditions. The issue is that the dialog only shows for a few seconds before the form conti ...