Bootstrap Dashboard组件:视口尺寸适配下拉菜单样式问题
问题背景
当前使用Dash Bootstrap构建的Navbar布局如下:
dbc.Navbar( dbc.Col(# logo 容器 align="center", style={"display": "grid", "justify-content": "left"}, ), dbc.Col(# 应用标题容器 align="center", style={"display": "grid", "justify-content": "center"}, ), dbc.NavbarToggler(id="navbar-toggler", n_clicks=0), dbc.Collapse( children=[right_elems], id="navbar-collapse", is_open=False, navbar=True ), )
right_elems初始样式设置为style={"display": "grid", "justify-content": "right"},在大屏(不显示NavbarToggler)下显示正常。通过客户端回调实现点击Toggler时,把right_elems的justify-content改为center:
app.clientside_callback( ''' function toggle_navbar(n, is_open){ let items = document.getElementByClassName("menu-item"); if (n){ for (var i=0, i < items.length; i++){ items[i].style.justifyContent = "center"; } return !is_open; } for (var i=0, i < items.length; i++){ items[i].style.justifyContent = "right"; } return is_open; } ''', Output("navbar-collapse", "is_open"), [Input("navbar-toggler", "n_clicks")], [State("navbar-collapse", "is_open")], )
核心问题:当视口从移动端(显示Toggler)切回大屏(隐藏Toggler)时,right_elems还保持着justify-content: center的内联样式,没法自动恢复成right。
解决方案
方法1:用CSS媒体查询替代JS操作样式(推荐)
直接靠CSS类和媒体查询控制样式,避开内联样式的优先级问题,代码更简洁:
- 给
right_elems加一个自定义类,比如right-aligned-menu,去掉内联的justify-content设置:
right_elems = dbc.Nav( # 你的菜单元素内容 className="right-aligned-menu menu-item" )
- 在应用里添加自定义CSS:
/* 大屏下默认右对齐 */ .right-aligned-menu { display: grid; justify-content: right; } /* 小屏且折叠菜单展开时,设置居中对齐 */ /* 注意:991px是Bootstrap默认的NavbarToggler显示断点,根据你的实际配置调整 */ @media (max-width: 991px) { #navbar-collapse.show .right-aligned-menu { justify-content: center; } }
这样完全不用JS操作样式:大屏下默认右对齐;小屏时只有折叠菜单展开(Bootstrap会自动给展开的折叠容器加.show类),才会触发居中样式。
方法2:监听窗口resize事件动态调整样式
如果一定要用JS回调,可以加个窗口尺寸监听,在视口切回大屏时强制恢复样式:
- 先引入
dash_extensions的WindowSize组件(用来获取窗口宽度):
from dash_extensions import WindowSize
- 修改客户端回调,加入窗口尺寸输入:
app.clientside_callback( ''' function toggle_navbar(n, width, is_open){ let items = document.getElementsByClassName("menu-item"); // 大屏下直接恢复右对齐,同时关闭折叠菜单 if (width >= 992) { for (let i = 0; i < items.length; i++) { items[i].style.justifyContent = "right"; } return false; } // 小屏下根据点击事件切换样式和菜单状态 if (n){ is_open = !is_open; for (let i = 0; i < items.length; i++){ items[i].style.justifyContent = is_open ? "center" : "right"; } } return is_open; } ''', Output("navbar-collapse", "is_open"), [Input("navbar-toggler", "n_clicks"), Input("window-size", "width")], [State("navbar-collapse", "is_open")], )
- 在布局里添加
WindowSize组件:
app.layout = html.Div([ WindowSize(id="window-size"), # 你的Navbar和其他页面内容 ])
内容的提问来源于stack exchange,提问作者Lebcode
相关产品推荐
相关产品推荐

