A modern re-styling of the Hacker News front page, including automatic light/dark mode.
-
-
Save christippett/5097af0ea59c867c4578996350933776 to your computer and use it in GitHub Desktop.
/* ==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 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!
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.
Sure thing! If I stumble across a cause/solution I'll post it here
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
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.
I've been on HN so long that I actually had no idea that they limited who could actually vote or comment. 😮
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.
@gingerbeardman
I just got an account on lobste.rs. It feels like early Reddit. I get your point of view though.
If either of you have a spare invite I'd appreciate the hook up 🙂 I've largely stopped visiting Reddit since the API debacle.
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.
I can't send invitations yet either. 70 days is quite a long time to force before allowing further invitations!
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"
yeah, I have some thoughts on that
-
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
-
70 days is too fucking long. A couple of weeks would be sufficient to accomplish the goals they use to defend this decision.
-
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
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.
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.
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?
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).
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.
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).
Hey, it seems like the Userstyle has stopped working - starting today, at least for me.
Using the Userstyle directly from this gist, fwiw.
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?
(actually, I applied to tilde.town via SSH. Which is an amazing user filter. LOL)
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.
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.
And it's back to not being applied. I'm clueless as to what's happening.
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.
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
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?
Another unexpected addition in the top bar (sorry)