fix(theme): 内容块宽度改为流式取值 + 1440px 封顶,消除档位跳变(#31)
现象:窗口从宽拖窄时,中间内容块宽度离散跳档(540/720/960/1280 四档),
档内两侧留白极宽 —— 1920 视口每边白 320px,占整个窗口约 1/3。
根因:bootstrap.min.css 的 .container 只有 4 个固定 max-width 档位,
档内宽度恒定不变,跨断点瞬间跳一格。不是"断点太少",而是宽度只有 4 个取值。
改法(assets/css/site.css +134 行):
1) .container 宽度改成连续函数
width: min(1440px, 100% - 2 * max(16px, 2.5vw))
min() 是连续取值,@media 是离散判断 —— 这是两者的本质区别。
上限 1440 由用户选定;边距 max(16px, 2.5vw) 做窄屏保底 + 宽屏按比例。
同时 max-width: none 显式压掉 Bootstrap 的 4 个档位(缺它宽屏仍被
1280 卡住,等于没改)。
2) padding 归零 + .row 负 margin 同步归零
Bootstrap 原本靠 container 的 15px padding 与 .row 的 -15px margin 相互
抵消。现在边距由 width 公式承担,padding 必须归零(否则双重扣减,
窄屏吃 30px);.row 的 -15px 也必须归零(否则内容外顶 15px、贴到容器边)。
列自身的 15px padding 保留,它是两列间隙的来源。
3) 导航容器单独对齐(三版才修对)
.k-nav 同时带 Bootstrap 的 .navbar,左右各有 16px padding,容器嵌在
已内缩的盒子里。直接用正文公式会得到正确宽度但差 16px 位置。
正确解是同公式 + margin:auto 在已内缩的盒子里居中。
两个失败版本记在注释里:① calc(100% + 32px) 因 100% 在绝对定位盒里
解析成视口宽 ⇒ 满宽 320@0;② 负 margin 把容器顶到父级 padding 之外
⇒ 左边缘变 0 而非 36。
验证(_tooling/yang_theme_test/,均为线上真实页面 + 拦截替换待发布 CSS):
- _diag_width3.js 改前定量:4 档平台 540×192 / 720×224 / 960×318 / 1280×609,
跳变 89.5/119.5/158.5px,1920 视口 521 个宽度留白 ≥60px
- _geom31.js 16/0:逐 1px 扫 320~1920 共 1601 档,W1 无固定档位(唯一平台
1440 封顶段)、W2 单步 ≤2px(实测 1px)、W3 单调、W4 封顶 1440 且对称、
W5 留白 ≤40px、W6 无横向溢出、W7 三容器一致、W8 正文占比 66.7%、
W9 正文缩进 15px;四条反证全部红在预期条目
- _shot31.js 33/0:7 档截图 + 表格/代码/图片不溢出、页脚同宽、目录块不越界、
暗色模式,另含 V4b 防空靶子守卫
- _align31.js 5/0:导航/正文/页脚容器左边缘逐像素一致,logo 与首段偏移
-31px 跨 7 档零漂移
- _mkzip364.py 43/0 + _mkzip364_falsify.py 11/0(10 条注入全部命中)
侧栏行为按用户要求保持现状(992px 以下隐藏、正文整行),该处宽度变化
是侧栏出现/消失导致,非台阶,不在本版范围。
Refs #31
This commit is contained in:
@@ -338,3 +338,137 @@ ol > li {
|
||||
ul > li {
|
||||
line-height: 1.8;
|
||||
}
|
||||
|
||||
/* ══════════════════════════════════════════════════════════════════
|
||||
* 容器宽度:改为流式(工单 #31)
|
||||
*
|
||||
* ── 改之前是什么样(线上实测,Playwright 逐 1px 扫 320~1920)──────
|
||||
* Bootstrap 的 `.container` 只有 **4 个固定 max-width 档位**:
|
||||
*
|
||||
* 视口 576~767 → 容器 540px 单边留白 18~113.5px
|
||||
* 视口 768~991 → 容器 720px 单边留白 24~135.5px
|
||||
* 视口 992~1309 → 容器 960px 单边留白 16~174.5px
|
||||
* 视口 1312~1920 → 容器 1280px 单边留白 16~320px
|
||||
*
|
||||
* 每个档位内宽度**完全不变**,于是窗口越宽、两侧空白越宽;跨过断点
|
||||
* 宽度瞬间跳一格,留白突变 89.5 / 119.5 / 158.5px —— 这就是用户说的
|
||||
* 「一蹦一蹦」「某些固定宽度下两边有两个非常宽的空白」。
|
||||
*
|
||||
* 根本问题不是"断点太少",而是**容器宽度本身只有 4 个取值**。
|
||||
* 加密断点只是让台阶小一点,仍然是台阶。
|
||||
*
|
||||
* ── 现在怎么算 ─────────────────────────────────────────────────
|
||||
* 用 **min()** 让宽度连续跟随视口、到上限后居中:
|
||||
*
|
||||
* width: min(1440px, 100% - 2×边距)
|
||||
*
|
||||
* · 视口窄时 → `100% - 边距` 生效,宽度随窗口连续变化,两侧永远只有
|
||||
* 固定边距(不留大空白);
|
||||
* · 视口宽到某个点 → `1440px` 生效,超出部分居中留白,正文不会无限拉长。
|
||||
*
|
||||
* 两个分支在交界处**数值相等**(1440 + 2×边距),所以过渡是**连续的**,
|
||||
* 没有台阶、没有突变。这是 min() 相比 media query 的本质优势:
|
||||
* media query 是**离散判断**,min() 是**连续取值**。
|
||||
*
|
||||
* ⚠️ 上限 1440px 是用户选定的(工单 #31)。原来 Bootstrap 最高到 1280,
|
||||
* 1920 屏上单边空 320px;改 1440 后 1920 屏单边空 240px,同时正文
|
||||
* 依然有足够的宽度可读性。
|
||||
*
|
||||
* ⚠️ 边距用 `max(16px, 2.5vw)` 而不是定值:窄屏保证 16px 不被吃掉
|
||||
* (手机上贴边很难看),宽屏略微增加,与视口更协调。2.5vw 在 1440
|
||||
* 视口时 = 36px,正好让上限分支的边距看起来不突兀。
|
||||
*
|
||||
* 🔴 三条规则都要,缺一条就前功尽弃:
|
||||
* ① `.container` 基础规则 —— 覆盖 Bootstrap 的 `width:100%` 与 4 个
|
||||
* `max-width` 档位(后者全在 `@media (min-width:…)` 里,优先级
|
||||
* (0,1,0) 与基础规则相同,靠**后加载**取胜,见下方说明);
|
||||
* ② 页面上有 **3 个** `.container`(导航 / 主内容 / 页脚),
|
||||
* 必须同一条规则覆盖,否则导航和页脚会跟正文错位;
|
||||
* ③ `max-width` 必须显式设成 `none`,否则 Bootstrap 的
|
||||
* `@media (min-width:576px){.container{max-width:540px}}` 依然生效
|
||||
* —— 它和我们的基础规则同优先级,而 media query 里那条**更晚**
|
||||
* 出现在 bootstrap.min.css 里;我们虽然在 site.css(更晚加载),
|
||||
* 但 `max-width` 那条属性必须被我们**显式声明**才能压住。
|
||||
*
|
||||
* 加载顺序(inc/theme-core.php):bootstrap → kratos.min → **site.css**,
|
||||
* 所以同优先级下 site.css 胜出。
|
||||
* ⚠️ 不要用 `!important`:Bootstrap 里 `@media print` 有一条
|
||||
* `.container{min-width:992px!important}` 是打印用的,我们改的是
|
||||
* `width`/`max-width`,不冲突;一旦上 `!important` 反而会与打印样式
|
||||
* 打架。 */
|
||||
.container {
|
||||
/* 宽度 = min(上限, 视口 - 两侧边距)。连续取值,无台阶。 */
|
||||
width: min(1440px, 100% - 2 * max(16px, 2.5vw));
|
||||
/* 🔴 必须显式覆盖 Bootstrap 的 4 个 max-width 档位(540/720/960/1280) */
|
||||
max-width: none;
|
||||
/* 左右 auto 居中:窄屏时 width 已经等于可用宽度,auto 不产生额外偏移;
|
||||
宽屏时 width 封顶 1440,auto 把剩余空间均分到两侧。 */
|
||||
margin-right: auto;
|
||||
margin-left: auto;
|
||||
/* Bootstrap 原来是 15px;这里改由 width 的边距项承担,
|
||||
否则会**双重扣减**(padding 15 + width 里再扣一次边距),
|
||||
窄屏上内容被吃掉 30px。 */
|
||||
padding-right: 0;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
/* 栅格行原本用 margin:-15px 抵消 container 的 15px padding。
|
||||
现在 container 的 padding 已经是 0,这 -15px 会把内容**往外顶** 15px、
|
||||
直接溢出容器右侧。所以同步归零。
|
||||
(`.row` 只出现在 .k-main 里,导航/页脚没有 .row,不必担心误伤。) */
|
||||
.k-main .row {
|
||||
margin-right: 0;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
/* 列自身的 15px padding 保留:它是"两列之间的间隙"来源,
|
||||
归零会让正文和侧栏贴在一起。这里显式声明是为了说明意图 ——
|
||||
不管 Bootstrap 以后怎么改,这一条的语义是明确的。 */
|
||||
.k-main .row > [class*="col-"] {
|
||||
padding-right: 15px;
|
||||
padding-left: 15px;
|
||||
}
|
||||
|
||||
/* 🔴 导航里的 container 要单独补偿(实测才发现)
|
||||
*
|
||||
* `.k-nav` 同时带着 Bootstrap 的 `.navbar` 类,而 `.navbar` 有
|
||||
* `padding-right/left: 16px`。所以导航里的 container 是嵌在**已经内缩
|
||||
* 16px** 的盒子里的:
|
||||
*
|
||||
* 视口 1440:正文 container 宽 1368 左 36
|
||||
* 导航 container 宽 1336 左 52 ← 比正文窄 32、右移 16
|
||||
*
|
||||
* 改之前两者都是 Bootstrap 的 1280px 固定档位、都被居中,宽度一致,
|
||||
* 这个 16px 内缩只表现为"导航比正文稍微靠里一点",不明显。
|
||||
* 改成流式后上限提高、位置随视口走,16px 的相对偏差就突出了,
|
||||
* 导航栏的 logo/菜单会与正文左边缘对不齐。
|
||||
*
|
||||
* 解法见下方规则体内注释(用同一套 width 公式 + **margin:auto 居中**;
|
||||
* 我最初的两版负 margin 方案都是错的,原因记在下面)。
|
||||
* ⚠️ 不能给 `.k-nav` 直接 `padding:0` —— 那是 Bootstrap 给所有 navbar 的
|
||||
* 统一内边距,小屏折叠态下菜单面板依赖它,去掉会贴边。 */
|
||||
.k-nav > .container,
|
||||
.k-nav .navbar > .container {
|
||||
/* 导航里的 container 要和正文**逐像素对齐**。
|
||||
*
|
||||
* 难点:`.k-nav` 同时带 Bootstrap 的 `.navbar`,而它左右各有 16px padding。
|
||||
* 直接用 `width: min(1440px, 100vw - 边距)` 会得到正确**宽度**,但
|
||||
* 位置差 16px(父级内缩没被算进去)。
|
||||
*
|
||||
* 正确做法:用**与正文完全相同**的公式算宽度,然后**不要**加负 margin,
|
||||
* 让 `margin: auto` 在这 16px 内缩的盒子里居中。数学上刚好抵消:
|
||||
*
|
||||
* 视口 1440:navbar 内容框 1408,容器 1368,auto ⇒ 左 = 16+(1408-1368)/2 = 36 ✅
|
||||
* 视口 1920:navbar 内容框 1888,容器 1440,auto ⇒ 左 = 16+(1888-1440)/2 = 240 ✅
|
||||
*
|
||||
* 🔴 前两版都错在这里,值得记下:
|
||||
* ① 用 `100%` + `calc(… + 32px)` + 负 margin ⇒ `100%` 在绝对定位的
|
||||
* `.k-nav` 里解析成**视口宽**,结果满宽 320@0;
|
||||
* ② 用 `100vw` 公式 + `margin-left/right: -16px` ⇒ 宽度对了,但负 margin
|
||||
* 把容器顶到父级 padding **之外**,左 = 0 而不是 36。
|
||||
* 负 margin 是"抵消父级内缩"的思路,但抵消之后就不再居中;
|
||||
* 真正要的是"在已内缩的盒子里按比例居中"。 */
|
||||
width: min(1440px, 100vw - 2 * max(16px, 2.5vw));
|
||||
margin-right: auto;
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user