Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web

GitHub Windows Edition: transforming GitHub into Windows 95

5.00/5 (7 votes)
8 Jul 2018MIT4 min read 11.6K  
A walkthrough of creating a user style which changes GitHub user interface to one resembling classic Windows GUI from Windows 9x.

Introduction

Image 1

About a month ago, @nikitonsky posted a joke about GitHub redesign on Twitter. I thought the joke is too good to remain merely a joke. So let's celebrate Microsoft's acquisition of GitHub with a full-featured Windows theme.

Colors

"Clasic" Windows theme actually had many iterations. First versions of Windows had white backgrounds, slightly rounded buttons with thick pseudo-3D borders. In Windows 95, background became light gray, most controls acquired sharp corners and pseudo-3D lines became single pixel thick. Windows 98 introduced gradients in window titles, but the style mostly remained the same. Windows in Windows 2000 became slightly yellowish.

I decided to choose pure Windows 95 colors, but extracted all colors into CSS variables (or "custom properties") to make multiple color schemes possible later.

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);

Fonts

I couldn't find a way to disable ClearType through CSS, so had to settle for MS Sans Serif font.

CSS
body {
  background: var(--color-button-face) !important;
  font: var(--font) !important;
}

where

CSS
--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);

There's almost no variation in font sizes and styles in classic Windows GUI, so I had to add font: inherit !important; in many places. Selection background and color can be set for the whole page using ::selection nowadays (Firefox still requires prefix for some reason):

CSS
::selection {
  color: var(--color-highlight-text) !important;
  background: var(--color-highlight) !important;
}

Considering I settled with a readable main font, I decided to not mess with the monospace font and leave it as is whithout changing to Courier New.

3D

The next problem is drawing pseudo-3D. CSS still supports only single border, so I added a second one with box-shadow. (Later I discovered that border-image is very powerful, so I plan to change this code in later versions.)

ListBox, TextBox, TreeView...

Let's color list boxes and other white "lowered" controls:

CSS
.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;
}

where

CSS
--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);

I had to add so many shadows to avoid causing single-pixel "round" corners (with top-up and bottom-down shadows, top-right and bottom-left pixels remain uncolored.)

Button

A similar approach with buttons:

CSS
.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;
}

where

CSS
--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);

Buttons have more sub-items like icons and down-arrows, change border style when pressed and have a focus rectangle. Focus rectangle can be drawn with the third border property, outline.

CSS
.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

Tab headers have rounded corners. Thankfully, that's one feature which is supported in modern browsers, even with separate border radius values for every corner.

.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;
}

Only a few little details remain: gray text on disabled tab headers, no border on selected tabs (implemented using negative margin which moves tab header below tab content):

CSS
.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

Group boxes have ridge border style. Unfortunately, standard groove and ridge border styles are impossible to use due to different rendering in different browsers.

CSS
.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;
}

where

CSS
--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);

Groups are nice, but don't look like groups without headers. Let's add headers at least in a few spots.

CSS
.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";
}

Other controls

There're windows, tooltips and other controls, but there's nothing interesting about them.

Icons

Icons can be extracted using good old Resource Hacker. Hard to believe, but the tool is still alive, still true freeware and is still being developed. So let's get Windows 95 and dig for icons in all system DLLs and EXEs...

Now, let's put the icons into CSS. First, we need to extract separate icon sizes from ICO files (I used Imagine plugin for Total Commander for this, but any image editor which supports ICO would work), optimize to the last bit (I used TinyPNG service) and encode as Data URI (Base64-Image service came in handy.) This is what we get:

CSS
--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==');
CSS
.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; }

Last bits

The website uses a ton of styles, every "control" has many different CSS classes. Also there're little items like counters in circles. It would be logical to transform them into pure text, as would've been done in Windows 9x age:

CSS
.Counter {
  background: inherit !important;
  font: inherit !important;
  color: inherit !important;
  padding: 0 !important;
}
.Counter::before {
  content: "(";
}
.Counter::after {
  content: ")";
}

User style header

In the modern age, it's important to have the "standard" .user.css header, which is supported by Stylus extension:

CSS
/* ==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== */

If you open a file with this header, Stylus will offer to install the style and will check for updates periodically. No need for shady UserStyles.org.

Done!

Well, more or less. The user style is still in the alpha stage, many pages aren't completely converted. But I've been using the style for about two weeks myself and almost nothing seems to be broken.

You can install the user style using either Stylus or Stylish (or TamperMonkey). Links are at the top.

P.S. Stylish has recently been removed from Firefox's and Chrome's extension stores for spying on users' complete history, so please be careful if you're still using it.

Points of Interest

A few bugs have already been reported, so I need to fix them ASAP.

Then I need to introduce a build system as currently it's one pure CSS file. Once this is done, the style can be easily expanded to support multiple themes (different extensions use different syntax for this).

Some people have suggested interesting ideas. One is BSOD (blue screen of death) on error pages, another is Clippy assistant. Both look very interesting.

History

  • 0.5.0 — First release

License

This article, along with any associated source code and files, is licensed under The MIT License