现象:窗口从宽拖窄时,中间内容块宽度离散跳档(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
475 lines
24 KiB
CSS
475 lines
24 KiB
CSS
@charset "UTF-8";
|
||
/**
|
||
* 站点级公共样式(3.2.29 起)
|
||
*
|
||
* 这些规则原来是站长手填在「主题设置 → 自定义代码 → 自定义 CSS」里的,
|
||
* 3.2.29 把它们并入主题公共样式,配置项因此留空。
|
||
*
|
||
* ⚠️ 选择器与声明**必须与原来的自定义 CSS 逐字一致**:
|
||
* 自定义 CSS 是以 `<style>` 形式紧跟在 kratos.min.css 之后输出的,
|
||
* 所以「排在最后 + 同选择器」才等价于原来的层叠结果。
|
||
* 本文件的加载顺序同样是 kratos.min.css 之后(enqueue 依赖 'kratos'),
|
||
* 改选择器范围(例如把 ul 收窄到 .article .content ul)会改变实际渲染。
|
||
*
|
||
* @author Yongquan Yang <yangyq.net>
|
||
* @license MIT License
|
||
*/
|
||
|
||
/* 正文段落首行缩进两字 */
|
||
.article .content p {
|
||
text-indent: 2em;
|
||
}
|
||
|
||
/* ── 正文插图:不吃段落的首行缩进,自成一行、左右都不缩进(3.2.60 / 工单 #28)
|
||
*
|
||
* 🔴 为什么必须有这一段:`text-indent` 是**可继承属性**。
|
||
*
|
||
* WP 把图片插进段落时,DOM 是 `<p><img></p>` 或 `<p><a><img></a></p>`。
|
||
* 图片(或包着它的 <a>)作为**行内级盒子**落在段落首行
|
||
* ⇒ 继承 32px 缩进,整体右移。
|
||
* 而 `max-width: 100%` 里的 100% 是**包含块(p)的内容宽度**,
|
||
* 不是"缩进之后剩下的宽度" ⇒ 图片仍按全宽铺开。
|
||
*
|
||
* 结果:左边缩进多少,右边就溢出多少,**二者永远相等**。
|
||
* 线上实测(2022/05/set-font-in-latex):左缩进 32px、右溢出 32px,
|
||
* 正文可绘制区 111~902.33,图片却是 143~934.33。
|
||
*
|
||
* ── ⚠️ 只给 img 清零 text-indent 是**不够**的(第一版就这么错)────────
|
||
*
|
||
* 实测:`.article .content img{ text-indent:0; display:block }` 之后,
|
||
* 图片自己的 computed text-indent 确实是 0px、display 也是 block,
|
||
* 但几何仍停在 143(照样偏 32px)。
|
||
*
|
||
* CDP `CSS.getMatchedStylesForNode` 抓到的真相:
|
||
* WP 会把图片包进 `<a class="yang-lb-item">`(灯箱),
|
||
* 而 lightbox.css 给它设了 `display: inline-block`。
|
||
* **inline-block 盒子的起点同样受父级 text-indent 影响** ——
|
||
* 它继承了 p 的 32px,于是整个「链接 + 图片」盒子被推进去 32px。
|
||
* 图片在盒子内部再怎么清零,也改不了盒子自己的起点。
|
||
*
|
||
* ⇒ 缩进必须清在**真正参与父级行内排版的那个盒子**上,
|
||
* 也就是 a.yang-lb-item / 裸 img 两者都要清。
|
||
*
|
||
* 修法:
|
||
* ① `text-indent: 0` 切断继承(不改 p 上的规则本身 ——
|
||
* 段落首行缩进是站长期望的效果,去掉会改变全站观感);
|
||
* ② `display: block` 自成一行,不参与首行的行内排版;
|
||
* ③ 图片用 `margin: … auto` 居中。
|
||
*
|
||
* ⚠️ 只看 `.content img`(后代)而不是 `> img`:图片外面常套一层
|
||
* `<a class="yang-lb-item">`(灯箱),直接子元素选择器量不到。
|
||
*
|
||
* ⚠️ 对齐类图片用 `:where()` 把特异性降到 0,让 kratos 的
|
||
* `.alignright{float:right}` / `.aligncenter` 等**照常生效**:
|
||
* 浮动的图本来就不该吃缩进,也不该被强制成块级居中。
|
||
* `:where()` 是 CSS4,Chrome 88+ / Safari 14+ / Firefox 78+ 支持;
|
||
* 更老的浏览器会整条规则失效 —— 退化成"维持现状",不会更坏。 */
|
||
.article .content img {
|
||
text-indent: 0;
|
||
display: block;
|
||
margin-left: auto;
|
||
margin-right: auto;
|
||
}
|
||
|
||
/* 🔴 灯箱链接:必须一起清零。它是 inline-block,本身就是参与父级
|
||
* 行内排版的盒子 —— 只清 img 无论用,位置由它决定。
|
||
* 见上面实测说明。 */
|
||
.article .content a.yang-lb-item {
|
||
text-indent: 0;
|
||
display: block;
|
||
line-height: 0;
|
||
margin-left: auto;
|
||
margin-right: auto;
|
||
}
|
||
|
||
/* 表情图必须保持行内:正文里它是夹在文字中的小图,
|
||
* 变 block 会换行、把句子拆断。特异性 (0,2,1) 压过上面那条。 */
|
||
.article .content img.wp-smiley,
|
||
.article .content img.emoji {
|
||
display: inline;
|
||
margin: 0;
|
||
vertical-align: middle;
|
||
text-indent: 0;
|
||
}
|
||
|
||
/* 对齐类图片交还给 kratos 的浮动/居中语义(特异性 0,不参与竞争)。
|
||
* 连包裹它的灯箱链接一起处理 —— 否则链接是 block、图片却 float,
|
||
* 会空出一整行。 */
|
||
:where(.article .content) img.alignright {
|
||
display: inline;
|
||
float: right;
|
||
margin: 0 0 8px 16px;
|
||
}
|
||
|
||
:where(.article .content) img.alignleft {
|
||
display: inline;
|
||
float: left;
|
||
margin: 0 16px 8px 0;
|
||
}
|
||
|
||
:where(.article .content) img.aligncenter {
|
||
display: block;
|
||
margin-left: auto;
|
||
margin-right: auto;
|
||
}
|
||
|
||
:where(.article .content) a.yang-lb-item:has(img.alignright) {
|
||
display: inline;
|
||
float: right;
|
||
margin: 0;
|
||
}
|
||
|
||
:where(.article .content) a.yang-lb-item:has(img.alignleft) {
|
||
display: inline;
|
||
float: left;
|
||
margin: 0;
|
||
}
|
||
|
||
/* 正文二级标题:左侧蓝条 + 浅灰底,横向铺满(负 margin 吃掉正文的 16px 内距)
|
||
*
|
||
* 3.2.61(工单 #29 追加):字号 20→24、字重 500→700。
|
||
* 🔴 这是 3.2.60 留下的层级倒挂的修复:3.2.60 把 h3 提到 20px/600,
|
||
* 而 h2 一直是 20px/500 —— 结果 h2 和 h3 同字号、h3 还更粗 100,
|
||
* 三级标题比二级标题更抢眼。用户一眼就看出"h3 比 h2 还大"。
|
||
* 根因是当时只动了 h3,没把 h2 一起拉起来,而且判据里
|
||
* **没有任何一条断言 h2 > h3**,所以 52 条全绿也照样漏了。
|
||
* ⇒ 往后调任一标题级别,必须同时断言相邻两级的**字号 + 字重**
|
||
* 都单调递减(见 _geom361_route.js 的 G 组)。
|
||
*
|
||
* 行高 41→46:24px 字配 41px 行高,上下各只剩 8.5px,灰底看着发扁;
|
||
* 46px 让上下各留 11px。这个 11px 是**算出来的**:
|
||
* 24px 字的实际墨迹高约 24×0.88 ≈ 21px(中文黑体 ascent+descent 之内),
|
||
* 行框 46px 减 21px 再除以 2 ≈ 12.5px,与 3.2.60 的 20px/41px
|
||
* (20×0.88=17.6,41-17.6=23.4,/2≈11.7px)基本持平。 */
|
||
.k-main .details .article .content h2 {
|
||
margin: 16px -16px;
|
||
padding: 0 10px;
|
||
border-left: 5px solid #00a2ff;
|
||
background-color: rgba(243, 243, 243, 0.7);
|
||
font-size: 24px;
|
||
font-weight: 700;
|
||
line-height: 46px;
|
||
}
|
||
|
||
/* ── 正文三级标题:左侧细竖线 + 底部细线(3.2.60 / 工单 #29)
|
||
*
|
||
* 3.2.60 之前 h3 只有 `font-size:18px; font-weight:500`,没有任何装饰,
|
||
* 而正文是 16px/350 —— **只差 2px 字号、150 字重**,放在长文里根本分不出来。
|
||
*
|
||
* 层级梯度(3.2.61 定稿,三级 + 四级同步调整):
|
||
* h2 24px / 700 / 左 5px 蓝条 + 浅灰底 ← 最重,分节
|
||
* h3 20px / 600 / 左 3px 蓝条 + 底 1px 细线,无底色
|
||
* h4 17px / 500 / 纯文字,无装饰
|
||
* p 16px / 350
|
||
*
|
||
* 🔴 两条铁律(3.2.60 违反第 1 条,导致 h3 比 h2 还抢眼):
|
||
* ① 字号与字重**同时**严格递减:24>20>17>16、700>600>500>350;
|
||
* ② 装饰强度也递减:蓝条+灰底 > 蓝条+细线 > 无 > 无。
|
||
* 任一级调了,必须回头核对相邻两级的下行关系,别只盯自己那一级。
|
||
*
|
||
* 为什么 h3 竖线用 3px 而不是 h2 的 5px:同族但更轻,一眼能看出次一级。
|
||
* 为什么 h3 不加底色:h2 已经有灰底,h3 再铺一层整篇会碎成一块块。
|
||
* 为什么 h4 用 500 而不是 600:600 与 h3 同字重,就只剩字号 3px 的差别,
|
||
* 视觉上"像同一个级别被缩了一点"。降到 500 后,字重也参与分层。
|
||
* 500 仍然明显重于正文的 350(差 150),不会糊回正文里去。
|
||
*
|
||
* ⚠️ 特异性必须是 (0,4,1) 起步、并把字号/字重一起写死:
|
||
* kratos 的 `.k-main .details .article .content h3` 是 (0,4,1),
|
||
* 只写 `.article .content h3`(0,2,1)会被它压掉 —— 这在本项目
|
||
* 踩过一次(archives.css 里 22px/700 写了两版都没生效,实际一直是 18px/500)。
|
||
* 所以这里与 h2 用同一套前缀,并且 font-size / font-weight 都显式声明。 */
|
||
.k-main .details .article .content h3 {
|
||
margin: 24px 0 16px;
|
||
padding: 2px 0 2px 10px;
|
||
border-left: 3px solid #00a2ff;
|
||
border-bottom: 1px solid #eaedf2;
|
||
font-size: 20px;
|
||
font-weight: 600;
|
||
line-height: 32px;
|
||
}
|
||
|
||
/* ── 正文四级标题:17px / 500(3.2.61 定稿)
|
||
*
|
||
* 字号 17px 保持不动(h3 20px 之下、正文 16px 之上的唯一合理档位,
|
||
* 再往下压到 16px 就与正文同大、层级直接断层)。
|
||
* 字重 600 → 500:600 与 h3 完全同重,等于只有 3px 字号差,
|
||
* 看着像"同一级被缩小",不像下一级。降到 500 让字重也参与分层。
|
||
*
|
||
* 不加任何装饰 —— 到第四级再加线就满屏都是线了。 */
|
||
.k-main .details .article .content h4 {
|
||
margin: 20px 0 12px;
|
||
font-size: 17px;
|
||
font-weight: 500;
|
||
line-height: 30px;
|
||
}
|
||
|
||
/* 🔴 归档页的年份标题也是 `<h3 class="ar-year">`,而且它就在
|
||
* `.article .content` 里面([Archives] 是正文短代码)。
|
||
* 上面那条 h3 会命中它 —— 于是年份会多出一条左竖线和一条底细线,
|
||
* 而 archives.css 里 `.ar-head` 已经有自己的底边线,会变成**两条线**。
|
||
*
|
||
* 这不是"顺手加个补丁",是必须的:archives.css 的 `.ar-year`
|
||
* 靠 (0,5,0) 才压过 kratos,本文件若也用 (0,5,0) 且排在它后面,
|
||
* 谁赢就变成"看入队顺序",非常脆。
|
||
*
|
||
* 这里主动让路:把 ar-year 的装饰清零,尺寸仍交给 archives.css 管
|
||
* (它写 26px/700,本规则不碰字号,避免两边抢)。 */
|
||
.k-main .details .article .content h3.ar-year {
|
||
padding: 0;
|
||
border-left: 0;
|
||
border-bottom: 0;
|
||
margin: 0;
|
||
}
|
||
|
||
/* ── 正文标题的自动编号(3.2.62 / 工单 #30)
|
||
*
|
||
* 结构由 PHP 插入:<h2 id="x"><span class="yang-h-num">1.1</span>标题</h2>
|
||
* 编号是**独立 span**,不是改标题文本 —— 所以不进编辑器、不进 RSS、
|
||
* 不进搜索结果、不进摘要。作者手写编号时压根不插这个 span。
|
||
*
|
||
* ── 为什么用灰色(用户选定的方案)──────────────────────────────
|
||
* 标题的核心是**文字本身**,编号只是索引辅助。若与标题同色同粗,
|
||
* 视觉上"1.1"会和标题正文抢注意力,长文章里满屏都是数字。
|
||
* 灰色 + 字重 400 让编号退到背景,眼睛扫标题时能忽略它、需要定位时
|
||
* 又能看见 —— 这也与目录里 `.yang-toc-num` 的处理一致,
|
||
* 正文和目录的编号看起来是同一套东西。
|
||
*
|
||
* ── 字号是 1em(与标题完全同大,3.2.63 起)────────────────────
|
||
* 🔴 0.62em 那一版**用户否掉了**:「字体不能太小,要不然很不协调,看着难受」。
|
||
* 实测 0.62em 在 h2 上是 14.88px、而标题 24px —— 差 9px,比例失衡,
|
||
* 编号像"贴在标题边上的小注脚",不像标题的一部分。
|
||
* 改成 1em 之后:h2 编号 24px、h3 20px、h4 17px,与标题逐级同大。
|
||
* 弱化只靠**颜色 + 字重**(灰 #a8abb2 / 400),不靠缩字号。
|
||
*
|
||
* ⚠️ 换成 1em 有个连带项:`margin-right` 原来是 0.35em,
|
||
* 而 em 是相对**编号自身**字号的。字号从 14.88 → 24 后,
|
||
* 同一个 0.35em 会从 5.2px 变成 8.4px,间距明显偏大。
|
||
* 所以同步收到 **0.25em**(24px ⇒ 6.0px、20 ⇒ 5.0px、17 ⇒ 4.25px),
|
||
* 与原来 5.2px 的观感基本一致。
|
||
*
|
||
* ── font-weight / font-style 必须显式重置 ────────────────────
|
||
* span 会继承标题的 font-weight(700/600)和可能的斜体。
|
||
* 不重置的话"灰色但加粗"仍然很重,弱化就白做了。
|
||
*
|
||
* ── 🔴 为什么仍保留 `display: inline-block` ────────────────────
|
||
* 这一条最初是为了修「小字号撑高行盒」,字号改成 1em 之后
|
||
* **同字号本身已经不撑高了**(实测 inline + inherit 也是 46px)。
|
||
* 但仍然保留,两个理由:
|
||
* ① 防回归 —— 以后谁把字号改回小号,不会立刻复发 3px;
|
||
* ② 编号成为原子盒,永远不跨行断开,始终贴在标题第一行开头。
|
||
*
|
||
* 下面是当时那个 3px 问题的完整记录,留着是因为**修法不直观**:
|
||
* 小字号的行内元素会把行盒**撑高**,实测 h2 46 → **49px**、h3 37 → **40px**,
|
||
* 每级都多 3px。3px 不起眼,但它出现在**每一个**标题上:长文 10 个二级标题
|
||
* 就多出 30px,h2 的灰底跟着变高,整篇标题的节奏全变;更麻烦的是它**只在
|
||
* 该标题有编号时出现**,于是「有编号的文章」和「没编号的文章」行距不一致,
|
||
* 极难归因。
|
||
*
|
||
* ⚠️ 我先试过 `line-height: inherit`(以及写死 46px)—— **完全无效**,
|
||
* 仍 49px。原因值得记下来,因为直觉是反的:
|
||
*
|
||
* 同行高下,行内盒的上下边界由「半行距」决定,而半行距
|
||
* 把 content-area **居中**塞进 line-height:
|
||
*
|
||
* 盒底 = baseline + desc×fs + (L − fs) / 2
|
||
* h2 (fs=24, L=46): 0.25×24 + (46−24)/2 = 17.00
|
||
* span(fs=14.88,L=46): 0.25×14.88+ (46−14.88)/2 = 19.28 ← 多探 2.28
|
||
*
|
||
* **字号越小,半行距越大**,盒底反而越往下走。所以「让两者共用行高」
|
||
* 不是解药,恰恰就是病根 —— line-height 怎么调都救不回来。
|
||
*
|
||
* ⚠️ `vertical-align` 也试过:`baseline` 仍 49px;`middle` 48.52px。
|
||
*
|
||
* ✅ 真解:把编号变成**原子行内盒**(inline-block),它就只按自身内容
|
||
* 高度参与行盒,不再受半行距拉扯。配 `line-height: 1` 让盒高正好
|
||
* 等于字号(14.88px),基线落在 asc 处 —— 上下都远在 strut 之内,
|
||
* 实测 h2 46→**46**、h3 37→**37**,一分不多。
|
||
* (八组隔离试验的完整数据见 `_tooling/yang_theme_test/_diag362b.js`。)
|
||
*
|
||
* 副作用检查:inline-block 不会跨行断开 ⇒ 编号永远留在标题第一行开头,
|
||
* 正是想要的;`white-space: nowrap` 随之只作用于这个原子盒,不会影响标题文字。
|
||
*
|
||
* ⚠️ 归档页 `h3.ar-year` 同样不会带编号 —— 编号是在 the_content
|
||
* 过滤器里按「目录条目」插的,而归档短代码的年份标题不在
|
||
* yang_toc_scan() 的结果里(它们是 [Archives] 渲染时才产生的),
|
||
* 所以天然不受影响。评论区 h3 同理(不在 .content 内)。 */
|
||
.k-main .details .article .content .yang-h-num {
|
||
/* 🔴 原子行内盒:不参与行盒的半行距计算,标题高度才不会被撑高(见上)
|
||
*
|
||
* 3.2.63:字号改成 1em(与标题同大)。用户反馈 0.62em 太小、"很不协调"。
|
||
* 实测同字号之后,inline / inherit 也不会撑高了(撑高本来就是小字号的
|
||
* 半行距造成的,字号一致时半行距也一致)。但 display 仍保留 inline-block:
|
||
* ① 防回归 —— 以后若有人把字号改回小号,不会立刻复发 3px 问题;
|
||
* ② 编号变成原子盒,永远不会跨行断开,始终贴着标题第一行开头。 */
|
||
display: inline-block;
|
||
line-height: 1;
|
||
/* 🔴 margin-right 是相对**编号自身**字号的(0.35em 在 14.88px 时是 5.2px)。
|
||
* 字号改成 1em 后同一个 0.35em 会变成 8.4px,间距明显偏大 ⇒ 同步收到 0.25em
|
||
* (24px 标题 ⇒ 6.0px,20px ⇒ 5.0px,17px ⇒ 4.25px,与原来的观感接近)。 */
|
||
margin-right: 0.25em;
|
||
color: #a8abb2;
|
||
font-size: 1em;
|
||
font-weight: 400;
|
||
font-style: normal;
|
||
/* 数字等宽,1.1 和 3.10 宽度一致,多行标题才不会看着参差 */
|
||
font-variant-numeric: tabular-nums;
|
||
/* 编号自身不换行(inline-block 本来也不拆,写上是为了并列时也不拆) */
|
||
white-space: nowrap;
|
||
}
|
||
|
||
/* 暗色站点:跟目录序号同一个灰,否则 #a8abb2 在深色底上过亮 */
|
||
html.yang-dark .k-main .details .article .content .yang-h-num {
|
||
color: #767d88;
|
||
}
|
||
|
||
/* 列表缩进与行距 */
|
||
ul {
|
||
margin-left: 2em;
|
||
}
|
||
|
||
ol {
|
||
margin-left: 2em;
|
||
}
|
||
|
||
ol > li {
|
||
line-height: 1.8;
|
||
}
|
||
|
||
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;
|
||
}
|