Show HN: Penumbra, a perceptually optimized color palette based on natural light (github.com)
For this palette, I used recent advances in color science, which made perceptual design more accessible, to choose a set of colors (mainly for syntax highlighting) that have uniform luminance for less visually uneven, fluidly readable code, but at the same time maximally distinguishable hue and chroma. The background colors are based on natural (sun-)light and shade for a more pleasing look than equally neutral greys.
For much more detailed info, including the construction, check out the repository.
There’s also already a (bare-bones) VSCode extension, linked in the repository, but it could admittedly use more informed distribution of colors over tokens, language specific highlighting and perhaps more opinionated use in UI elements.
126 comments
[ 2.9 ms ] story [ 189 ms ] threadAre you claiming it's a significant improvement over Solarised? Either way, good stuff.
I’m claiming it is an improvement in terms of usability, simply because Solarised wasn’t designed with these properties in mind. Whether it’s significant everyone needs to judge for themselves. I personally was mostly annoyed by how some colours are over-emphasised with Solarised, especially magenta and red, to a lesser degree orange.
You could take a fundamentally different approach and use different levels of emphasis for different colours, but I don’t think this was done in a quantitative and purposeful way. It’s also just not the approach I favour as I (and probably others) prefer an overall less busy look more like a text.
And aesthetics in general are of course subjective and were admittedly only of secondary consideration.
> I’m claiming it is an improvement in terms of usability, simply because Solarised wasn’t designed with these properties in mind.
Are you sure about that? On [1] and [2] the creator of Solarized describes why he choose low contrast and specific hue differences, representable in CIELAB. That sounds rather similar to your first three points in [3].
Even if the approaches have some similarities, it does doesn't denigrate your work. Thanks for continuing this line of work. And I am looking forward to test Penumbra in comparison to Solarized.
[1]: https://ethanschoonover.com/solarized/#features
[2]: https://ethanschoonover.com/solarized/
[3]: https://github.com/nealmckee/penumbra#Features
For the colours, this means uniform chroma and hues that aren’t hand-picked but optimised (on top of that using a more hue-accurate colour space).
I’d argue there’s enough of a difference, especially in the visual result, to make this more than an iteration, but even if it was simple iterative, there’s nothing bad about that and it can still be valuable work without being plagiarism .
https://github.com/nealmckee/penumbra#acknowledgments
Which reminds me, of https://github.com/jan-warchol/selenized/blob/master/whats-w... Selenized is another theme which aims to improve on Solarized.
https://github.com/jan-warchol/selenized/blob/master/feature...
https://github.com/jan-warchol/selenized/blob/master/balanci...
Wonder how they compare.
It definitely improves on some of the same issues I had with Solarized, but in a non-rigorous way, with more of a “good enough” approach.
Also, the light theme only has a “barely enough contrast” version due to constraints described in the README, the dark theme has options with much more.
(compare it to the greys used in the samples and you’ll see what I mean)
If not, I’m very open to pull requests on the theme, including fundamental reworks. Otherwise there might be an argument whether one would want to make the closest de-emphasised colour less so, but that would require more fundamental changes to the palette (which I’m also open to for the background colours!). I think for this part I looked at what others were doing so I might have gotten it wrong from them.
Nice idea, but I'm afraid that for coding I'm going to be sticking with Solarized light for the moment.
Do you have the same issues with the Dark Contrast++ version?
When trying to encode highlighting with only chroma and hue and still be accessible, one would probably have to limit the palette to two hues which obviously isn’t practical. This means it would be necessary to use luminance, which expressly goes against the design goals and would eliminate the advantages I’m trying to achieve for people with normal vision.
But you're right, I should have been more clear in the docu, this palette is actually particularly unsuitable. (update: clarified it now)
I honestly haven’t put much thought into “marketing” the theme yet and I would want to properly think about how to best do the highlighting before showing it off in real code. Ideally the latter also with the help of more seasoned programmers.
I appreciate the feedback and will try to keep it in mind once I get to that stage!
Such colors spaces are great for color difference measurement, though.
Of course this means that “yellow” no longer looks like the (much brighter) yellow that we’re intuitively used to, but that yellow would also jump out from the page much more than the main text colour or other “naturally” darker colours.
And I still tried to position them as close as possible to intuitively named colours though with all the other constraints there wasn’t much room for that.
Whether you think this even luminance is something desirable is up to your personal preference, but in my opinion it makes the code more readable as your eye isn’t drawn to things as much when you’re not actively scanning for them.
Part of being able to skim code is to pick out the key words or symbols that denote control flow, important (exceptional, even) cases, etc. The dizzying array of identifiers is less important when trying to skim and pick apart the general "feel" of code quickly.
In this pallette, at least with python, the identifiers are red, everything is "flat" (due to the perceptual brightness) and thus nothing really sticks out or gives me "grit" to hold on to when navigating around.
I could be wrong. This is just my hypothesis going in.
Cool project nonetheless, I love the idea to use color science as the basis for this.
I suspect a useful tool would be one that starts with vision science based uniformities but that then enables personalised tweaks, ideally with vision science guidance.
To your point, it matters what kind of tokens a colour is going to be used for. If they’re small (eg operators), then the effective perceptual uniformity is broken. They’ll be less conspicuous. Being brighter and more saturated would probably help. Perceptual salience can be tricky, and it’s useful to remember that our colour vision is flawed and finicky. Similarly but inverted for large tokens such as class names.
Beyond that, once you start modulating saturation and brightness to get a nicer look, you’re back into a 3D colour space where the evenly spaced hues idea starts to make less sense, or so I suspect.
Nonetheless, cool work! I would have liked to do the same if I was able!
This is defined by luminance. This is the 'L' in Lab and OKLab (and in their polar representation: LCH and OKLCH).
Given the way that themes are currently implemented, I thought making this simplification was reasonable.
If you’re not dead set on the hard constraints I was aiming for, the tool linked below looks great for your purpose though, except it should really be using OKlab instead of CIELab.
If someone disagrees with that assumption, the palette will not work for them.
Some existing examples are "warning squiggles" added by IDE integrated linters, as well as language-level syntactic markers for "here be dragons" parts like Rust’s `unsafe {}` that can be highlighted by standard syntax highlighters (as an aside, it occurs to me that for simplicity’s sake most syntax coloring is in fact merely lexical coloring, but I digress…)
It seems to me that many color schemes these days choose to render comments in grayed-out, low-contrast colors. I find this to defeat the purpose of comments and maintain the unfortunate notion that they are something nearly redundant. A properly written comment tells me something nonobvious and should be displayed prominently rather than faded into obscurity!
In this area, as a novice coder, I am absolutely out of my depth though, so I’d have to defer to actual experts for the implementation.
Someone else brought up a similar point on comment emphasis but I’ve seen the opposing opinion too.
With the situations you describe, you can write tree-sitter queries to make unsafe code highlighted in a different color, for instance, or highlight specific anti-patterns.
[0] https://tree-sitter.github.io/tree-sitter
[1] https://github.com/siraben/tree-sitter-formula
Control flow & operators etc are dark red, identifiers more or less neutral, and top level functions accented. This makes it easy to scan quickly, because you want to be able to navigate a file quickly without getting bogged down in a rainbow of color and then slow down down to understand the tricky bits.
Just reading the comments provided a lot of insight on things like accent color usage.
Im very used to warm colors now so Gotham is the closet spiritual thing in VSCode to this.
[1] https://github.com/sjl/badwolf/ https://raw.github.com/sjl/badwolf/master/colors/badwolf.vim
So I find the trend for color schemes with many lexical types colored differently, unpleasant to the eye and usually of little practical advantage.
The more different things we try to distinguish in a color theme, the harder it is to produce a comfortable aesthetic and the harder it is to make things which should advance or retreat from the eye, to do so.
Keywords can take pleasant color slots which are not the most easily read, because their color confirms they are typed correctly. There is little advantage and much overhead in theming keywords of different types differently. Strings types can all share a hue similarity with small difference to help notice single or double quotes etc. Escaped chars are good to stand out a bit, within the appropriate quotation hue. Comments should be in color range which retreats from the eye a little and is well separated from the executable hues.
I feel its all window dressing, plain text is just a little harder to scan for things than nicely syntax highlighted. Busy, un-finessed syntax highlighting is more of a quirk to be tolerated than it is a comfort.
If you just like them aesthetically and all they’re meant to do is look good, feel free, though I have to say they weren’t designed with aesthetics in mind at all.
For accessible categorical colour schemes, check out Okabe-Ito, Paul Tol or colour brewer.
I'm using an open source calendar component to visualize my agenda. I have various types of events I'm showing (scheduled work items, events and completed items). I'm having a difficult time deciding on a color scheme.
Upcoming events should be emphasized. Completed work items are useful information ("I finished this") but they should be least noticeable.
I'll play around with both your color scheme and the references you provided just to see if something sticks.
There could be issues with your display calibration (most likely), things like f.lux/night shift and so on that cause these to deviate from the calculated ideal values.
I was messing around with something similar (before I found out about Oklab), that generated a nice pastel colour ring.
(I didn't (at the time) know how to get the colours to a fixed perceptual saturation level, so gave up intending to come back to it.)
(If I were doing it now, I'd use Oklab for normalisation.)[0] - https://bottosson.github.io/posts/oklab/
This tool that others have linked is pretty good if you’re fine with relaxing the constraints (just make sure to change to colour space to LCH OKlab): https://huetone.ardov.me.
Good luck making this work despite having next to no value contrast.
Like I said: good luck making this work, because you sure are breaking a pretty important rule of choosing colors.
I’m glad I achieved my main goal though.
The artist isn't being arrogant. You ignored what they said and talked down to them, and they stood their ground. Now you're acting like they're doing something wrong, and publicly criticizing them.
No, it's not arrogance. It's just that you are arguing without understanding.
I am curious how you think I could have said "dude you are making this so fucking hard on yourself by choosing to have next to no value contrast, here are some ways I regularly have to check that I'm not doing this by mistake, good luck figuring out how to get everything else so amazingly perfect that it overcomes this giant deliberate flaw" without sounding "arrogant".
https://en.wikipedia.org/wiki/HSL_and_HSV
I am doing everything else extra to make up for the lack of contrast in luminance if you read the documentation, but of course that can only do so much.
The reason to choose uniform luminance is also explained, and motivated by classical typography where you aim for a uniform, even appearance of text. I was attempting to achieve this while using the remaining colour space to still allow for the ability to scan for hue/chroma.
There was never any room to make it look “good” or “pretty” and as much as I personally also value beauty in design, I put function first here, even if that makes things look “muddy”.
Plus the folders in the repo are named after what implementation they contain which I hoped was self-explanatory.
In a nutshell, warmer colors for foreground content and cooler for background goes a long way in adding depth. Even when working with the same base hue. The fundamental reason this works is precisely sky/sun interaction, which is fascinating.
I used chroma.js with oklab as color space (importantly: it's perceptual). Working with HSV or RGB directly is very difficult in comparison.
Imho OKLab should be the defacto standard for designing with colour, I’m a big fan. Using the colour space based on the display technology never really made sense in this context as we are designing for humans and the display is merely a constraint.
Agreed. It's a little challenging to make color picking UIs and programmatic interfaces I guess. Before seeing oklab in action, I never knew just how distorted a typical HSV picker is, it doesn't map to our vision at all.
https://i.ibb.co/1GkpLw7/2022-08-05-T04-00-27-UTC.png
Is it at least acceptable with the contrast++ version?
On the other hand, if you can't tell apart the cyan from the magenta, something else is going on.
https://github.com/mcchrish/zenbones.nvim
I've found it to be quite practical because it makes keywords easier to pick out, and it allows search matches and diagnostics to stand out better.
Personally, I could see myself tweaking the palettes to have a bit more saturation and maybe even have a particular hue palette or have the hues centre around a particular value as you do with the "warm" variant or the "Zenburned" (my fav, and similar to my own manual scheme) in the showcase (https://github.com/mcchrish/zenbones.nvim/blob/main/doc/show...).
Interesting to compare to the the parent post as luminance/brightness contrast based perception is generally better than our colour contrast based perception. There's arguably less information, as colours are categorical (not continuous like brightness) and colours multiplex brightness with hue and saturation, but there are probably some pretty objective metrics in which your kind of scheme would tend to be better in readability.
Of course that doesn’t tell the whole story because in the end luminance and chroma are not perceived the same way as we tend to associate luminance with more with distance and light and hue and chroma more with the surface properties of the object. (As you mentioned we also tend to treat luminance as a continuous variable and colour as categorical even though both are continuous.) So if you want to use luminance because of this difference, that is a valid, but fundamentally different approach, but I don’t think it would necessarily be superior outright and I’ve tried to make the argument of why I prefer mine.
However note that it is quite difficult to get Zenbones work with existing colorschemes, I tried creating/tweaking one based on Zenburn, but in the end I had to go back to the original Zenburn because Zenbones just wasn't distinguishing enough for the various treesitter highlighting groups.
But perhaps some of the zenbones concepts could be combined with Penumbra in penumbra itself to have another variant in addition to the contrast++ one.
And as mentioned elsewhere there are scientific ways to produce colormaps that work for people with color vision deficiency too, so it'd be nice if that was addressed.
I’m aware of all the continuous colour maps for visualisations and these are pretty much “solved”, but for discrete, categorical ones, the optimisation is trickier and I’m only aware of “good enough” versions rather than fully optimized ones.
I am not colourblind though, so I can't vouch for how good these are in practice, but at least there is some systematic thought that went into the process instead of ad-hoc rules.
Colormaps have very different constraints due to having to cover a continuous ramp and are therefore also not optimal for categorical palettes. I personally like these the best overall: https://www.fabiocrameri.ch/colourmaps/ but there are many good options at this point.
I’m not a fan of this almost fully monochrome theme though, by limiting yourself to differences mostly along one axis, you quickly run into to issues where adjacent values are hard to distinguish. I would argue that since we are trying to encode categories, it’s a mistake to completely forego chroma and hue.
https://github.com/romainl/vim-rnb
> RNB is a template designed to help vimmers create their own colorschemes without much effort.
Thanks!
[1]: https://protesilaos.com/codelog/2021-02-25-modus-themes-diff...
Just have to find something that looks good, or that almost does and tweak it slightly.
But red/green in slide decks to draw distinctions/emphasise things should be banned. Except perhaps absolute #f00/#0f0, which nobody uses because they're not pastelly and subtle (and identical-looking to a chunk of the room) enough.
What's a little frustrating sometimes is that deuteranomaly affects around 8% of men, but is quite often ignored simply ignored. Using red-blue instead of red-green by default would make a lot of problems disappear.
There is an issue on the main repo where I answer a similar question but to my knowledge there is no truly optimised categorical palette for colour blindness (only uniform colour maps) and that’s actually something I’m also doing work on.
It would be nice if this used the upcoming WCAG3 contrast algorithm https://www.myndex.com/APCA/ and ensured it's minimum contrast meets the recommended values there for body text, etc.
There is a tool that can assist in designing color maps taking APCA into account https://huetone.ardov.me/
For perceptually uniform colormaps see also https://colorcet.com/
Meeting the minimum values for body text in this new standard is unfortunately straight up impossible if you want to maintain uniform chroma for the syntax colouring as the contrast requirements are simply too strict and the sRGB colour space too small. I’ll try to read through all the justifications at some point and aim to meet their goals as best as possible once I understand them.
Luckily the high contrast version is already very close to meeting the standard for fluent text and also has maximum chroma so at least there’s already a version that’s at least usable under these guidelines.
The tool you linked is great and honestly if it would be updated to use OKLab instead of CIELab and allowed for additional constraints, would make my efforts obsolete. As it is, they are using maximum chroma per hue and non-uniform hue differences (plus CIELab has hue prediction errors in the first place).
I don't think your efforts are obsolete though, the 2 approaches could be combined IIUC your approach is based on computing values based on color science, and the tool/website is a more visual approach, it won't design the colorscheme for you, but you can use it to validate the colorscheme, or tweak it after the fact.
Switching to OKLab actually reveals how narrow the bands of available colours can be in the different dimensions and how difficult it would probably be to hand-pick the colours that I’ve chosen. I agree now that they’re probably more complementary.
It would be awesome if the tool allowed you to set constraints like the ones I used.
If it seems useful to you try reaching out to them on a GitHub issue and see whether they'd be willing to implement the missing features or collaborate with you in another way.
The original intent was really just to use it myself, but if at least a couple other people may benefit, I feel like putting in the effort to make it shareable is worth it.
However, please increase the contrast of comments! They are borderline illegible, when they're generally more important than the code itself.
Edit: I tweaked my config to make comments green - as someone who writes a lot of Python, this makes sense to me, since python multi-line strings are also used as comments.
Me too, on VSCode. looks nice, let's have a try.
https://www.benkuhn.net/syntax/ https://jameshfisher.com/2014/05/11/your-syntax-highlighter-...
https://bottosson.github.io/posts/oklab/
"Great"
Making the public accusation of plagiarism is a serious thing to do
If it’s not the actual design goals that work for you, it might also just be the fact that even the enhanced contrast versions are overall relatively low contrast compared to many other themes. Often times “just enough” can be more pleasing than maximum contrast.