Pull to refresh

GitHub превращается… превращается GitHub… в элегантный Windows 95

Reading time7 min
Views80K


В Твиттере какое-то время назад запостили шутку в честь приобретения Майкрософтом ГитХаба — страницу сайта, перестилизованную в стиле Windows 98. Я решил, что шутка слишком хороша, чтобы оставаться шуткой.


Цвета


"Классическая" тема Windows на самом деле имеет несколько итераций. Первые версии Windows (до 9x) отличались белыми окнами, слегка скругленными границами кнопок и очень сильным псевдо-объёмом. В Windows 95 окна приобрели серый цвет, всё стало более квадратным, а линии для создания псевдо-объёма уменьшились до одного пикселя. В Windows 98 добавились градиенты, но в целом стилистика осталась более-менее прежняя. В Windows 2000 окна приобрели слегка желтоватый оттенок.


Я остановился на 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);

Шрифты


Добиться от браузера рендеринга пиксельных шрифтов не удалось, поэтому пришлось довольствоваться "MS Sans Serif":


  body {
    background: var(--color-button-face) !important;
    font: 12px/1.2 MS Sans Serif, MS Reference Sans Serif !important;
  }

В интерфейсе Windows размер шрифта почти повсеместно было одинаковый, поэтому на многих элементах приходится добавлять font: inherit !important;. Цвет выделения текста ныче можно переопределить с помощью ::selection, однако в Firefox оно почему-то до сих пор поддерживается только с префиксом.


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

И раз уж основной шрифт получился удобочитаемый, я решил оставить стандатный шрифт для кода в покое и не менять на "Courier New".


Объём


Следующая проблема — рисование объёма. Границы border в CSS до сих пор могут быть только в один слой, поэтому для двойных контуров пришлось воспользоваться box-shadow.


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 — третьего свойства 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


Ушки у вкладок скругленные. К счастью, уж скругленные-то уголки браузеры рисовать умеют, причём можно задать скругленность для каждого угла.


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

Однако группа элементов без заголовка уже не смотрится как группа. Давайте добавим заголовки хотя бы в некоторых местах.


  .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 и проходимся по всем бинарникам, выбирая красивые иконки...


Теперь, много часов спустя, пора положить иконки в CSS. Для этого извлекаем отдельные иконки из ICO в PNG (я воспользовался плагином Imagine для Total Commander, но вообще подойдёт любая программа, понимающая формат), оптимизируем до последнего бита (я воспользовался TinyPNG.com) и кодируем в виде Data URI в CSS (сервис Base64-Image.de оказался достаточно удобным). Получается примерно так:


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

Последние штрихи


На сайте огромное количество стилей, поэтому приходится проходить везде и всё стилизовать. И "кнопки", и "листбоксы" имеют довольно различающиеся классы. Также есть множество мелочей вроде счётчиков в кружочках, которые логично преобразовать в голый текст, как это сделали бы во времена Windows 95:


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

Шапка


Так как мы люди современные, то оформим "стандартизированную" шапку для UserCSS, которая поддерживается 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== */

Теперь, если открыть такой файл в браузере, расширение предложит применить стиль и будет следить за обновлениями. И не нужно никаких сомнительных UserStyles.org.


Готово!


Ну, более-менее. Стиль скорее в стадии proof-of-concept / alpha, потому что многие страницы перестилизованы не полностью. Но начало положено!



Если у вас стоят расширения для юзер-стилей, то вот прямые ссылки на установку:



P.S. Осторожно, Stylish недавно был удалён из списка расширений Firefox и Chrome за шпионаж. Советую перейти на современное опен-сорсное расширение Stylus, если вы этого ещё не сделали.

Tags:
Hubs:
Total votes 206: ↑202 and ↓4+198
Comments82

Articles