Skip to content

Instantly share code, notes, and snippets.

@christippett
Last active March 21, 2024 15:50
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • 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;
}
}
@gingerbeardman
Copy link

Another unexpected addition in the top bar (sorry)

image

@christippett
Copy link
Author

@gingerbeardman I've just updated the stylesheet. I also realised that the version hosted on userstyles.org was a bit behind, which may have contributed to a few of the quirks you came across. I'd recommend using this gist going forward if you want to track future changes.

Please let me know if you notice anything missing or out of place!

@gingerbeardman
Copy link

Clicking a plus arrow on a comment I'm seeing this:

Screen shot 2023-07-19 at 13 52 04

Previously I clicked a plus arrow and and it disappeared.

I'm honestly not sure if either are intentional.

@christippett
Copy link
Author

I haven't changed or updated anything recently, so if it's a new thing you're noticing then maybe there's been a change to the site's HTML that I haven't accounted for.

I remember thinking it'd be nice to have something visual to indicate when I'd upvoted a comment rather than having it disappear, so it's very likely to be something in my CSS that's at fault. No promises it'll be anytime soon, but I'll make a note to look into it the next time I tinker with the style.

@gingerbeardman
Copy link

Sure thing! If I stumble across a cause/solution I'll post it here

@pmarreck
Copy link

I've had the upvote arrow click also show a downvote arrow style change for a while now.

And yet I still use this style because it's Just. That. Good. =)

It's pretty obvious to me at this point that other people may use sites like Reddit and Hacker News a lot more differently than I do (I'm big on participation via commenting, voting, etc... lol) since all of the bugs so far have to do with... commenting and/or voting. LOL

@christippett
Copy link
Author

You folks with your fancy downvote buttons. I'm close, but still shy of the number of points needed to see it, otherwise it'd surely be fixed by now!

I'm chuffed you like the style though! I'm thinking it might be time to turn this gist into a proper repo so it's easier to track these issues – but I also quite like the single threaded discussion we have going here. I'll think about it.

@pmarreck
Copy link

pmarreck commented Aug 8, 2023

I've been on HN so long that I actually had no idea that they limited who could actually vote or comment. 😮

@gingerbeardman
Copy link

gingerbeardman commented Aug 8, 2023

Off topic: I've been trying out Lobste.rs a kind of HN "alternative" and every limit they say is "for the benefit of the community" (eg. new users can't get support other than on IRC!) is borderline passive-aggressive - big turn off.

@pmarreck
Copy link

pmarreck commented Aug 8, 2023

@gingerbeardman
I just got an account on lobste.rs. It feels like early Reddit. I get your point of view though.

@christippett
Copy link
Author

If either of you have a spare invite I'd appreciate the hook up 🙂 I've largely stopped visiting Reddit since the API debacle.

@gingerbeardman
Copy link

Given my earlier message it may come as no surprise that new users cannot send invitations. I might be able to after 70 days, we'll see.

@pmarreck
Copy link

pmarreck commented Aug 9, 2023

I can't send invitations yet either. 70 days is quite a long time to force before allowing further invitations!

@gingerbeardman
Copy link

gingerbeardman commented Aug 9, 2023

More info about https://lobste.rs/about#invitations

Invitations are used as a mechanism for spam-control, to slow registrations to a pace we can acculturate (more below) and to encourage users to be nice, not to make the Lobsters userbase an elite club. Users are considered "new" for their first 70 days, and their usernames appear in green. New users can't send invites, submit links to domains we haven't seen submitted before, flag stories and comments, suggest edits to story titles and tags, resubmit links that have been seen before, or use tags for meta discussions or that are prone to off-topic stories (meta rant show announce satire job interview merkle-trees ask culture).

or "how to make new users feel worthless"

@pmarreck
Copy link

pmarreck commented Aug 10, 2023

yeah, I have some thoughts on that

  1. restricting new user uptake that much (especially when Reddit is basically bleeding users and has essentially jumped the shark) is an incredibly bad decision, at least from a business perspective

  2. 70 days is too fucking long. A couple of weeks would be sufficient to accomplish the goals they use to defend this decision.

  3. Restricting signups in any way, automatically turns it into an "elite club" of sorts, so it's too late to claim they aren't trying to do that =)

It's sad because I accidentally got permabanned across all my Reddit accounts after having an account there since almost the beginning of Reddit (I accidentally posted from a different account to a sub I had been banned from years prior, and Reddit very aggressively then flags ALL your accounts, which they determine via AI fingerprinting (!), as "ban circumvention offense accounts"... I'm not even joking... and then you can't even reach anyone to resolve it, and the mods are worthless ego-inflated assholes about it because they assume that since ALL your accounts are banned, you must be an asshole instead of a victim of an over-aggressive algorithm)

I can still browse Reddit (with a very ominous banner at the top if I'm logged in about how bad a person I am) but I'm very much a community participant type

@gingerbeardman
Copy link

I agree on all this. I've not been marked on Reddit but I did close the only sub I had and go there much less.

@christippett
Copy link
Author

I feel like given Reddit's current trajectory, being permabanned is almost like a badge of honour. I almost feel the same way for having a VAC ban on my Steam account from 18 years ago.

@pmarreck
Copy link

Ha, I'm a big Steam fan. It's a pretty big deal these days, and the Steam Deck is pretty sweet. What did you do to get banned? Do you lose access to whatever games you bought then? Did you ever start a new account?

@christippett
Copy link
Author

Oh, don't get me wrong – I love Valve/Steam and I'm especially appreciative of the work they're doing with Proton.

I was banned by Valve's anti-cheat system after I installed an aimbot/wallhack tool and played online. I was a stupid teenager and I'm thankful it only cost me an embarrassing mark on my Steam profile and not my whole account. The experience certainly hasn't stopped me from spending hundreds of dollars on Steam over the years (I also own the Steam Deck, amazing machine).

@gingerbeardman
Copy link

So I'm abandoning Lobsters, for all the reasons above. Just far too unfriendly and nobody needs that in 2023.

My new favourite place is Tildes.net which is another "Hacker News clone" but with much friendlier interface, onboarding, users and range of topics. Invites are quick, free and easy by posting at https://www.reddit.com/r/tildes/ at the time of writing this thread. Once invited you login and post new links through the sidebar.

@christippett
Copy link
Author

Interesting, I wonder if the name has any correlation with the Linux tilde communities that are out there (tilde.club, tilde.town are the two I'm familiar with).

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

@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