Skip to content

Instantly share code, notes, and snippets.

@christippett
Last active March 21, 2024 15:50
Show Gist options
  • Save christippett/5097af0ea59c867c4578996350933776 to your computer and use it in GitHub Desktop.
Save christippett/5097af0ea59c867c4578996350933776 to your computer and use it in GitHub Desktop.
Hacker News Stylesheet

Hacker News userstyle

A modern re-styling of the Hacker News front page, including automatic light/dark mode.

Install directly with Stylus

Screenshots

HN 1

HN 2

/* ==UserStyle==
@name Hacker's New CSS
@author Chris Tippett <git@christippett.dev> (https://christippett.dev)
@description A modern retake on the classic Hacker News design.
@version 2023.05.28
@namespace @christippett
@homepageURL https://github.com/christippett
@supportURL https://gist.github.com/christippett/5097af0ea59c867c4578996350933776/
@updateURL https://gist.github.com/christippett/5097af0ea59c867c4578996350933776/raw/hn.user.css
@license MIT
@preprocessor uso
==/UserStyle== */
@-moz-document domain("news.ycombinator.com") {
:root {
color-scheme: light dark;
}
html {
--font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI",
Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif,
"Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol",
"Noto Color Emoji";
--primary: #ff6600;
--primary-alt: #c8c5c5;
--text-color: #4b4b4b;
--text-color-alt: #828282;
--table-bg: #fcfffa;
--body-bg: #f6f6ef;
--border-color: #f6f6ef;
--border-radius: 3px;
--smaller: 0.8em;
--content: 0.96rem;
font-size: 14px;
color: var(--text-color);
}
@media (prefers-color-scheme: dark) {
html {
--text-color: white;
--text-color-alt: #c3c3c3;
--primary-alt: #828282;
--border-color: #1b1b1c;
--table-bg: #232323;
--body-bg: #1b1b1c;
}
}
* {
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
-webkit-border-horizontal-spacing: 0;
-webkit-border-vertical-spacing: 0;
font-family: var(--font-family) !important;
}
body {
padding: 20px 40px 50px;
background-color: var(--body-bg);
}
@media (max-width: 750px) {
body {
padding: 0;
}
}
body > center {
position: relative;
}
table {
width: 100%;
}
td {
font-size: 1rem;
color: var(--text-color);
}
br {
padding: 0;
}
/* hide consecutive <br> tags */
br + br {
display: none;
}
i {
font-size: calc(var(--content) / 1.1);
margin: 0 0.25em;
}
font[size] {
font-size: var(--smaller);
}
/* help text on profile & post submission pages */
font[size="2"],
html[op="submit"] form > table tr:last-child td {
font-size: var(--smaller);
color: var(--text-color-alt);
font-style: italic;
}
a,
a:link {
color: var(--text-color);
text-underline-offset: 2px;
text-decoration-color: var(--text-color-alt);
}
a:visited {
color: var(--text-color-alt);
}
form {
padding: 0;
max-width: 700px;
}
textarea,
input,
select,
a.morelink {
max-width: 90%;
border: none;
font-size: var(--smaller);
border-radius: var(--border-radius);
color: var(--text-color-alt) !important;
padding: calc(var(--smaller) / 2) var(--smaller);
box-shadow: inset 0 0 1px var(--primary-alt);
outline: 1px solid var(--border-color);
background-color: var(--body-bg);
}
textarea + a {
padding: 0.25rem;
}
textarea:focus,
input:not([type="submit"]):focus {
background-color: var(--table-bg);
}
/* button style */
input[type="submit"],
a.morelink {
cursor: pointer;
margin: 0.75rem 0;
display: inline-flex;
align-items: center;
letter-spacing: 0.2px;
text-transform: capitalize;
text-decoration: none !important;
}
form input[type="submit"]:hover,
a.morelink:hover {
text-decoration: underline !important;
}
input[name="q"] {
background: var(--table-bg);
}
/* --- LOGIN / CREATE ACCOUNT --*/
html:not([op]) body {
background-color: var(--table-bg);
}
html:not([op]) b {
display: inline-block;
margin-top: 1rem;
}
a[href="forgot"] {
display: inline-block;
margin-top: -1rem;
padding: 0.75rem;
color: var(--text-color-alt) !important;
font-style: italic;
text-decoration: none;
font-size: var(--smaller);
}
/* --- USER PROFILE --- */
#pagespace + tr > td:empty {
display: none;
}
form > table td {
padding: 0.25rem;
width: 100%;
}
/* field labels */
form > table td:first-child {
width: auto;
min-width: 120px;
padding-right: 1rem;
font-size: 0.75rem;
font-weight: 500;
text-transform: uppercase;
}
/* --- TABLE / LAYOUT --- */
#hnmain {
max-width: 900px;
overflow: hidden;
background: var(--table-bg);
border-radius: var(--border-radius);
box-shadow: 0 0 1px var(--primary-alt);
}
/* only add padding for parent table cells */
#hnmain > tbody > tr:not(:first-child) > td {
padding: 1rem;
width: 100%;
}
#hnmain tr:not(.spacer):empty {
display: none;
}
.morespace {
display: none;
}
.morespace + tr td {
padding: 0.5rem 0;
}
.spacer {
height: 1rem !important;
}
/* error message shown if not logged in when making comment */
html[op="x"] #hnmain > tbody > tr:last-child td {
color: transparent;
}
/* --- HEADER --- */
td[bgcolor="#ff6600"] {
background: linear-gradient(#ff6600, #eb5f00);
}
td[bgcolor="#000000"] {
background: linear-gradient(#111111, #2c2b2a);
}
#hnmain > tbody > tr:first-child > td:first-child {
padding: 0.4rem 0.6rem;
}
#hnmain > tbody > tr:first-child > td:first-child > table td {
height: auto !important;
line-height: 1 !important;
vertical-align: middle;
}
.pagetop {
color: #fff;
line-height: 1;
font-weight: 500;
font-size: var(--smaller);
padding: 0 0.5rem;
}
.pagetop font {
font-weight: bold;
}
.pagetop a,
.pagetop a:visited {
color: #fff;
line-height: 1rem;
}
.pagetop a:hover,
.sitebit a:hover {
text-decoration: underline;
text-decoration-thickness: 1px;
text-underline-offset: 2px;
}
/* 'hacker news' title */
.hnname {
margin-right: 0.5rem;
text-transform: uppercase;
font-size: 1.1rem;
font-weight: 800;
}
.hnname a:hover {
text-decoration: none !important;
}
#me {
font-weight: 600;
font-style: italic;
}
#karma {
font-size: var(--smaller);
line-height: 1rem;
display: inline-flex;
align-items: center;
cursor: grabbing;
}
/* can't remember what this was supposed to hide */
span:not([class])[id]:not(#karma) {
display: none;
}
/* ---- FRONT PAGE ---- */
.sitebit a:hover {
text-decoration-color: var(--primary);
}
/* stories from [Month] [Day], [Year] */
#pagespace + tr > td > div {
padding: 0 0 1rem;
margin: 0 0 1rem !important;
border-bottom: 1px solid var(--primary-alt);
font-size: var(--content);
font-weight: 500;
}
#pagespace + tr > td > div > div {
font-style: italic;
font-size: var(--smaller);
margin-top: 0.25rem !important;
}
.hnmore a,
.hnmore a:link,
.hnmore a:visited {
color: var(--text-color-alt);
}
/* --- ARTICLE --- */
.rank {
color: var(--text-color-alt);
font-weight: 500;
}
.title {
font-size: 1rem;
overflow: unset;
}
.title .titleline {
width: 100%;
font-weight: 500;
display: flex;
gap: 1rem;
justify-content: space-between;
align-items: baseline;
}
/* transparent parantheses around url */
.titleline .sitebit {
color: transparent;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
display: block;
}
.subtext span.subline,
.subtext span.subline a {
display: inline-block;
color: var(--text-color-alt);
font-size: 0.9rem;
padding: 2px 0;
}
.subtext .score {
color: var(--text-color-alt);
font-weight: 600;
border-radius: var(--border-radius);
}
/* ---- COMMENTS ---- */
/* text color */
.c00,
.c00 a:link {
color: var(--text-color);
text-decoration-color: var(--primary-alt);
}
table.itemlist,
table.fatitem,
table.comment-tree {
position: relative;
}
html:not([op="reply"]) table.fatitem {
padding-bottom: 0.75rem;
margin-bottom: 0.75rem;
border-bottom: 1px solid var(--primary-alt);
}
td.default {
width: 100%;
position: relative;
padding: 0;
font-size: var(--content);
}
td.default div:first-child {
height: 18px;
display: inline-flex;
align-items: center;
margin: 0 !important;
}
.default p {
margin-top: var(--smaller);
}
.toptext,
form[action="comment"] {
padding: 1rem 0;
margin: 1em 0 0;
}
.toptext {
font-size: var(--content);
margin-bottom: -1rem;
}
/* comment: header/author/etc */
.comhead {
font-size: var(--smaller);
color: var(--text-color-alt);
}
a.hnuser {
font-weight: 500;
}
.comment {
font-size: var(--content);
line-height: 1.4;
color: var(--text-color);
margin: 0 0 0.5rem;
padding: 0.4rem 0.8rem;
}
.reply {
margin-top: 0.8rem;
text-transform: capitalize;
}
.reply a,
.reply a:link,
.reply a:visited {
color: var(--text-color-alt);
text-decoration-color: var(--primary-alt);
}
.reply u {
text-decoration: none;
}
.navs {
margin-left: 0.25ch;
display: inline-flex;
align-items: center;
gap: 0.75ch;
}
a.togg {
padding: 0.1em 0.2em;
font-weight: bold;
border-radius: var(--border-radius);
/*background-color: red;*/
}
/* --- UPVOTE/DOWNVOTE LINKS --- */
.votelinks {
position: relative;
text-align: center;
padding: 0;
--icon-size: 1rem;
}
.votelinks center {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
background: var(--table-bg);
padding: 0 0.25rem;
}
/* self-post indicator */
.votelinks center img,
.votelinks center br {
display: none;
}
.votelinks center font {
height: 1rem;
width: 1rem;
color: transparent;
}
.votelinks center font:before {
content: "★";
color: var(--primary);
display: inline-block;
font-size: 0.8em;
}
.votearrow {
background: none;
margin: 0;
width: auto;
height: auto;
transform: unset !important;
}
.votearrow:before {
width: 1rem;
height: 1rem;
padding: 1px;
display: block;
line-height: 1;
font-size: 0.9em;
text-align: center;
border-radius: 50%;
color: var(--text-color-alt);
transition: transform 100ms ease-in-out;
}
.votearrow[title="upvote"]:before {
content: "↑";
}
.votearrow[title="downvote"]:before {
content: "↓";
}
a.clicky:hover > .votearrow:before,
a.clicky.nosee > .votearrow:before {
color: var(--primary);
}
a.clicky:hover > .votearrow:before {
transform: scale(1.2);
}
.votelinks a.nosee {
visibility: visible;
font-weight: bold;
}
/* ---- FOOTER ---- */
#hnmain > tbody > tr:has(.yclinks) {
position: absolute;
bottom: 0;
left: 0;
right: 0;
display: flex;
justify-content: center;
transform: translateY(100%);
z-index: 99;
padding: 1rem 0;
}
/* footer: hide orange horizontal bar above footer */
img[src="s.gif"] + table {
display: none;
}
.yclinks {
display: flex;
align-items: center;
justify-content: center;
gap: 0.5rem;
color: var(--text-color-alt);
margin: 0.5rem 0;
padding: 0.5rem 1rem;
width: max-content;
border-radius: calc(var(--border-radius) * 2);
}
.yclinks a:link {
color: var(--text-color-alt);
font-size: 0.9rem;
}
.yclinks a:hover {
text-decoration: underline;
text-underline-offset: 2px;
text-decoration-thickness: 1px;
text-decoration-color: var(--primary);
}
form[action="//hn.algolia.com/"]
{
color: var(--text-color-alt);
font-size: var(--smaller);
display: flex;
align-items: center;
justify-content: center;
gap: 1ch;
}
/* yc application notice */
center > a[href$="ycombinator.com/apply/"] {
color: var(--text-color-alt);
text-decoration: underline;
text-underline-offset: 2px;
font-weight: 500;
}
}
@pmarreck
Copy link

