简体   繁体   中英

Footer Position in Shiny

I would like to adjust the footer position in a shiny app. When the page content is shorter than the viewport, the footer should be at the bottom of the viewport. When the page content is longer than the viewport, the footer should be below the content. This post suggests how to usually implement it in CSS. This and similar solutions are commonly straightforward to use when writing the page's HTML code by hand.

There are discussions on footer positions in shiny and some of them manage to move the footer to the bottom. However, they fail to keep the footer from overlapping with the bottom of the page's main content, which requires shortening the main content's container.

Consider the following minimal working example:

library(shiny)

ui <- navbarPage(title = "Some Example", id = "example",
    tabPanel(title = "Something", value = "something",
        textOutput("some_text")
    ),
    footer = "The footer."
)

server <- function(input, output, session) {
    output$some_text <- renderText(stringi::stri_rand_lipsum(5))
}

shinyApp(ui = ui, server = server)

It is possible to have a footer like you describe, but it is not straightforward to implement. There does not seem to be a built-in function to position the footer, let alone in the way you would like.

So, we need to write some custom CSS. To do so, we need to be able to target the footer. When we look at the HTML produced by the example, we can see that the content specified by the argument footer is simply wrapped in a <div> tag with class row .

      <div class="container-fluid">
        <div class="tab-content" data-tabsetid="6611">
          <div class="tab-pane active" data-value="something" id="tab-6611-1">
            <div id="some_text" class="shiny-text-output"></div>
          </div>
        </div>
        <div class="row">The footer.</div>
      </div>
    </body>
    </html>

In any reasonably sized shiny app, there will be multiple <div> s with this class, which makes it difficult to write CSS which reliably targets just the footer. A workaround is the following:

    ui <- tagList(navbarPage(
      title = "Some Example",
      id = "example",
      tabPanel(
        title = "Something",
        value = "something",
        textOutput("some_text")
      )),
      tags$footer("The footer.", class = "footer")
    )

Now all that is left to do is adding CSS that positions the footer. I use the example found on the Bootstrap website . A way to integrate this into shiny is like so:

    ui <- tagList(
      tags$head(
        tags$style(HTML(
          "html {
             position: relative;
             min-height: 100%;
           }
           body {
             margin-bottom: 60px; /* Margin bottom by footer height */
           }
           .footer {
             position: absolute;
             bottom: 0;
             width: 100%;
             height: 60px; /* Set the fixed height of the footer here */
             background-color: #f5f5f5;
           }"))),
      navbarPage(
      title = "Some Example",
      id = "example",
      tabPanel(
        title = "Something",
        value = "something",
        textOutput("some_text")
      )),
      tags$footer("The footer.", class = "footer")
    )

Replacing the UI in the example with the UI above will produce the desired footer that sticks to the bottom of the viewport when the content is short, but is below the content when the content is longer than the viewport.

I am not proficient in html, is this how the footer needs to look?

library(shiny)

ui <- navbarPage(title = "Some Example", id = "example",
                 tabPanel(title = "Something", value = "something",
                          textOutput("some_text"),
                          ##add a footer with 2 empty lines and the info to display
                          tags$footer(HTML('
                          <br>
                          <br>
                          <p>Author: Your Name<br>
                          <a href="mailto:your_name@example.com">your_name@example.com</a></p>'))
                 )
                 
)

server <- function(input, output, session) {
    output$some_text <- renderText(stringi::stri_rand_lipsum(15)) #change this number (15) to view how the footer reacts
}

shinyApp(ui = ui, server = server)

Or perhaps:

library(shiny)

ui <- navbarPage(title = "Some Example", id = "example",
                 tabPanel(title = "Something", value = "something",
                          textOutput("some_text"),
                          
                 
#add some empty lines to avoid overlap at the bottom    
tags$div(HTML('   <br>
                  <br>
                  <br>
                  <br>
                  <br>
                  <div class="footer">
                    <p>Author: Your Name<br>
                    <a href="mailto:your_name@example.com">your_name@example.com</a></p>
                  </div>')),
                  tags$style('
                  .footer {
                   position: fixed;
                   left: 0;
                   bottom: 0;
                   width: 100%;
                   background-color: lightgrey;
                   color: white;
                   text-align: right;}')),

tabPanel(title = "no_footer", value = "something",
         textOutput("some_text2")))

                 
                 


server <- function(input, output, session) {
    output$some_text <- renderText(stringi::stri_rand_lipsum(15)) #change this number (15) to view how the footer reacts
    output$some_text2 <- renderText(stringi::stri_rand_lipsum(5))
}

shinyApp(ui = ui, server = server)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM