Shiny+bslib布局问题:让navset_hidden/layout_sidebar填充页面高度
问题根源
navset_hidden 默认是自适应内容高度,而直接放在 nav_panel 里的 layout_sidebar 会自动继承 page_navbar 主体区域的100%高度。要让Nav1里的布局和Nav2表现一致,需要给嵌套的容器逐层设置高度继承规则。
修改后的代码
library(shiny) library(bslib) nav1UI <- function(id) { ns <- NS(id) layout_sidebar( # 让layout_sidebar占满父容器高度 height = "100%", sidebar = sidebar( open = "always", paste0("sidebar of ", id) ), # 主内容区超出高度时自动滚动,避免页面整体滚动 div( style = "height: 100%; overflow-y: auto;", paste0("main of ", id), lapply(1:20, function(i) h1(i)) ) ) } ui <- page_navbar( title = "MyApp", nav_panel( "Nav1", # 让Nav1的面板内容占满page_navbar主体高度 style = "position: relative; height: 100%;", actionButton("nav1_select", "select", style = "position: absolute; top: 0; left: 0; z-index: 1000;"), # 让navset_hidden占满父容器高度 navset_hidden( id = "nav1_navset", style = "height: 100%;", nav_panel_hidden("A", nav1UI("A")), nav_panel_hidden("B", nav1UI("B")), nav_panel_hidden("C", nav1UI("C")), nav_panel_hidden("D", nav1UI("D")) ) ), nav_panel( "Nav2", layout_sidebar( sidebar = sidebar("sidebar of Nav2"), "main of Nav2" ) ), nav_panel("Nav3", "content of Nav3") ) server <- function(input, output, session) { observeEvent(input$nav1_select, { showModal(modalDialog( title = "Select one", selectInput("nav_panel_to_go", NULL, choices = c("A", "B", "C", "D")), easyClose = TRUE, footer = tagList( modalButton("Close"), actionButton("go", "Go", class = "btn-success") ) )) }) observeEvent(input$go, { nav_select("nav1_navset", input$nav_panel_to_go) removeModal() }) } shinyApp(ui, server)
关键修改点
- 给Nav1的
nav_panel添加height: 100%,确保面板内容区继承page_navbar主体的高度。 - 给
navset_hidden添加height: 100%,让它占满父容器空间。 - 给
layout_sidebar设置height = "100%",使其填充navset_hidden的高度。 - 给主内容区包裹一层
div并设置height: 100%; overflow-y: auto;,这样内容超出时在主区域内滚动,保持整体布局高度不变。
关于抽屉式导航的后续方向
如果要实现GitHub风格的抽屉式搜索导航,可以基于bslib的sidebar组件扩展:
- 将导航选项放在一个可折叠的左侧sidebar中,默认收起。
- 在sidebar内添加搜索输入框,通过
observeEvent过滤导航选项。 - 用
nav_select实现点击选项切换navset_hidden的面板。
内容的提问来源于stack exchange,提问作者toxin
相关产品推荐
相关产品推荐

