【问题标题】:Shiny app using fluidrow and columns has overflow issues使用流体行和列的闪亮应用程序存在溢出问题
【发布时间】:2019-03-22 15:52:34
【问题描述】:

我在闪亮的应用程序中使用流畅的行和列布局。当我减小屏幕尺寸时,两列中的元素重叠。如果它们是两个不同的列并且使用流体行,则内容不应重叠。下面是代码。我有两列,宽度分别为 4 和 8。它们似乎在常规屏幕尺寸下工作正常,但一旦我最小化它们重叠的窗口。

library(shiny)
library(shinyjs)

ui <- navbarPage(
  "Bootstrap scrollspy on multiple tabs",
  id = "navbar",
  header = div(
    useShinyjs(),
    extendShinyjs("www/app-shinyjs.js", functions = c("updateScrollspy")),
    includeCSS("www/app.css"),
    includeScript("https://cdnjs.cloudflare.com/ajax/libs/jquery-scrollTo/1.4.3/jquery.scrollTo.min.js")
  ),

  # tab 1 contains 4 sections and a scrollspy on the left with text
  tabPanel(
    "tab1",
    div(id = "tab1-content",
        fluidRow(
          column(
            4,
            div(
              id = "tab1-scrollspy",
              class = "potential-scrollspy",
              tags$ul(
                class = "nav nav-pills nav-stacked",
                tags$li(tags$a(href = "#section1-1", "Section 1-1")),
                tags$li(tags$a(href = "#section1-2", "Section 1-2")),
                tags$li(tags$a(href = "#section1-3", "Section 1-3")),
                tags$li(tags$a(href = "#section1-4", "Section 1-4"))
              )
            )
          ),
          column(
            8,
            div(id = "section1-1",
                class = "scrollspy-section",
                p('Section 1-1')
            ),
            div(id = "section1-2",
                class = "scrollspy-section",
                p('Section 1-2')
            ),
            div(id = "section1-3",
                class = "scrollspy-section",
                p('Section 1-3')
            ),
            div(id = "section1-4",
                class = "scrollspy-section",
                p('Section 1-4')
            )              
          )
        )
    )
  ),

  # tab 2 contains 3 sections and a scrollspy on the right without text
  tabPanel(
    "tab2",
    div(id = "tab2-content",
        fluidRow(
          column(
            8,
            div(id = "section2-1",
                class = "scrollspy-section",
                p('Section 2-1')
            ),
            div(id = "section2-2",
                class = "scrollspy-section",
                p('Section 2-2')
            ),
            div(id = "section2-3",
                class = "scrollspy-section",
                p('Section 2-3')
            )
          ),
          column(
            4,
            div(
              id = "tab2-scrollspy",
              class = "potential-scrollspy",
              `data-offset` = 50,
              tags$ul(
                class = "nav nav-pills nav-stacked",
                tags$li(tags$a(href = "#section2-1")),
                tags$li(tags$a(href = "#section2-2")),
                tags$li(tags$a(href = "#section2-3"))
              )
            )
          )
        )
    )
  )
)

server <- function(input, output, session) {
  # when changing tabs, update the scrollspy control
  observeEvent(input$navbar, {
    js$updateScrollspy(input$navbar)
  })
}

shinyApp(ui = ui, server = server)

屏幕尺寸缩小:

// initialize common scrollspy control
shinyjs.init = function() {
  $('body').scrollspy({ target: '.active-scrollspy' });
}

// update the active scrollspy control and refresh so that it will function
shinyjs.updateScrollspy = function(tab) {
  // make all scrollspy controls inactive
  $('active-scrollspy').removeClass('active-scrollspy');
  // get the content in the current tab
  var $tabContent = $('#' + tab + '-content');
  if ($tabContent.length) {
    // find the scrollspy control in the current tab
    var $scrollspy = $tabContent.find('.potential-scrollspy');
    if ($scrollspy.length) {
      // mark the scrollspy in the current tab as active
      $scrollspy.addClass('active-scrollspy');
      // figure out the offset for this scrollspy
      var offset = 0;
      if ($scrollspy.data('offset')) {
        offset = $scrollspy.data('offset');
      }
      // update the scrollspy object
      $('body').data('bs.scrollspy').options.offset = offset;
      $('body').scrollspy('refresh');
      // unbind click events and re-bind clicks to animate scrolling
      $scrollspy.unbind('click.scrollto');
      $scrollspy.bind('click.scrollto', 'ul li a', function(event) {
        event.preventDefault();
        $.scrollTo(event.target.hash, 500, {
          offset: -offset
        });
      });
    }
  }
}
#tab1-content .scrollspy-section {
height: 500px;
border: 1px solid #DDD;
}
#tab1-scrollspy {
position: fixed;
}
#tab1-scrollspy li > a {
background-color: #FFF;
  }
#tab1-scrollspy li > a:hover {
background-color: #EEE;
  }
#tab1-scrollspy li.active > a {
background-color: #AAA;
  }
#tab2-content .scrollspy-section {
height: 900px;
border: 1px solid #DDD;
}
#tab2-scrollspy {
position: fixed;
top: 300px;
}
#tab2-scrollspy li > a {
padding: 0;
width: 15px;
height: 15px;
background-color: #DDD;
  margin-bottom: 5px;
}
#tab2-scrollspy li > a:hover {
background-color: #AAA;
  }
#tab2-scrollspy li.active > a {
background-color: #444;
  }

【问题讨论】:

  • 您应该发布 app-shinyjs.jsapp.css 文件以重现您的代码。
  • @alessio 我刚刚添加了支持文件。

标签: css r shiny


【解决方案1】:

这是有意的。

您在这里体验到的是 Bootstrap 的一个功能,responsive breakpoint。在其边缘情况下:所有容器将跨越整个页面的最小宽度。这样做主要是为了让网站变得对移动设备友好,因为跨越设备三分之一以上的列变得非常狭窄并且可能变得非常难以阅读。因此,“专栏”会在某个时间点解散。

如果你真的不希望这种情况发生,你有两个选择。

要么,知道这发生在引导程序中,你避免使用列并自己指定 div 宽度,这样无论如何它都是固定的。

或者你尝试通过包含另一个样式表来对抗引导 css。您可以通过 bootstrap.css 查看导致中断的媒体查询。然后复制样式并将它们应用于非常小的屏幕尺寸。我冒昧地创建了一个足以满足您的案例的 CSS,发布在下面:

bs-no-break.css

@media (max-width: 768px) {
  .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12 {
    float: left;
  }
  .col-sm-12 {
    width: 100%;
  }
  .col-sm-11 {
    width: 91.66666667%;
  }
  .col-sm-10 {
    width: 83.33333333%;
  }
  .col-sm-9 {
    width: 75%;
  }
  .col-sm-8 {
    width: 66.66666667%;
  }
  .col-sm-7 {
    width: 58.33333333%;
  }
  .col-sm-6 {
    width: 50%;
  }
  .col-sm-5 {
    width: 41.66666667%;
  }
  .col-sm-4 {
    width: 33.33333333%;
  }
  .col-sm-3 {
    width: 25%;
  }
  .col-sm-2 {
    width: 16.66666667%;
  }
  .col-sm-1 {
    width: 8.33333333%;
  }
  .col-sm-pull-12 {
    right: 100%;
  }
  .col-sm-pull-11 {
    right: 91.66666667%;
  }
  .col-sm-pull-10 {
    right: 83.33333333%;
  }
  .col-sm-pull-9 {
    right: 75%;
  }
  .col-sm-pull-8 {
    right: 66.66666667%;
  }
  .col-sm-pull-7 {
    right: 58.33333333%;
  }
  .col-sm-pull-6 {
    right: 50%;
  }
  .col-sm-pull-5 {
    right: 41.66666667%;
  }
  .col-sm-pull-4 {
    right: 33.33333333%;
  }
  .col-sm-pull-3 {
    right: 25%;
  }
  .col-sm-pull-2 {
    right: 16.66666667%;
  }
  .col-sm-pull-1 {
    right: 8.33333333%;
  }
  .col-sm-pull-0 {
    right: auto;
  }
  .col-sm-push-12 {
    left: 100%;
  }
  .col-sm-push-11 {
    left: 91.66666667%;
  }
  .col-sm-push-10 {
    left: 83.33333333%;
  }
  .col-sm-push-9 {
    left: 75%;
  }
  .col-sm-push-8 {
    left: 66.66666667%;
  }
  .col-sm-push-7 {
    left: 58.33333333%;
  }
  .col-sm-push-6 {
    left: 50%;
  }
  .col-sm-push-5 {
    left: 41.66666667%;
  }
  .col-sm-push-4 {
    left: 33.33333333%;
  }
  .col-sm-push-3 {
    left: 25%;
  }
  .col-sm-push-2 {
    left: 16.66666667%;
  }
  .col-sm-push-1 {
    left: 8.33333333%;
  }
  .col-sm-push-0 {
    left: auto;
  }
  .col-sm-offset-12 {
    margin-left: 100%;
  }
  .col-sm-offset-11 {
    margin-left: 91.66666667%;
  }
  .col-sm-offset-10 {
    margin-left: 83.33333333%;
  }
  .col-sm-offset-9 {
    margin-left: 75%;
  }
  .col-sm-offset-8 {
    margin-left: 66.66666667%;
  }
  .col-sm-offset-7 {
    margin-left: 58.33333333%;
  }
  .col-sm-offset-6 {
    margin-left: 50%;
  }
  .col-sm-offset-5 {
    margin-left: 41.66666667%;
  }
  .col-sm-offset-4 {
    margin-left: 33.33333333%;
  }
  .col-sm-offset-3 {
    margin-left: 25%;
  }
  .col-sm-offset-2 {
    margin-left: 16.66666667%;
  }
  .col-sm-offset-1 {
    margin-left: 8.33333333%;
  }
  .col-sm-offset-0 {
    margin-left: 0;
  }
  .navbar-right .dropdown-menu {
    right: 0;
    left: auto;
  }
  .navbar-right .dropdown-menu-left {
    right: auto;
    left: 0;
  }
  .navbar {
    border-radius: 4px;
  }
  .navbar-header {
    float: left;
  }
  .navbar-collapse {
    width: auto;
    border-top: 0;
    -webkit-box-shadow: none;
            box-shadow: none;
  }
  .navbar-collapse.collapse {
    display: block !important;
    height: auto !important;
    padding-bottom: 0;
    overflow: visible !important;
  }
  .navbar-collapse.in {
    overflow-y: visible;
  }
  .navbar-fixed-top .navbar-collapse,
  .navbar-static-top .navbar-collapse,
  .navbar-fixed-bottom .navbar-collapse {
    padding-right: 0;
    padding-left: 0;
  }
  .container > .navbar-header,
  .container-fluid > .navbar-header,
  .container > .navbar-collapse,
  .container-fluid > .navbar-collapse {
    margin-right: 0;
    margin-left: 0;
  }
  .navbar-static-top {
    border-radius: 0;
  }
  .navbar-fixed-top,
  .navbar-fixed-bottom {
    border-radius: 0;
  }
  .navbar > .container .navbar-brand,
  .navbar > .container-fluid .navbar-brand {
    margin-left: -15px;
  }
  .navbar-toggle {
    display: none;
  }
  .navbar-nav {
    float: left;
    margin: 0;
  }
  .navbar-nav > li {
    float: left;
  }
  .navbar-nav > li > a {
    padding-top: 15px;
    padding-bottom: 15px;
  }
  .navbar-left {
    float: left !important;
  }
  .navbar-right {
    float: right !important;
    margin-right: -15px;
  }
  .navbar-right ~ .navbar-right {
    margin-right: 0;
  }
}

【讨论】:

    猜你喜欢
    • 2021-09-30
    • 2013-07-08
    • 2021-07-20
    • 2020-03-15
    • 2016-02-09
    • 2017-02-15
    • 1970-01-01
    • 2016-05-23
    • 2016-11-01
    相关资源
    最近更新 更多