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 2024.05.24 | |
@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); | |
} | |
.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; | |
} | |
} |
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?
Oh yikes, yes that's awful. I've removed the td.default div:first-child
rule altogether, the HTML has obviously been updated and it no longer targets whatever it was it was originally supposed to! Hopefully the update propagates quickly to a stylesheet extension near you...
Thanks @christippett ! I noticed the same the other day; turned it off assuming (correctly) that it'll get fixed. Appreciate this HN restyle!
Just noticed that if I try to style a code block by indenting it 4 spaces, it won't monospace it as it's supposed to...
@pmarreck leave it with me, I'll look into it.
While we're posting bugs: there's an issue with the column widths becoming unwieldy if the first item on a page happens to be a sponsored post (ie. a YC company job ad). These items don't allow for up/down votes which throws out the alignment for the rest of the table. I've noticed this mostly when viewing page 2+ onwards.
And it's back to not being applied. I'm clueless as to what's happening.