pmarreck commented Sep 2, 2023

Since I got banned by Reddit across everything thanks to "intelligence-free and thus sometimes accidentally too punitive fingerprinting", I can't even join "tildes" apparently. Is there another way to join?

@pmarreck
Copy link

pmarreck commented Sep 2, 2023

(actually, I applied to tilde.town via SSH. Which is an amazing user filter. LOL)

@christippett
Copy link
Author

Hey, it seems like the Userstyle has stopped working - starting today, at least for me.
Using the Userstyle directly from this gist, fwiw.

What extension are you using to apply the CSS? The gist hasn't been updated for awhile and it's still working fine for me on both Safari and Firefox.

@nervous-inhuman
Copy link

Hey, it seems like the Userstyle has stopped working - starting today, at least for me.
Using the Userstyle directly from this gist, fwiw.

What extension are you using to apply the CSS? The gist hasn't been updated for awhile and it's still working fine for me on both Safari and Firefox.

Stylus with Firefox, oddly enough, it seems to have fixed itself, but prior to that, it just wasn't getting applied at all.

@nervous-inhuman
Copy link

And it's back to not being applied. I'm clueless as to what's happening.

@christippett
Copy link
Author

And it's back to not being applied. I'm clueless as to what's happening.

When you next notice it not working, can you dump the HTML source here so I can take a look? Maybe there's an overly specific CSS selector that's not applying.

@nervous-inhuman
Copy link

And it's back to not being applied. I'm clueless as to what's happening.

When you next notice it not working, can you dump the HTML source here so I can take a look? Maybe there's an overly specific CSS selector that's not applying.

Yeah, I probably should've started with that, sorry.

Here it is: https://gist.github.com/nervous-inhuman/1e1f470ab7a108a8e4f759bcb77391ca

@christippett
Copy link
Author

christippett commented Sep 29, 2023

FYI I've been playing around with the style, mostly around the layout of items and the upvote/downvote links. I'll dogfeed it for a week to ensure I haven't completely broken things before I publish it. Maybe it'll fix things for a few of you – who knows!

@nervous-inhuman I loaded your HTML gist and the page rendered just fine with the current CSS. It perhaps suggests there's something else interfering with the style on your end?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment