GitHub Windows 版:将 GitHub 转换为 Windows 95
介绍如何创建一个用户样式,将 GitHub 用户界面更改为类似于 Windows 9x 时代的经典 Windows GUI。
- GitHub 仓库 — 源代码和安装说明
- 使用 Stylus 安装 — 直接安装
- 使用 Stylish 安装 — 通过 UserStyles.org 安装
- 使用 TamperMonkey 安装 — 通过 UserStyle.org 作为用户脚本安装
引言
大约一个月前,@nikitonsky 在 Twitter 上发布了一则关于 GitHub 重新设计的笑话。我觉得这个笑话太棒了,不应该仅仅停留在笑话的层面。所以,让我们用一个功能齐全的 Windows 主题来庆祝微软收购 GitHub 吧。
颜色
“经典” Windows 主题实际上经历了很多迭代。Windows 的早期版本有白色背景,略带圆角的按钮,带有粗的伪 3D 边框。在 Windows 95 中,背景变成了浅灰色,大多数控件获得了尖角,伪 3D 线变成了单像素厚。Windows 98 在窗口标题中引入了渐变,但风格基本保持不变。Windows 2000 中的 Windows 颜色略带黄色。
我决定选择纯粹的 Windows 95 颜色,但将所有颜色提取到 CSS 变量(或“自定义属性”)中,以便以后能够实现多种颜色方案。
--color-button-text: rgb(0, 0, 0);
--color-button-face: rgb(192, 192, 192);
--color-button-highlight: rgb(255, 255, 255);
--color-button-shadow: rgb(128, 128, 128);
--color-button-shadow-dark: rgb(0, 0, 0);
--color-button-checked: rgb(223, 223, 223);
--color-window-text: rgb(0, 0, 0);
--color-window: rgb(255, 255, 255);
--color-active-caption-text: rgb(255, 255, 255);
--color-active-caption: rgb(0, 0, 128);
--color-info-background: rgb(255, 255, 192);
--color-highlight-text: rgb(255, 255, 255);
--color-highlight: rgb(0, 0, 128);
--color-gray-text: rgb(128, 128, 128);
--color-link: rgb(0, 0, 255);
--color-hover: rgb(223, 223, 255);
字体
我找不到通过 CSS 禁用 ClearType 的方法,因此不得不采用 MS Sans Serif 字体。
body {
background: var(--color-button-face) !important;
font: var(--font) !important;
}
其中
--font-family: MS Sans Serif, MS Reference Sans Serif, Liberation Sans, Tahoma, sans-serif;
--font-size: 12px;
--font-line: 1.2;
--font: var(--font-size)/var(--font-line) var(--font-family);
经典 Windows GUI 中的字体大小和样式几乎没有变化,因此我不得不在很多地方添加 font: inherit !important;
。现在可以使用 ::selection
为整个页面设置选择背景和颜色(Firefox 由于某些原因仍然需要前缀)
::selection {
color: var(--color-highlight-text) !important;
background: var(--color-highlight) !important;
}
考虑到我采用了可读性强的正文字体,我决定不改变等宽字体,而是将其保持原样,不更改为 Courier New。
3D
下一个问题是绘制伪 3D 效果。CSS 目前只支持单个 border
,所以我添加了第二个使用 box-shadow
的边框。(后来我发现 border-image
非常强大,所以我计划在以后的版本中更改此代码。)
ListBox, TextBox, TreeView...
我们来给列表框和其他白色“凹陷”控件上色。
.file-wrap,
.blob-wrapper,
#readme,
.overall-summary,
.issues-listing > div[class^=border] {
background: var(--color-window) !important;
border: solid 1px black !important;
border-color: var(--box-3d-border-color) !important;
border-radius: 0 !important;
box-shadow: var(--box-3d-box-shadow) !important;
}
其中
--group-3d-border-color:
var(--color-button-highlight)
var(--color-button-shadow)
var(--color-button-shadow)
var(--color-button-highlight);
--box-3d-box-shadow:
0 -1px 0 0 var(--color-button-shadow),
-1px 0 0 0 var(--color-button-shadow),
-1px -1px 0 0 var(--color-button-shadow),
-1px 1px 0 0 var(--color-button-highlight),
1px 0 0 0 var(--color-button-highlight),
1px 1px 0 0 var(--color-button-highlight);
我不得不添加大量的阴影以避免产生单像素的“圆角”(通过顶部向上和底部向下的阴影,右上角和左下角的像素保持不变。)
Button
按钮也采用了类似的方案。
.btn-link,
.btn,
.btn:hover,
.subnav-item,
.pagination > :not(.gap),
#user-links .dropdown,
.js-menu-close {
font: inherit !important;
font-weight: normal !important;
background: var(--color-button-face) !important;
color: var(--color-button-text) !important;
border: solid 1px transparent !important;
border-color: var(--button-3d-border-color-exact) !important;
border-radius: 0 !important;
box-shadow: var(--button-3d-box-shadow-exact) !important;
margin: 1px 2px !important;
}
其中
--button-3d-border-color-exact:
var(--color-button-face)
var(--color-button-shadow)
var(--color-button-shadow)
var(--color-button-face);
--button-3d-box-shadow-exact:
0 -1px 0 0 var(--color-button-highlight),
-1px 0 0 0 var(--color-button-highlight),
-1px -1px 0 0 var(--color-button-highlight),
-1px 1px 0 0 var(--color-button-shadow-dark),
1px 0 0 0 var(--color-button-shadow-dark),
1px 1px 0 0 var(--color-button-shadow-dark);
按钮有更多的子项,如图标和向下箭头,按下时边框样式会改变,并且有焦点框。焦点框可以用第三个边框属性 outline
来绘制。
.btn-link svg,
.btn svg,
.btn:hover svg,
.subnav-item svg,
#user-links .dropdown svg,
.js-menu-close svg {
fill: var(--color-window-text) !important;
}
.btn-link .dropdown-caret,
.btn .dropdown-caret,
.btn:hover .dropdown-caret,
.subnav-item .dropdown-caret,
#user-links .dropdown .dropdown-caret {
color: var(--color-window-text) !important;
border-top-color: var(--color-window-text) !important;
}
.btn-link:active,
.btn:active,
.btn.selected,
[open] > .btn,
.subnav-item:active,
.pagination > :active,
#user-links .dropdown:active,
.js-menu-close:active {
border-color: var(--color-button-shadow) !important;
box-shadow:
0 0 0 1px var(--color-button-shadow-dark)
!important;
}
.btn-link:focus,
.btn:focus,
.subnav-item:focus {
outline: dotted 1px var(--color-button-text) !important;
outline-offset: -4px !important;
}
TabControl
选项卡标题有圆角。幸运的是,这是现代浏览器支持的一项功能,甚至可以为每个角设置不同的 border-radius
值。
.tabnav-tabs a, .tabnav-tabs span:not(.Counter), .reponav-item, .select-menu-tab a { font-size: 12px; font-weight: normal !important; color: var(--color-button-text) !important; background: var(--color-button-face) !important; border: solid 1px transparent !important; border-color: var(--button-3d-border-color) !important; border-bottom: none !important; border-radius: 2px 2px 0 0 !important; box-shadow: 1px 0 0 var(--color-button-shadow-dark), 0 1px 0 var(--color-button-highlight) !important; margin: 0 1px -1px 0 !important; padding: 4px 6px !important; min-height: 26px; }
只剩下一些小的细节:禁用的选项卡标题是灰色文本,选定的选项卡没有边框(通过负外边距实现,将选项卡标题移到选项卡内容下方)
.tabnav-tabs a.selected,
.tabnav-tabs span:not(.Counter).selected,
.reponav-item.selected,
.select-menu-tab a.selected {
box-shadow:
1px 0 0 var(--color-button-shadow-dark),
0 1px 0 var(--color-button-face)
!important;
margin: -2px 1px 1px 0 !important;
min-height: 28px;
}
.tabnav-tabs span:not(.Counter) {
color: var(--color-gray-text) !important;
}
GroupBox
分组框有脊状边框样式。不幸的是,由于不同浏览器渲染效果的差异,无法使用标准的 groove
和 ridge
边框样式。
.Box:not(.position-absolute):not(.Popover-message),
.blankslate,
.border,
.timeline-comment,
.commit-tease {
font: inherit !important;
color: inherit !important;
line-height: 20px !important;
background: var(--color-button-face) !important;
border: solid 1px black !important;
border-color: var(--group-3d-border-color) !important;
border-radius: 0 !important;
box-shadow: var(--group-3d-box-shadow) !important;
position: relative !important;
padding: 12px 8px 4px 8px;
margin-top: 2px !important;
}
其中
--group-3d-border-color:
var(--color-button-highlight)
var(--color-button-shadow)
var(--color-button-shadow)
var(--color-button-highlight);
--group-3d-box-shadow:
0 -1px 0 0 var(--color-button-shadow),
-1px 0 0 0 var(--color-button-shadow),
-1px -1px 0 0 var(--color-button-shadow),
-1px 1px 0 0 var(--color-button-highlight),
1px 0 0 0 var(--color-button-highlight),
1px 1px 0 0 var(--color-button-highlight);
分组框很好,但没有标题就看起来不像分组框。让我们至少在一些地方添加标题。
.js-notice > .border::before,
.commit-tease::before {
color: var(--color-button-text) !important;
background: var(--color-button-face) !important;
position: absolute;
left: 6px;
top: -11px;
padding: 0 3px;
}
.js-notice > .border::before {
content: "Notice";
}
.commit-tease::before {
content: "Last commit";
}
其他控件
有窗口、工具提示和其他控件,但它们并没有什么特别有趣的地方。
图标
图标可以使用经典的 Resource Hacker 工具提取。难以置信的是,这个工具仍然存在,仍然是免费软件,并且仍在开发中。所以,让我们获取 Windows 95 并从所有系统 DLL 和 EXE 文件中挖掘图标...
现在,我们将图标放入 CSS。首先,我们需要从 ICO 文件中提取单独的图标尺寸(我为此使用了 Total Commander 的 Imagine 插件,但任何支持 ICO 的图像编辑器都可以),进行极致优化(我使用了 TinyPNG 服务),并将其编码为 Data URI(Base64-Image 服务派上了用场。)这就是我们得到的结果
--image-folder: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAGFBMVEUAAAD//5nMzGYAAAD/zJmZmQD//8zx8fEIMK00AAAAAXRSTlMAQObYZgAAAE5JREFUCNdjQIDQ0GAwzVqWKGoAYgQpKSmFhoYyMISlgYCQAUOYIAg4QRgiIjARR4iICFzEESIiAgQghiMQuAAZQUpgYMDAbAwGBgwYAABoaBIom9Nm3gAAAABJRU5ErkJggg==');
--image-folder-documents: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAMFBMVEUAAACZmQD//5n/zJn///8zMwDn59aGhobMzGZVVVUAM5mAgADx8fH/+/Dq6upNTU2p3qmcAAAAAXRSTlMAQObYZgAAAGlJREFUCNdjAIECBghgfwmmGAVLrn0AMSTaXY68BDNKXNYem72BgUE8LSsrLXMDgyAYpH1gEHEBAguxTAYRJSUlZWWxAAZGJWUlI+NGIAMkoGwIZAAFjIyADAZhZYgIVD+QwRoKAgxwAADcLBkG7Oto1QAAAABJRU5ErkJggg==');
.octicon-file-directory, .octicon-file {
fill: transparent !important;
width: 16px !important;
height: 16px !important;
}
.octicon-file-directory { background: var(--image-folder) !important; }
.octicon-file { background: var(--image-file-text) !important; }
最后的几点
该网站使用了大量的样式,每个“控件”都有许多不同的 CSS 类。还有一些小项目,如圆圈中的计数器。将其转换为纯文本是符合逻辑的,就像在 Windows 9x 时代所做的那样。
.Counter {
background: inherit !important;
font: inherit !important;
color: inherit !important;
padding: 0 !important;
}
.Counter::before {
content: "(";
}
.Counter::after {
content: ")";
}
用户样式头
在现代,拥有“标准”的 .user.css 头很重要,它被 Stylus 扩展支持。
/* ==UserStyle==
@name GitHub Windows Edition [Ath]
@namespace https://github.com/Athari
@version 0.5.0
@description Transforms GitHub's pages into GUI resembling Windows 9x.
@author Athari
@homepageURL https://github.com/Athari/CssGitHubWindows
@license MIT
==/UserStyle== */
如果您打开带有此头的文件,Stylus 会提供安装样式的选项,并定期检查更新。无需使用可疑的 UserStyles.org。
完成!
好吧,大概就是这样。用户样式仍处于 alpha 阶段,许多页面尚未完全转换。但我自己已经使用了该样式大约两周,几乎没有什么东西似乎坏了。
您可以使用 Stylus 或 Stylish(或 TamperMonkey)来安装用户样式。链接在顶部。
附注:Stylish 最近因窃取用户完整历史记录而被 Firefox 和 Chrome 的扩展商店移除,所以如果您仍在使用它,请务必小心。
关注点
一些 bug 已经被报告,所以我需要尽快修复它们。
然后我需要引入一个构建系统,因为目前它是一个纯 CSS 文件。完成后,该样式可以轻松扩展以支持多个主题(不同的扩展使用不同的语法来实现这一点)。
一些人提出了有趣的建议。一个是在错误页面上显示 BSOD(蓝屏死机),另一个是 Clippy 助手。两者看起来都非常有趣。
历史
- 0.5.0 — 首次发布