Files
HomeDash/web/navi.css
JianFeeeee 9eb8214fab fix(web): 搜索栏改为底部悬浮,补极简视图页脚与整体动效
- 搜索栏 position:fixed 悬浮在视口下侧,任何视图/滚动位置都可见;
  原先是流式跟在页脚之后,手机上要滚到底才看得到
- 极简视图(/minimal)与工作空间不渲染 Dashy 页脚,备案号整段消失;
  navi.js 从只读 pageinfo 取回页脚补一份(DOMParser,不用 innerHTML)
- 空分组不再渲染成空玻璃条(:not(:has(a.item))),修掉 mini 页底部一排空框
- 图标统一 56/48px 容器 + object-fit:contain,修 24px 与 56px 混排
- 备案号页脚改为胶囊样式
- 新增动效层:视图/卡片淡入、搜索栏滑入、悬停位移,全部只动
  transform/opacity 并遵循 prefers-reduced-motion
2026-09-11 16:25:26 +08:00

580 lines
17 KiB
CSS
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* HomeDash responsive presentation layer.
Loaded after Dashy's bundled styles; persistent wallpaper rules stay in conf.yml. */
html {
-webkit-text-size-adjust: 100%;
text-size-adjust: 100%;
}
html[data-theme] body {
min-width: 0;
overflow-x: hidden;
/* 悬浮搜索栏固定在底部,给内容留出空间,避免遮挡页脚备案号。 */
padding-bottom: 104px !important;
}
/* Dashy's native filter/settings strip duplicates the portal search and breaks on phones. */
html[data-theme] .home > .settings-outer,
html[data-theme] .minimal-home .title-and-search > form {
display: none !important;
}
html[data-theme] body:has(.modal-overlay) > .navi-search-bar {
visibility: hidden !important;
pointer-events: none !important;
}
/* Keep configuration dialogs above section tabs and cards without changing dialog layout. */
html[data-theme] .modal-overlay {
z-index: 10000 !important;
}
html[data-theme] dialog.dashy-modal {
z-index: 10001 !important;
}
/* Stable icon geometry: raster/SVG and font icons occupy the same visual box. */
html[data-theme] a.item .item-icon {
flex: 0 0 56px !important;
width: 56px !important;
min-width: 56px !important;
height: 56px !important;
min-height: 56px !important;
display: inline-flex !important;
align-items: center !important;
justify-content: center !important;
overflow: hidden !important;
transform: none !important;
}
html[data-theme] a.item .item-icon .tile-icon,
html[data-theme] a.item .item-icon img,
html[data-theme] a.item .item-icon object {
box-sizing: border-box !important;
width: 48px !important;
min-width: 48px !important;
max-width: 48px !important;
height: 48px !important;
min-height: 48px !important;
max-height: 48px !important;
padding: 2px !important;
object-fit: contain !important;
object-position: center !important;
transform: none !important;
}
html[data-theme] a.item .item-icon i,
html[data-theme] a.item .item-icon svg:not(.tile-icon) {
width: 32px !important;
height: 32px !important;
font-size: 30px !important;
line-height: 32px !important;
}
html[data-theme] a.item .tile-title {
min-width: 0 !important;
overflow: hidden;
}
html[data-theme] a.item .tile-title .text,
html[data-theme] a.item .description,
html[data-theme] a.item .item-url {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
/* 底部搜索:悬浮固定在视口下侧,任何页面/任何滚动位置都可见。 */
html[data-theme] .navi-search-bar {
box-sizing: border-box !important;
position: fixed !important;
left: 50% !important;
bottom: calc(16px + env(safe-area-inset-bottom, 0px)) !important;
transform: translateX(-50%) !important;
width: min(760px, calc(100% - 28px)) !important;
min-height: 58px !important;
margin: 0 !important;
padding: 7px 8px 7px 18px !important;
display: flex !important;
align-items: center !important;
gap: 12px !important;
z-index: 900 !important;
color: #475569 !important;
background: rgba(255, 255, 255, .68) !important;
border: 1px solid rgba(255, 255, 255, .88) !important;
border-radius: 20px !important;
box-shadow: 0 14px 38px rgba(15, 23, 42, .14), inset 0 1px 0 rgba(255, 255, 255, .95) !important;
backdrop-filter: blur(22px) saturate(180%) !important;
-webkit-backdrop-filter: blur(22px) saturate(180%) !important;
}
html[data-theme] .navi-search-bar > span {
flex: 0 0 20px;
height: 20px;
display: grid;
place-items: center;
}
html[data-theme] .navi-search-bar input {
min-width: 0 !important;
height: 42px !important;
flex: 1 1 auto !important;
padding: 0 4px !important;
color: #0f172a !important;
background: transparent !important;
border: 0 !important;
outline: 0 !important;
box-shadow: none !important;
font: inherit !important;
font-size: 16px !important;
}
html[data-theme] .navi-search-bar input::placeholder {
color: #64748b !important;
opacity: 1;
}
html[data-theme] .navi-search-bar button {
flex: 0 0 44px !important;
width: 44px !important;
height: 44px !important;
display: grid !important;
place-items: center !important;
padding: 0 !important;
color: #fff !important;
background: linear-gradient(135deg, #0ea5e9, #2563eb) !important;
border: 0 !important;
border-radius: 14px !important;
box-shadow: 0 8px 20px rgba(37, 99, 235, .28) !important;
cursor: pointer;
}
html[data-theme] .navi-search-bar button svg {
width: 20px;
height: 20px;
}
/* Minimal view is the phone/tablet layout used by Dashy. */
html[data-theme] .minimal-home {
box-sizing: border-box !important;
width: min(100% - 24px, 920px) !important;
max-width: 920px !important;
min-height: auto !important;
margin: 0 auto !important;
padding: 28px 0 16px !important;
background: transparent !important;
}
html[data-theme] .minimal-home .title-and-search {
padding: 0 8px !important;
}
html[data-theme] .minimal-home .title-and-search h1 {
max-width: 100%;
margin: 0 !important;
color: #0f172a !important;
font-size: clamp(2rem, 8vw, 3rem) !important;
line-height: 1.08 !important;
letter-spacing: -.04em !important;
overflow-wrap: anywhere;
}
html[data-theme] .minimal-home > .item-group-container {
box-sizing: border-box !important;
width: 100% !important;
margin: 32px auto 0 !important;
padding: 0 6px !important;
}
html[data-theme] .minimal-headings-wrap {
position: relative;
z-index: 2;
gap: 6px !important;
margin-bottom: 8px !important;
}
html[data-theme] .minimal-headings-row {
gap: 6px !important;
scroll-snap-type: x proximity;
}
html[data-theme] .minimal-headings-row .headings {
flex-basis: 132px !important;
min-height: 44px !important;
padding: 8px 12px !important;
border-radius: 14px !important;
scroll-snap-align: start;
}
html[data-theme] .minimal-headings-row .headings .section-title {
font-size: 15px !important;
line-height: 1.2 !important;
}
html[data-theme] .minimal-headings-wrap .tab-scroll-btn {
min-width: 34px !important;
padding: 0 8px !important;
border-radius: 12px !important;
}
html[data-theme] .minimal-section-inner {
padding: 8px !important;
background: rgba(255, 255, 255, .34) !important;
border: 1px solid rgba(255, 255, 255, .72) !important;
border-radius: 20px !important;
box-shadow: 0 16px 38px rgba(15, 23, 42, .10), inset 0 1px 0 rgba(255, 255, 255, .88) !important;
backdrop-filter: blur(20px) saturate(170%) !important;
-webkit-backdrop-filter: blur(20px) saturate(170%) !important;
}
/* 空分组(非选中分组 / 无条目)不能被渲染成空玻璃条。
Dashy 会把其余分组渲染成 16px 的空 .minimal-section-inner,
一旦给它加了边框和底色就会变成一排“莫名其妙的框”。 */
html[data-theme] .minimal-section-inner:not(:has(a.item)),
html[data-theme] .minimal-section-inner:empty {
display: none !important;
}
html[data-theme] .minimal-widget-wrap:empty {
display: none !important;
}
html[data-theme] .minimal-section-inner .section-items {
gap: 10px !important;
}
html[data-theme] .minimal-section-inner a.item {
box-sizing: border-box !important;
min-height: 82px !important;
margin: 0 !important;
padding: 12px 16px !important;
}
@media (max-width: 599px) {
html[data-theme] .minimal-home {
width: min(100% - 16px, 430px) !important;
padding-top: 22px !important;
}
html[data-theme] .minimal-home .title-and-search h1 {
font-size: clamp(1.9rem, 9.4vw, 2.55rem) !important;
}
html[data-theme] .minimal-home > .item-group-container {
margin-top: 26px !important;
padding: 0 !important;
}
html[data-theme] .minimal-headings-row .headings {
flex-basis: 116px !important;
padding: 8px 10px !important;
}
html[data-theme] .minimal-section-inner {
padding: 7px !important;
}
html[data-theme] .minimal-section-inner a.item {
min-height: 78px !important;
padding: 10px 12px !important;
border-radius: 16px !important;
}
html[data-theme] a.item .item-icon {
flex-basis: 52px !important;
width: 52px !important;
min-width: 52px !important;
height: 52px !important;
min-height: 52px !important;
}
html[data-theme] a.item .item-icon .tile-icon,
html[data-theme] a.item .item-icon img,
html[data-theme] a.item .item-icon object {
width: 44px !important;
min-width: 44px !important;
max-width: 44px !important;
height: 44px !important;
min-height: 44px !important;
max-height: 44px !important;
}
/* Keep the screen-level warning inside the phone viewport. */
html[data-theme] .modal-overlay .modal-body {
min-width: 0 !important;
max-width: 100vw !important;
overflow-x: hidden !important;
}
html[data-theme] .modal-overlay .config-tabs {
overflow-x: auto !important;
overscroll-behavior-x: contain;
scrollbar-width: none;
}
html[data-theme] .modal-overlay .config-tabs::-webkit-scrollbar {
display: none;
}
html[data-theme] .modal-overlay .config-tabs > * {
flex: 0 0 auto !important;
}
html[data-theme] .modal-overlay .config-buttons,
html[data-theme] .modal-overlay .config-buttons > * {
min-width: 0 !important;
max-width: 100% !important;
}
html[data-theme] .modal-overlay .config-buttons > p,
html[data-theme] .modal-overlay .config-buttons .warning,
html[data-theme] .modal-overlay .config-buttons .info {
white-space: normal !important;
overflow-wrap: anywhere !important;
}
html[data-theme] .navi-search-bar {
width: calc(100% - 20px) !important;
min-height: 56px !important;
bottom: calc(12px + env(safe-area-inset-bottom, 0px)) !important;
padding-left: 15px !important;
border-radius: 18px !important;
}
}
/* ── 页脚:备案号胶囊 ──
备案号在 /admin/ 里编辑,这里只负责呈现;同时清掉历史上塞在
内联样式里的 margin-bottom:80px(那是给旧的流式搜索栏让位的)。 */
html[data-theme] footer {
margin: 0 !important;
padding: 0 0 4px !important;
background: transparent !important;
}
html[data-theme] footer > div {
margin-bottom: 0 !important;
padding: 0 !important;
}
html[data-theme] .navi-footer-host {
display: flex !important;
justify-content: center !important;
padding: 0 8px 6px !important;
}
html[data-theme] .navi-footer {
display: flex !important;
flex-wrap: wrap !important;
align-items: center !important;
justify-content: center !important;
gap: 9px !important;
width: fit-content !important;
max-width: min(680px, calc(100% - 24px)) !important;
margin: 14px auto 0 !important;
padding: 9px 18px !important;
color: #64748b !important;
font-size: 12.5px !important;
line-height: 1.4 !important;
background: rgba(255, 255, 255, .55) !important;
border: 1px solid rgba(255, 255, 255, .78) !important;
border-radius: 999px !important;
box-shadow: 0 6px 18px rgba(15, 23, 42, .06), inset 0 1px 0 rgba(255, 255, 255, .92) !important;
backdrop-filter: blur(14px) saturate(170%) !important;
-webkit-backdrop-filter: blur(14px) saturate(170%) !important;
}
html[data-theme] .navi-footer a {
color: #64748b !important;
text-decoration: none !important;
border-bottom: 1px dashed rgba(100, 116, 139, .45) !important;
transition: color .2s ease, border-color .2s ease !important;
}
html[data-theme] .navi-footer a:hover {
color: #0284c7 !important;
border-bottom-color: rgba(2, 132, 199, .6) !important;
}
html[data-theme] .navi-footer-sep {
color: rgba(100, 116, 139, .45) !important;
}
/* ── 工作空间:侧栏与内容区同样走玻璃圆角 ── */
html[data-theme] .work-space,
html[data-theme] .web-content {
padding-bottom: 104px !important;
}
html[data-theme] nav.side-bar {
background: rgba(255, 255, 255, .62) !important;
border-right: 1px solid rgba(255, 255, 255, .6) !important;
backdrop-filter: blur(18px) saturate(180%) !important;
-webkit-backdrop-filter: blur(18px) saturate(180%) !important;
}
html[data-theme] nav.side-bar .side-bar-section {
padding: 2px !important;
}
html[data-theme] nav.side-bar .side-bar-item {
border-radius: 12px !important;
transition: background .2s ease !important;
}
html[data-theme] nav.side-bar .side-bar-item:hover {
background: rgba(255, 255, 255, .92) !important;
}
/* ── 动效 ──
只动 transform / opacity,不触发布局;时长 180–380ms,
缓动统一 cubic-bezier(.22,1,.36,1)(快速起步、平稳收尾)。 */
@keyframes navi-fade-in {
from { opacity: 0; }
to { opacity: 1; }
}
@keyframes navi-fade-up {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}
@keyframes navi-bar-in {
from { opacity: 0; transform: translate(-50%, 16px); }
to { opacity: 1; transform: translate(-50%, 0); }
}
html[data-theme] html,
html[data-theme] body {
scroll-behavior: smooth;
}
/* 视图切换:主内容与选中分组淡入 */
html[data-theme] #dashy > *,
html[data-theme] .minimal-section-inner.selected,
html[data-theme] .work-space {
animation: navi-fade-in .3s cubic-bezier(.22, 1, .36, 1) both;
}
/* 悬浮搜索栏:从下侧滑入 */
html[data-theme] .navi-search-bar {
animation: navi-bar-in .36s cubic-bezier(.22, 1, .36, 1) both;
transition: box-shadow .24s ease, border-color .24s ease, background .24s ease !important;
}
html[data-theme] .navi-search-bar button {
transition: transform .2s cubic-bezier(.22, 1, .36, 1), box-shadow .2s ease, filter .2s ease !important;
}
html[data-theme] .navi-search-bar button:hover {
filter: brightness(1.06);
transform: translateY(-1px) scale(1.04);
box-shadow: 0 12px 26px rgba(37, 99, 235, .34) !important;
}
html[data-theme] .navi-search-bar button:active {
transform: translateY(0) scale(.96);
}
html[data-theme] .navi-footer-host {
animation: navi-fade-in .42s ease both;
}
/* 卡片逐个淡入:只作用在内容层,避免和 masonry 布局的位移冲突 */
html[data-theme] div.collapsible-content .item-wrapper,
html[data-theme] .minimal-section-inner .item-wrapper {
animation: navi-fade-up .34s cubic-bezier(.22, 1, .36, 1) both;
}
html[data-theme] .item-wrapper:nth-child(1) { animation-delay: 0ms; }
html[data-theme] .item-wrapper:nth-child(2) { animation-delay: 30ms; }
html[data-theme] .item-wrapper:nth-child(3) { animation-delay: 60ms; }
html[data-theme] .item-wrapper:nth-child(4) { animation-delay: 90ms; }
html[data-theme] .item-wrapper:nth-child(5) { animation-delay: 120ms; }
html[data-theme] .item-wrapper:nth-child(6) { animation-delay: 150ms; }
html[data-theme] .item-wrapper:nth-child(n+7) { animation-delay: 180ms; }
/* 分组容器:悬停轻微上浮 */
html[data-theme] div.collapsable {
transition: box-shadow .26s ease, border-color .26s ease, transform .26s cubic-bezier(.22, 1, .36, 1) !important;
}
html[data-theme] div.collapsable:hover {
transform: translateY(-2px);
border-color: rgba(147, 197, 253, .6) !important;
box-shadow: 0 18px 40px rgba(15, 23, 42, .12), inset 0 1px 0 rgba(255, 255, 255, .9) !important;
}
html[data-theme] div.collapsable h2,
html[data-theme] .minimal-headings-row .headings {
transition: background .22s ease, color .22s ease, transform .22s cubic-bezier(.22, 1, .36, 1), border-color .22s ease !important;
}
html[data-theme] .minimal-headings-row .headings:hover {
transform: translateY(-1px);
border-color: rgba(147, 197, 253, .75) !important;
}
html[data-theme] .minimal-headings-row .headings:active {
transform: scale(.975);
}
html[data-theme] .minimal-headings-wrap .tab-scroll-btn {
transition: background .2s ease, color .2s ease, transform .2s cubic-bezier(.22, 1, .36, 1) !important;
}
html[data-theme] .minimal-headings-wrap .tab-scroll-btn:hover:not([disabled]) {
transform: scale(1.06);
}
html[data-theme] a.item:active {
transform: translateY(-1px) scale(.99) !important;
}
html[data-theme] a.item .item-icon img,
html[data-theme] a.item .item-icon svg {
transition: transform .26s cubic-bezier(.22, 1, .36, 1) !important;
}
html[data-theme] nav.side-bar .side-bar-item {
transition: background .2s ease, transform .2s cubic-bezier(.22, 1, .36, 1) !important;
}
html[data-theme] nav.side-bar .side-bar-item:hover {
transform: scale(1.06);
}
html[data-theme] .navi-footer a {
transition: color .2s ease, border-color .2s ease !important;
}
@media (prefers-reduced-motion: reduce) {
html[data-theme] html,
html[data-theme] body {
scroll-behavior: auto !important;
}
html[data-theme] #dashy > *,
html[data-theme] .minimal-section-inner.selected,
html[data-theme] .work-space,
html[data-theme] .navi-search-bar,
html[data-theme] .navi-footer-host,
html[data-theme] div.collapsible-content .item-wrapper,
html[data-theme] .minimal-section-inner .item-wrapper {
animation: none !important;
opacity: 1 !important;
transform: none !important;
}
html[data-theme] a.item,
html[data-theme] a.item .tile-icon {
transition: none !important;
}
html[data-theme] a.item:hover,
html[data-theme] div.collapsable:hover,
html[data-theme] nav.side-bar .side-bar-item:hover,
html[data-theme] .minimal-headings-row .headings:hover {
transform: none !important;
}
}