Posts in Frontend (20 found)
Unsung 3 days ago

“It took months to find appliances that didn’t need apps to function.”

The Ringer journalist Brian Phillips asked on Bluesky : I’m working on a column about the tech annoyances that drive us crazy, and I want it to be as universal as possible, so tell me yours! E.g. scanning a QR code to read a menu, never receiving the one-time passcode they supposedly texted you, “verify you’re human” by IDing tiny motorcycles, etc. There are already many responses. I am drafting behind Phillips before he even writes his essay, because I like occasionally checking in with people this way. Not just for commiserating; perhaps scanning the answers will also give you some inspiration, or validation, or quotes for something you can push to make better, wherever you are. Some patterns I noticed: The way super sketchy bootleg websites used to look (written in questionable English, 2/3 of the window overtaken by ads, constant popups and redirects, incorrect information more often than not) is just how all websites are now. Also, this little beauty : My toaster says to unplug when not in use. It also has a digital clock that resets when I unplug it. #enshittification #software evolution A lot of logging in woes: password requirements, bouncing people from apps to web to log in, login flows forgetting context, “I trusted this device” settings you cannot trust. “Local news websites that crash under the weight of all their pop-up ads and auto-play videos.” This post had a great take: Hatred of QR codes, or perhaps what they represent: needing to install an app, removing people out of the equation, introducing phones where they weren’t needed before. Surprisingly little AI. Is that because of the audience or the way the question was phrased?

0 views
Josh Comeau 5 days ago

CSS vs. JavaScript

There are a bunch of JavaScript animation libraries out there, and you might have wondered whether there’s a performance cost compared to traditional CSS transitions and keyframe animations. In this blog post, we’ll compare the same animation across several different strategies and see the differences firsthand. There’s some interesting nuance here!

0 views
Blargh 5 days ago

RustRadio UI improved

This is just a short followup to the last RustRadio post. If you came for more rants about C , you’ll be disappointed. I’ve never been that interested in writing UI code, including HTML. You can see the “programmer art” in the screenshots linked from www.habets.pp.se . And then the slightly different tech section , that doesn’t serve much of a purpose now that we have github. I’ve not been happier with GTK, QT, and the others either. But [RustRadio][rustradio] needs a UI. I feel like the browser is the most stable and portable UI. So I’d already decided on that. So now I have to manually do a bunch of DOM manipulation, to create an interactive UI? Or worse, learn the React/Angular/Whatever flavor of the day, that will be obsolete by next afternoon? Gag me with a spoon. For now I’m just continuing to focus on the SDR and architectural parts of RustRadio, and I’m letting the LLM-written code do the HTML manipulation. Yeah, it’s kinda vibe coding. But doesn’t use , and it demonstrably outputs what I want. (I mean, sure it may require some follow-up prompts), so who cares? The vibe coding is isolated to the files doing the drawing. If I want to artisanally craft better code in the future, that’s the file that needs to be rewritten. Until then, it works. <iframe width=”560” height=”315” src=”https://www.youtube.com/embed/7k0JNT6itaI frameborder=”0” allowfullscreen></iframe> See the quick start instructions in the ruwasm repo for how to run this UI live with an RTL-SDR.

0 views
Kelly Sutton 1 weeks ago

Moving on from React, 2 Years Later

It’s been an even busier year and change for Scholarly . We’re coming up on 3 years in business. We’ve raised a small round of funding from our existing investors, grown the team in both Denver and Seattle, and continue growing in all dimensions. I’m trying to do an annual review of a decision to move away from React in ~2023 to see how things are turning out. You can read the original posts, Moving on from React and Moving on from React, a Year Later . What a wild 18 months it’s been. Since the last post, we’ve moved from tab-completion and copy-paste LLM-aided development to full-on agents with things like Claude Code. We’ve also grown the team and we have reintroduced React (gasp!). The decision to reintroduce React was solely driven by React Flow . It’s the best diagram tool we found, and we thought it was worth eating our hat. Unlike some of the other libraries we use and pay for, it’s not currently packaged as Vanilla JavaScript. We’ve also deployed React in a select few areas where its state management yields the best customer experience. We ship this as small pieces of a page that is otherwise server-rendered. The React bits help us add the interactivity that we believe makes the best customer experience. For those keeping tabs, here’s how our Ruby/JS LOC has changed over time: A few reflections on the numbers above: Given the recent changes in software engineering, it’s hard to tell how much of this even matters anymore. Our roles as software engineers are changing with every model or harness upgrade. Agents and models have gotten a lot better at interpreting and using StimulusJS and Turbo . We use Claude Code with Opus 4.7 at the time of writing. Some of the rough edges of using Turbo with LLMs in the beginning feel completely gone now. Kept this one short to provide an update. Things are changing quickly, and it’s kind of interesting to think how much of this may or may not matter in the long run. If the LLM is writing our code and the customers have a great experience, how much does stack choice matter? Maybe we should index toward more complex technologies for humans but easier for LLMs to write? How much control should we cede? Thanks for reading. Until next time. Our codebase has 179k LOC of Ruby, compared to 61k from 18 months ago. A tripling! This can be somewhat attributed to our adoption of Sorbet for static type-checking. It just produces more verbose Ruby and provides some more safety that certain parts of our code base benefit from. Our JS LOC went from 4.1k to 14.8k in the same time frame. We’ve also adopted TypeScript here for some of our files that touch React. I’ve kept the linear trendline to simulate where we might have been with React. We’re still below where I’d predict we’d be had we stuck with it. You can clearly see where we made the cutover from React to Stimulus in August 2023, although it’s not as obvious since it’s so far in the past. Our Ruby LOC was growing super linearly last time, and that continues to be the case. I attribute this solely to Claude Code. It really whips the llama’s ass. Volume of LOC remains a liability, but the product capability has grown about this much or more in the meantime, so not concerning.

0 views
Unsung 1 weeks ago

Chrome’s abnormal tab search

Chrome’s find option, like every search coming from a good home, does something clever with accented characters – it normalizes them: = 2x) and (width >= 700px)" srcset="https://unsung.aresluna.org/_media/chromes-abnormal-tab-search/1.2096w.avif" type="image/avif"> = 3x) or (width >= 700px)" srcset="https://unsung.aresluna.org/_media/chromes-abnormal-tab-search/1.1600w.avif" type="image/avif"> = 2x) and (width >= 700px)" srcset="https://unsung.aresluna.org/_media/chromes-abnormal-tab-search/2.2096w.avif" type="image/avif"> = 3x) or (width >= 700px)" srcset="https://unsung.aresluna.org/_media/chromes-abnormal-tab-search/2.1600w.avif" type="image/avif"> No matter whether you search with a proper accented character, or with its basic Latin equivalent, all the same stuff matches: The “ø” letter is treated the same as “o” both in the input field, and then in the search itself. Yet, Chrome’s tab search inexplicably doesn’t do that, which confused me when working on a post about diacritics earlier this week. Here, it should match all four open tabs: = 2x) and (width >= 700px)" srcset="https://unsung.aresluna.org/_media/chromes-abnormal-tab-search/3.2096w.avif" type="image/avif"> = 3x) or (width >= 700px)" srcset="https://unsung.aresluna.org/_media/chromes-abnormal-tab-search/3.1600w.avif" type="image/avif"> Tab search was introduced years ago; the Occam’s Razor says this isn’t a recent bug, but that the feature has always behaved like this. I filed the bug , but even if it gets fixed quickly, I think this doesn’t reflect well on Chrome’s team. If the right code already exists for ⌘F, why not reuse it? If it cannot be reused, why not repurpose at least its unit tests or the QA process to make sure this doesn’t fall through the cracks? Normalization should be treated as a core property of any search, rather than an optional “nice to have.” But, Marcin, didn’t you just invalidate your assertion that diacritics actually matter ? After all, wouldn’t you input “nestlé” instead of “nestle” if they did? To this, I have a few answers: Why does it matter specifically for the ⌘F and the tab search experience? I have this personal theory: the simplest the search, the more the users will blame themselves if it doesn’t work, and assume the tab or the string just isn’t there, rather than rewrite their query. That’s what happened to me. I assumed that the tab wasn’t open and tried to get to it again, wasting time and effort. The rule might be universally true for any UI surface – the tighter it gets, the less likely we assume it can break. After all, there is a manual for a typewriter, but there isn’t one for the pencil! And these UIs do feel positively basic; they are small windows with basically one input field and an immediate as-you-type reaction. #definitions #keyboard #localization Input is not output. This is no different than autocorrect, autocomplete, or other IME helpers. The very fact that on many keyboards accented characters are hard to input is itself a sign of anglo-centrism of companies that made early typewriters (Remington, which established a lot of European layouts like QWERTZ and AZERTY, employed a person who bragged he didn’t actually speak any languages in a “how hard could it be” way) and then most microcomputers. There is this really interesting rule, also known as Postel’s Law : “be conservative in what you output, but liberal in what you accept as input.” It’s not universally applicable – sometimes it’s better to teach the user to be more explicit if it benefits them in the longer run – but it feels appropriate to me here.

0 views
Julia Evans 2 weeks ago

Moving away from Tailwind, and learning to structure my CSS

Hello! 8 years ago, I wrote excitedly about discovering Tailwind . At that time I really had no idea how to structure my CSS code and given the choice between a pile of complete chaos and Tailwind, I was really happy to choose Tailwind. It helped me make a lot of tiny sites! I spent the last week or so migrating a couple of sites away from Tailwind and towards more semantic HTML + vanilla CSS, and it was SO fun and SO interesting, so here are some things I learned! As usual I’m not a full-time frontend developer and so all of my CSS learning has happened in fits and starts over many years. When I started thinking about structuring CSS, I was intimidated at first: I’m not very good at structuring my CSS! But then I started reading blog posts talking about how to structure CSS (like A whole cascade of layers or How I write CSS in 2024 ) and I realized a couple of things: For example, Tailwind has: I’m going to talk about a few aspects of my CSS codebase and my thoughts so far what kind of rules I want to impose on the codebase for each one. Some of them are copied from Tailwind and some aren’t. I just copied Tailwind’s “ preflight styles ” by going into and copying the first 200 lines or so. I noticed that I’ve developed a relationship with Tailwind’s CSS reset over time, for example Tailwind sets on every element (which means that an element’s width includes its padding): I think it would be a real adjustment for me to switch to writing CSS without these, and I’m sure there are lots of other things in the Tailwind reset (like ) that I’m subconsciously used to and don’t even realize are there. This next part is the bulk of the CSS! The idea here is to organize CSS by “components”, in a way that’s spiritually related to Vue or React components. (though there might not actually be any Javascript at all in the site) Basically the idea is that: So editing the CSS for one component won’t mysteriously break something in another component. And probably like 80% of the CSS that I would actually want to change is in various component files, so if I’m editing a 100-line component, I just have to think about those 100 lines. It’s way easier for me to think about. For example, this HTML might be the “component”. And the CSS looks something like this, using nested selectors: I haven’t done anything programmatic (like web components or @scope ) that ensures that components won’t interfere with each other, but just having a convention and trying my best already feels like a big improvement. Next: conventions to maintain some consistency across the site and keep these components in line with each other! has a bunch of variables like this which I can use as necessary. Colour is really hard and I didn’t want to revisit my use of colour in this refactor, so I left this alone. The only guideline I’m trying to enforce here is that all colours used in the site are listed in this file. One thing I appreciated about Tailwind was that if I wanted to set a font size, I could just think “hm, I want the text to be big”, write , and be done with it! And maybe if it’s not big enough I’d use or instead. No trying to remember whether I’m using or or . So I defined a bunch of variables, taken from Tailwind, like this: Then if I want to set a font size, I can do it like this. It’s a little more verbose than Tailwind but I’m happy with it for now. There are some things like buttons that appear in many different components. I’m calling these “utilities”. I copied some utility classes from Tailwind (like for things that should only appear for screenreader users). This section is pretty small and I try to be careful about making changes here. “base” styles are styles that apply across the whole site that I chose myself. I have to keep this section really small because I’m not confident enough to enforce a lot of styles across the whole site. These are the only two I feel okay about right now, and I might change the one: I think for the base styles it’s going to be easiest for me to work kind of bottom up – first start with almost nothing in the base styles, and then move some styles from the components into base styles as I identify common things I want. I haven’t completely worked out an approach to managing padding and margins yet. I’m definitely trying to be more principled than how I was doing it in Tailwind though, where I would just haphazardly put padding and margins everywhere until it looked the way I wanted. Right now I’m working towards making the outer layout components in charge of spacing as much as possible. For example if I have a with a bunch of children that I want to have space between them, I might use this to space the children evenly: Some inspiration blog posts: The way I was doing responsive design in Tailwind was to use a lot of media queries. Tailwind has this syntax that means “apply the style at sizes or larger”. I’m trying something pretty different now, which is to make more flexible CSS grid layouts that don’t need as many breakpoints. This is hard but it’s really interesting to learn about what’s possible with grid, and it’s a good example of something that I don’t think is possible with Tailwind. For example, I’ve been learning about how to use to automatically use 2 columns on a big screen and 1 column on a small screen like this: I also used a lot which is an amazing feature that I don’t think you can use with Tailwind. Some inspiration: In development, I don’t need a build system: CSS now has both built in import statements, like this: and built in nested selectors, like this: If I want, I can use to bundle the CSS file for production. That looks something like this. Even though I usually avoid using CSS and JS build systems, I don’t mind using esbuild (which I wrote about in 2021 here ) because it’s based on web standards and because it’s a static Go binary. A few people asked why I was migrating away from Tailwind. A few factors that contributed are: While doing this I learned about a lot of CSS features that I didn’t use but am curious about learning about one day: I still feel happy that I started using Tailwind, even if I’m moving away from it now. I learned a lot from using it and I can still use some parts from it in my sites even after deleting . Thanks to Melody Starling who originally designed and wrote the CSS for wizardzines.com , everything cool and fun about the site is thanks to Melody. Also I read so many incredible blog posts about CSS while working on this (from CSS Tricks , Smashing Magazine , and more), I’ve tried to link some of them throughout this post and I really appreciate how much folks in the CSS community share their practices. Every CSS code base has a bunch of different things going on (layouts! fonts! colours! common components!) It’s extremely useful to have systems or guidelines to manage each of those things, otherwise things descend into chaos Tailwind has systems for some of these, and I already know those systems! Maybe I can imitate the systems I like! a reset stylesheet a colour palette a font scale utility classes responsive design the build system Each “component” has a unique class The CSS for one component never overrides the CSS for any other component Each component has its own CSS file the owl selector “no outer margin” A responsive grid layout with no media queries from CSS Tricks Tailwind has become much more reliant on a build system since 2018, I think it’s impossible (?) to use newer versions of Tailwind without using a build system. So I’ve been using Tailwind v2 for years. (there’s also litewind apparently) It’s always been true that you’re supposed to use Tailwind with a build system, but I’ve never really done that, so I have 2.8MB files in a lot of my projects and it feels a little silly. I’m a lot better at CSS than I was when I started using Tailwind Ultimately Tailwind is limiting: if you want to do Weird Stuff in your CSS, it’s not always possible with Tailwind. Those limits can be extremely useful (a lot of this post is about me reimplementing some of Tailwind’s limits!) but at this point I’d like to be able to pick and choose. I ended up with sites that mixed both vanilla CSS and Tailwind in the same project and that was not fun to maintain I got curious about what writing more semantic HTML would feel like. (from A Whole Cascade of Layers ) container queries

0 views
Unsung 2 weeks ago

Mailbag: Photoshop’s focus post

The post about some of Photoshop’s new dialogs traveled through some of internet’s pipes and alleyways. Michael Tsai has a nice roundup of reactions ; let me pick a few things that caught my attention. 1. Nick Heer at Pixel Envy made a discovery that Photoshop’s new windows are… websites : Maybe it really is possible to build a web app that feels platform native. But I have never used one — not once — and for this mess to be increasingly used in the industry-standard professional suite of creative tools is maddening. I think it is possible – especially in the realm of classic form fields – but you really have to care and step up and test and replicate a some stuff that the operating system controls give you for free. (As an example, if the web platform/​Electron don’t give you access to the “keyboard navigation” OS accessibility setting, you’ll need to build a bridge from the OS to pass it through. This is how Figma’s Electron app got haptics, for example.) It is true that we don’t see that level of effort often. But there are also bad native interfaces, and there might be more; Roger Wong recently made an interesting observation that stuck with me. Emphasis mine: The mechanism differs but the outcome is the same: the platform stops being a place a designer can rely on. […] [Text user interfaces] are back because the platforms quit , and the curriculum can’t fix that. I think I agree with this; I’ve felt there haven’t been a lot of improvements in native desktop interfaces recently. In the mid-1990s, Apple was losing to Windows 95/98, and after years of falling by the wayside, the team eventually got their priorities in order, and rebooted classic Mac OS into a (I believe generally successful) Aqua. And in later years, Apple as a whole has often been good about creating extra distance from the peloton even if there was no immediate danger of being overtaken. But not here. Windows lost its way, and perhaps even the memories of the darkness of the 1990s and the revival of the 2000s are now forgotten. Even if Liquid Glass was executed extremely well, macOS would still feel bereft of true evolution and care. I know there have been some slight improvements to window tiling and more recently Spotlight, but little of this betrays urgency or suggests a vision. Finder feels like it’s been abandoned for over a decade. AirDrop UI is worse in use than many of the file sharing interfaces that came before it. This common UI is stuck in the state of the art of display colour science that is out of the previous century : = 2x) and (width >= 700px)" srcset="https://unsung.aresluna.org/_media/mailbag-photoshops-focus-post/1.2096w.avif" type="image/avif"> = 3x) or (width >= 700px)" srcset="https://unsung.aresluna.org/_media/mailbag-photoshops-focus-post/1.1600w.avif" type="image/avif"> Just on the topic that is fresh on my mind : Why does Shortcuts feel like a toy in all the moments it shouldn’t, but few of the moments it should? Why does the keyboard customization situation feels so messy? Or, why are both macOS and iPadOS still stuck in the ancient way of thinking that menu bars contain all the app’s commands, when the modern approach is: it’s command bars that do, with menus containing only a subset? An innovative modern operating system would offer a universal API for command bars that any app that wants one could use – instead, apps invent their own with varying levels of success and UI quality, and automation tools cannot do much since nothing’s compatible. (This in particular is an example of an area where web apps started leading the way.) These are just some examples that come to mind. It’s true I have admired and been inspired by some work done on Apple TV and the Vision Pro, but we also have to acknowledge that designing for net-new platforms is in many ways easier than for legacy ones. 2. Back to Photoshop. In the Hacker News thread , at least one person from Adobe dropped in to comment, and one paragraph caught my attention: These changes were part of the Beta program. As far as I am aware the response there was not on the same level as this blog post. It’s not my intention to pick on this Adobe employee, and I am not aware of the specific of their beta program (although I have used Photoshop in beta for a few years). But from my experience, this is why beta testing fails in this regard: 3. Oh, and when I say “broken windows,” I’m not just being cute. Here’s an example of Photoshop’s “explore” halo that occasionally appears on top of another app just because I have Photoshop open underneath. And, there is nothing I can do in Photoshop to get rid of it: = 2x) and (width >= 700px)" srcset="https://unsung.aresluna.org/_media/mailbag-photoshops-focus-post/2.2096w.avif" type="image/avif"> = 3x) or (width >= 700px)" srcset="https://unsung.aresluna.org/_media/mailbag-photoshops-focus-post/2.1600w.avif" type="image/avif"> I think there is something fundamentally very broken with Photoshop’s (custom?) window management, seeing how PS windows jump in front of other applications, or how PS breaks other apps’s mouse pointers. But that’s a story for a different post. #adobe #apple #bugs #interface design #nick heer #process People in beta programs might be more lenient and excited to experiment. For obviously broken small UI things, people will be more inclined to think “oh, they will surely take care of that in the polish phase.” In general, reports of smaller UI things are less likely than bigger functional bugs like “this is not working” or “this is really slow now.” You really have to encourage and reward and incentivize people to do that, and usually identify the right people first, too. Please excuse my directness, but Photoshop’s user interface has felt low-quality for at least a decade now. There are a lot more examples. It’s hard to expect people in the beta to flag small UI stuff – including literal broken windows – when the evidence all around them is that the company doesn’t care. Just because we all encounter interfaces doesn’t mean everyone knows how to identify the things and say the words and connect the dots, especially when it comes to generally undefinable and unmeasurable craft. Good UI is deep expertise . Just like you cannot research or data science your way out of fundamentally bad product decision-making process, you also cannot add craft through relying on your users to tell you. You need to foster this on the inside.

1 views
Unsung 2 weeks ago

Rug pulled

The best thing the crypto industry coined might have been the expression “rug pull,” but I’m not happy about that. To me, it perfectly describes how it feels when an app or a website randomly changes your scroll position for no rhyme or reason. You’ve seen it so many times before: To me, the scroll position is as sacred as the mouse pointer position , given the two are related whether Scroll Lock is around or not: one is you, the other is the world around you. But there are moments when software scrolling with the user or even for the user is appropriate, and here’s one example: When you switch tabs, the content below should always scroll to the top, but it doesn’t here. Here’s an even worse example, also from Settings: Why should the content scroll to the top here? Because in these situations, the fact that the content container gets reused is just a technical quirk of the implementation. From the user’s perspective, this is all new content, and new content should always start at the top. Otherwise, things will get confusing really fast; imagine it especially in the default configuration without scrollbars , where you might assume result number 6 is the first result, or completely miss the most important, topmost options. (Before you ask: Yes, I also see this in Tahoe.) #interface design #mouse you start reading a webpage, but it throws you back to the top when JavaScript finishes loading you start reading a webpage, and ads or other stuff appear and shove you around up and down you press a back button and that goes to the previous page… but to its top, rather than where you actually were you zoom in or out, the position isn’t recalculated properly, and suddenly you see a different part of the page and lose your orientation

0 views
Jim Nielsen 2 weeks ago

Out With the JS, In With the HTML

I’ve been posting about how you can make lots of HTML pages and leverage navigations over in-page, JS-dependent interactions . Now I’m gonna post another example. On my icon sites, I have a little widget that allows you to resize the icons you’re looking at. Previously, I implemented this functionality as a web component that looked something like this: The attribute corresponded to an enumeration like which mapped to actual pixel dimensions like 64×64 or 512×512. When the little widget was clicked to render icons at a different size, JavaScript changed the attribute on the custom element. From there, the web component’s JS took over changing the dimensions of the children elements, their attributes, etc. It all worked pretty well. However, because that was a client-side solution to my otherwise entirely pre-rendered static site, it required some templating logic and data be duplicated and sent over the wire to every client. I didn’t love that for various reasons — like “Crap, I updated this one small part of how my icon list renders on the server, but forgot to tweak it on the client, so things are slightly broken now.” Then one day the thought hit me: instead of relying on JS to make that interaction work (click, execute JS, modify in-page DOM to a new list), what if I just made that interaction a navigation? Click, navigate to a new list. Instead of “every list of icons ships with some JS that allows them to re-render at four different sizes” I could do “every list of icons ships in four different sizes”. So I tried it. And guess what? Once I added some code to support CSS view transitions, I got a cool effect amongst the icons for free — that’s right, by removing code! Works nice on mobile too! I know I’m not doing anything particularly novel here, but as we continue to get new, powerful primitives on the web — like CSS view transitions — I find it really interesting to revisit basic patterns and explore what’s possible now that wasn’t previously. It’s fun to ask yourself: “Could I remove some client-side JS and get a better overall experience?” If the answer is yes, I’ll bet you the development experience (and maintenance burden) is much improved too! Reply via: Email · Mastodon · Bluesky Previously: one page, like , with JS to re-render the icon list based on user interactions. Idea: four pages, like , each a different icon list size.

0 views
Unsung 3 weeks ago

“Traditionally, fonts were just shapes.”

Should you ever be worried that displaying just one glyph could take almost 2 seconds and slow down your website by as much? Naw, of course not. This wasn’t a problem already in the 1980s and, in the lord’s year 2026, computers are pretty good at rendering a letter or a symbol at a moment’s notice. Ha. I was just messing with you. Of course you should always be worried about fonts. All the time. Typography is beautiful, but fonts are brutal. They will constantly put you to the test, they will find ways to get out of alignment faster than a Zastava Yugo , and they will teach you about corner cases in places you didn’t even realize had edges. Fonts will break your heart like it’s the month before the prom again, and again, and again. Or, in Allen Pike’s case, break a heart somewhat literally. Pike wrote a nice quick story of the complexity of what needed to happen to show the heart emoji, and how under a very specific set of conditions – a certain browser, a certain emoji font, a certain emoji within that font – this led to an extreme slowdown. What’s really interesting is that in order to fix it, Apple can either improve Safari or the font itself, and at the moment of writing, it wasn’t clear what was the right thing to do. (Oh, yeah. Fonts don’t just have bugs . Fonts have many kinds of bugs.) Another interesting in-between-the-lines thing is that Apple’s emoji are perhaps the only survivor of the original skeuomorphic pre-iOS 7 era. Even today’s emoji party like 2008 never ended – still glossy, still textured, still bitmapped. I’m curious whether somewhere deep inside Apple, there exist exploratory designs for flat, vector versions of emoji that never saw the light of day. #bugs #skeuomorphism #typography

0 views
Jim Nielsen 3 weeks ago

Reminder: You Can Stitch Together Lots of Little HTML Pages With Navigations For Interactions

I wrote about building websites with LLMs — (L)ots of (L)ittle ht(M)l page(s) — and I think it’s time for a post-mortem on that approach: I’ve tweaked a few things from that original post but the underlying idea is still the same, which I would describe as: Avoid in-page interactions that require JavaScript in favor of multi-page navigations that rely on HTML and are enhanced with CSS view transitions (and a dash of JS if/where prudent). As an example, on my blog I have a “Menu”. It doesn’t “expand” or “slide out” or “pop in” or whatever else you can do with JS. Instead, it navigates to an entirely-new page that is focused on just the menu options of my site. I say “navigates” because it’s just a link — — and it functions like a link, but the navigation interaction is enhanced by CSS view transitions. Have a newer device with a modern browser? Great, you get a nicer effect. Have an older device, or an older browser, or JS disabled, Et al.? It’ll still work. If you can follow a link — which is the most fundamental thing a browser can do — it will work. So how’s it all work under the hood? In essence, all the pages have a link to the menu (except the menu page). When you navigate to the menu, that link is changed to an “X” which “closes” the menu. The closing is still just a link (back to ) but it’s enhanced with JS to actually do a “back” in the browser history. This makes it so “opening/closing” the menu doesn’t add an entry to your browser history. As a simplified example, the code looks like this: The checks whether we came to this page as a navigation (mostly likely from within the blog itself) or via a direct visit (i.e. somebody typed it into the URL bar, unlikely but possible) which is how I suss out whether there’s a meaningful run or not. Here’s a video of how it all works, if that’s your thing: While this solution seems simplistic, it was not a simple thing to arrive at. It required me to spend time thinking about what was essential to navigation, how that interaction could work across multiple pages, and how I could ensure page size stayed small so the interaction was both fast and robust while remaining intuitive to use. In other words, the approach shaped the design. Turns out, if you have a website and you think of the browser as a way to navigate documents — rather than a runtime to execute arbitrary code and fetch, compile, and present them — things can be a lot simpler than our tools often prime us to make them. Reply via: Email · Mastodon · Bluesky

0 views
Rafael Camargo 4 weeks ago

Alternative solution for small React apps that need i18n

In most projects I've worked on, the default pick for internationalization has always been react-i18next. It works, and it covers a lot of ground. But when I kicked off a tiny personal project called Veedgee, I started wondering: do I really need all of that? It was a simple app. Not much copy, only two languages, and still I'd have to...

0 views
Unsung 1 months ago

Photoshop’s challenges with focus, pt. 2

First of all, correction for part 1 – the “focus mode” wasn’t removed. It was renamed to “quiet mode” and relocated to a different part of the UI, and I failed to spot it there. It’s still slightly perplexing, shiftily capitalized, and I doubt fully effective, but the effort is there: = 2x) and (width >= 700px)" srcset="https://unsung.aresluna.org/_media/photoshops-challenges-with-focus-pt-2/1.2096w.avif" type="image/avif"> = 3x) or (width >= 700px)" srcset="https://unsung.aresluna.org/_media/photoshops-challenges-with-focus-pt-2/1.1600w.avif" type="image/avif"> I also want to warn you there will be no more positive things I say in this post. When Cabel Sasser posted this on Bluesky in February … = 2x) and (width >= 700px)" srcset="https://unsung.aresluna.org/_media/photoshops-challenges-with-focus-pt-2/2.2096w.avif" type="image/avif"> = 3x) or (width >= 700px)" srcset="https://unsung.aresluna.org/_media/photoshops-challenges-with-focus-pt-2/2.1600w.avif" type="image/avif"> …I experienced a little existential dread. Now that I’ve experienced the dialog myself in Photoshop 2026, and a few other dialogs that have been upgraded toward what Adobe calls “modern user interface,” how did it fare? These are 2025 windows and their 2026 equivalents: = 2x) and (width >= 700px)" srcset="https://unsung.aresluna.org/_media/photoshops-challenges-with-focus-pt-2/3.2096w.avif" type="image/avif"> = 3x) or (width >= 700px)" srcset="https://unsung.aresluna.org/_media/photoshops-challenges-with-focus-pt-2/3.1600w.avif" type="image/avif"> = 2x) and (width >= 700px)" srcset="https://unsung.aresluna.org/_media/photoshops-challenges-with-focus-pt-2/4.2096w.avif" type="image/avif"> = 3x) or (width >= 700px)" srcset="https://unsung.aresluna.org/_media/photoshops-challenges-with-focus-pt-2/4.1600w.avif" type="image/avif"> = 2x) and (width >= 700px)" srcset="https://unsung.aresluna.org/_media/photoshops-challenges-with-focus-pt-2/5.2096w.avif" type="image/avif"> = 3x) or (width >= 700px)" srcset="https://unsung.aresluna.org/_media/photoshops-challenges-with-focus-pt-2/5.1600w.avif" type="image/avif"> = 2x) and (width >= 700px)" srcset="https://unsung.aresluna.org/_media/photoshops-challenges-with-focus-pt-2/6.2096w.avif" type="image/avif"> = 3x) or (width >= 700px)" srcset="https://unsung.aresluna.org/_media/photoshops-challenges-with-focus-pt-2/6.1600w.avif" type="image/avif"> On the surface, it feels like a lateral move. I do not personally find the new design language (Spectrum) attractive, or even particularly “modern.” The gestalt remains off and things are still generally misaligned – they’re just misaligned in net new ways. But it was digging into the window below that showed all the problems in the still-wet foundations… = 2x) and (width >= 700px)" srcset="https://unsung.aresluna.org/_media/photoshops-challenges-with-focus-pt-2/7.2096w.avif" type="image/avif"> = 3x) or (width >= 700px)" srcset="https://unsung.aresluna.org/_media/photoshops-challenges-with-focus-pt-2/7.1600w.avif" type="image/avif"> = 2x) and (width >= 700px)" srcset="https://unsung.aresluna.org/_media/photoshops-challenges-with-focus-pt-2/8.2096w.avif" type="image/avif"> = 3x) or (width >= 700px)" srcset="https://unsung.aresluna.org/_media/photoshops-challenges-with-focus-pt-2/8.1600w.avif" type="image/avif"> …and a lot of them have to do with focus. 1. The first field is not focused, so you cannot start typing the number after opening this window. You need to immediately move your hand to the mouse. 2. If you click on any field, the value is not pre-selected, so you cannot start typing a new number then. A combination of both is rough in practice in repeated use, violating some of the basic things like this classic principle of interaction design : Principle: Defaults within fields should be easy to “blow away” When a user activates a field, the current entry should be auto-selected so that pressing Backspace/​Delete or starting to type will eliminate the current entry. Users can click within the field to deselect the whole, dropping the text pointer exactly where the user has clicked. The select-on-entry rule is generally followed today. (Sloppy coding, however, has resulted in the text cursor dropping at various unpredictable locations. ) 3. Clicking on parts of the input field doesn’t bring it into focus even though the hover state promises it. (Discrepancies between hover and focus handling are a horrible new thing I’m starting to see more in recent interfaces.) 4. Simply backspacing through the field shows a crude error modal error and – to add a second injury to the first injury – the dialog removes focus from the field! 5. Tabbing now goes through “Pixels” menu on the way from Width to Height, making it harder to type width → press Tab → type height → press Enter, in a nice quick keyboard gesture. I will recognize this is a tricky one, because it exposes a core tension with tabbing: some people use it for comprehensive keyboard access, but others want an accelerator “express train” with only relevant stops. However, macOS already has a “Keyboard navigation” setting for that – you can choose whether tabbing should go through all the controls, or only those you get to type in. Not only does Photoshop ignore that preference, but it’s inconsistent with itself – you can see that you cannot get to Anchor via tabbing anyway! 6. Clicking on the “relative” checkbox or canvas extension color does not restore focus to last control like it used to. 7–∞. There are tons of other transgressions. Some are downwind from focus; for example, undoing after moving a slider no longer works, because the ⌘Z keystroke is now swallowed by a UI element that doesn’t know what to do with it. Some are unrelated: Pull-downs are now of the slower kind , pressing ⌥P results in more blinking, and this tooltip below feels so cheap that I’m surprised it’s not a talking point of the current U.S. administration: I am tired even just noticing all this. (What is that weird clump of pixels on the left of the bottom edge!? Did no one spot it before launch?) So now what? I generally avoid such harsh labels on this blog, but: this is awful work . I’m angry. (Clearly.) We should all be angry in face of stuff like this. This is how people get fed up with software – because it feels unstable and deteriorates on its own without needing to . I know I brought up that an existing power user base can be a huge pain in the ass, and I am a decades-old Photoshop power user. But this is different than other examples where the product needs or at least wants to evolve past its core audience or toward a different market. For Photoshop here, nothing I see indicates any change in course or clientele – and yet all of these good moments in UI that used to help me out no longer exist. Plus, all those transgressions are solved problems. Those issues are not buried in pages of heavily litigated patents, or in seven collective brains of world-class interface designers whose driveways are presently occupied by cash-filled trucks sent over by frontier companies. This isn’t some long lost art that requires archaeologists to decipher. This feels like carelessness and laziness in face of basic UI engineering; in a likely internally-motivated effort to refresh the interface, the team threw an entire nursery worth of babies with the bathwater. It’s not just about disservice to craft. It’s not even about disrespect for change management, trivialization of institutional memory, and disinvestment in quality assurance. This isn’t only, in Tog’s words above, “sloppy coding.” This is also a failure of imagination . It’s not that hard to picture people spending 8+ hours a day going through these windows for years if not decades to come, and it’s not hard to add and multiply all of these microfrustrations into numbers that should make one pause. With these many paper cuts, you need to start thinking about establishing a blood bank. How can you expect people to use a professional tool effectively if you throw in so many roadblocks? In an internally-motivated UI refresh like this, you not only need to meet users where they used to be, you also ideally have to give them more to cover for the pains of change. Sometimes that “more” is better storytelling – here, no one even tried to really sell me on the new interface – but ideally “more” means actual felt improvements. I’m not on the team, but it’s not that hard to imagine some of them: I started this post talking about a setting, and there is another setting in Photoshop, buried on the last page – you can turn off this “modern user interface” that feels so underbaked the moment you start actually using it. But is that a real solution to anything? Toggle it on and the existential dread comes back: Am I going to miss out on some good stuff? When is the hammer going to drop? It’s not a tax break, it’s only a tax extension. = 2x) and (width >= 700px)" srcset="https://unsung.aresluna.org/_media/photoshops-challenges-with-focus-pt-2/21.2096w.avif" type="image/avif"> = 3x) or (width >= 700px)" srcset="https://unsung.aresluna.org/_media/photoshops-challenges-with-focus-pt-2/21.1600w.avif" type="image/avif"> Even this view above shows so little care, it would ordinarily deserve its own post. #adobe #change management #details #interface design Change those annoying modals that announce typing errors into something lighter and more modern, like attached tooltips. Add more comprehensive equation support so e.g. I could type “660*2” like I can in increasingly more and more apps. Announce the invisible shortcuts that already exist , or add a few ones. Add a bit of memory/​stickiness to some options (like Use Legacy in the first window), so I don’t have to keep toggling them over and over again.

0 views
Unsung 1 months ago

About Unsung: Thanks for your feedback!

(This is one of the meta posts about this very blog . If that’s not interesting to you, skip to the next one!) Thank you for all your feedback and bug reports in response to my call two weeks ago . Since then, I: If you see anything wrong or funny as a result of these changes – or any technical problem otherwise – please let me know (contact info is always in the footer). And, in general, please continue with your thoughts and feedback about content of the stuff I post, too! I’m enjoying hearing from you. #about unsung revamped the image and video pipelines, which should make the blog load a lot faster and CPU/GPU struggle a lot less, improved inline video handling on the web, and in (some) RSS readers, made transparent videos work in Safari, and figured out how to make even better transparent videos, improved Friday newsletters so they have a link to a nice web view, and GIFs hinting at video content (alas, you cannot put videos straight in email), and generally made the site work better on older computers and phones.

0 views
Den Odell 1 months ago

The Design-Minded Engineer

In 2002, I was a few weeks into a new role, my second since completing my degree two years earlier. I was a frontend engineer at AKQA , a creative agency in London. I’d just finished one of my first projects, building out a new page for a client, and I thought it looked great. So I told the designer it was done. A while later, I heard him in the engineering room. Den? Where’s Den? He came over to my desk and opened Photoshop. He placed a screenshot of my build on one layer and his original design on another, dropped the opacity to 50%, and let me see the difference for myself. Everything was off. Spacing, alignment, type rendering, visual weight. Not by miles, but by enough. Enough that the thing I’d built felt different from the thing he’d designed, even though I’d have sworn they were identical. I was embarrassed. I was so sure it was done. Something rewired in my brain that day. Not a new skill, exactly, but a new way of seeing. I had started to become an engineer who could see what I’d built through the eyes of the designer, not just through my own. The gap between what designers intend and what engineers ship is one of the oldest problems in our industry, and it has defined my career since that day. I’ve come to believe it’s the most undervalued skill in software engineering. Brian Lovin, currently at Notion, wrote recently about the difficulty of hiring what he called “design-minded frontend engineers.” The struggle he describes is widely shared. There are engineers who can code, and there are designers who can design, but the engineers who can honor design intent while building the real product? That pool is vanishingly small. Lovin’s framing was about frontend engineers specifically, but the gap he’s describing isn’t a web problem; it’s a general UI problem. Mobile engineers ship apps that drift from their designs. Embedded engineers build interfaces for cars, appliances, ATMs, point-of-sale terminals, and medical devices where a misjudged tap target has real-world consequences. Anywhere a human touches software, someone has to close the space between what was designed and what gets built, and that someone is an engineer regardless of what platform they work on. What’s striking about this gap is how much has been written about it already, and how little has changed. Designers have been naming the problem for years: posts about engineers breaking their designs , articles about the handoff process , and conference talks about the collaboration breakdown . The designer’s perspective on this is a well-established literature. But that literature is written by designers, for designers, and no amount of designers talking to each other about the problem has fixed it, because fixing it was never something designers could do alone. The engineer is the other half of the conversation, and the engineer is the half that has to change. And here’s the thing: this isn’t a new problem that appeared with the rise of design systems or component libraries. It’s been there since the first time a designer handed a mockup to an engineer and got something back that felt almost right but not quite. The gap between the mockup and the shipped product is an engineering problem, and it’s a problem with a solution. The skills required to close it can be taught. The thing to understand about design is that it isn’t the mockup, it’s the experience the person has when they’re using the shipped product. That experience is built by engineers from what designers describe and intend. The mockup is a promise, the feel is what actually ships. One distinction is the Design Engineer . This is someone who occupies a hybrid role: they design and they build. Matthias Ott has written persuasively about design engineering as the structural fix for the design-implementation gap : a role that holds both disciplines at once and makes the gap stop forming in the first place. Companies like Linear and Vercel have made the role famous, and I’m in awe of the people doing it; they are genuinely talented at both sides. But it’s also a luxury solution. Most companies can’t hire for it, and even at companies that do, many design engineers typically focus on design systems or high-fidelity components. Somebody still has to take those components and build the actual product with care. Ott’s prescription is a role; mine is a capability. The role is valuable where companies can hire for it, but the capability is what scales to the rest of us. That somebody is the design-minded engineer . That’s not a new job title; it’s a way of working, of engineering, of caring about how the product looks and feels. A design-minded engineer is not a designer, and their task is not to originate design decisions but to apply and extrapolate them. The goal is for the designer to look at the shipped product and not be able to tell where their design file ended and the engineer’s judgment began. The highest compliment a design-minded engineer can receive is silence from the designer, because silence means you got it right. This isn’t about engineers becoming designers either. Designers should still design, and engineers still build. But the engineer who builds with design judgment ships a different product than the engineer who builds without it. Apply and extrapolate, don’t originate. That’s design-minded engineering. Over the course of my career, from agency work at AKQA for Nike and Ferrari, to global e-commerce at Volvo, to my accessibility and animation work at Canva, I’ve developed a framework for how engineers should engage with design. It comes down to three lenses: 1. User behavior. What will people actually do with this? Not what the mockup assumes, but what happens in real conditions. The designer typically designs for one user in one ideal state, while the engineer knows that localized strings reshape layouts in ways the original mockup didn’t account for, that right-to-left languages flip everything, that users will hit this screen on a train with one bar of signal halfway through a checkout flow. The design-minded engineer sees those realities and addresses them before they become bugs. 2. Performance. What’s the hidden cost the user pays that the mockup can’t show? A prototype can promise buttery smooth interactions, but if the shipped product has 80ms input latency instead of 16ms, users feel the difference even if they can’t articulate it. Samsung famously copied Apple’s pinch-to-zoom gesture, matching the visual design almost exactly, but the interaction felt wrong because the engineering underneath didn’t match the design promise. Performance is a design decision, and engineers are the only ones who can make it real. 3. Accessibility. Who gets excluded? This is the most defensible concern you can raise in any design review, and it’s the one most often deferred. Accessibility isn’t a compliance checkbox but a signal of engineering quality, and more than that, a signal of care. Passing WCAG scores while the actual screen reader experience is incomprehensible doesn’t count. Turning on VoiceOver and navigating your own product with different input types does. These three lenses aren’t reasons to block work or push back on designers; they’re the opposite. They’re how an engineer earns a seat at the design table, by caring about design outcomes through a lens that designers recognize and respect. Design-minded engineering isn’t only analytical, though. There’s a whole dimension that’s about creative contribution. Engineers know things designers don’t, because the two disciplines have different vantage points. When CSS container queries landed, or view transitions went from spec to stable, or SwiftUI’s animation APIs opened up new motion possibilities on iOS, those weren’t just engineering milestones. They were creative unlocks. Each expanded what was possible in a user interface, and engineers saw the new ground first. At AKQA, I worked on a Ferrari project not long after CSS got the function for custom easing curves. We built a dropdown menu with easing curves derived from actual race car telemetry data. It was the kind of contribution that only happens when an engineer is in the room during the creative conversation, feeding into it, not waiting downstream for a handoff. The designer is constrained by what they think is possible, and the design-minded engineer knows what actually is. Stay current with new platform capabilities. You’ll have options to bring to every brainstorm, and the team designs something they couldn’t have designed without you. If there’s a single idea in this framework that I think resonates most immediately with working engineers, it’s gap states . Every mockup shows the happy path. The page loaded, the data arrived, the user is logged in, the content fits perfectly. But shipped products have to account for loading states, error states, empty states, skeleton screens, offline fallbacks, optimistic updates, expired sessions, permission denials, locale-specific edge cases, and a dozen other conditions that never appeared in any design file. These aren’t afterthoughts, they are the product for a significant percentage of real user sessions. The engineer who treats them as first-class design problems, who asks “what does this screen look like with no data?” before leaving the design review, is doing design-minded engineering. The craft applied to these in-between moments is what separates products that feel polished from products that feel like they were built from a mockup and nothing else. Everything I’ve described so far assumes a design exists. But what happens when it doesn’t? This is where design-minded engineering faces its real exam. Every engineer eventually encounters a situation where they need to build something with incomplete or absent design direction: a feature that needs shipping before the designer can get to it, a prototype built from raw data and business requirements, or a long stretch where the team is between designers. I’ve lived both extremes. I’ve been handed raw data and asked to build something that felt intentional with no design input at all. And at Volvo, before a design system existed, I spent six months without my designer, building across 70 markets from data and whatever fragments of earlier design work I could find. The early weeks were the hardest. You don’t realize how much of your confidence comes from having a design to reference until it’s gone. Every decision that would normally take seconds suddenly has weight. What size should this type be? How much padding feels right here? Is this hierarchy clear, or am I just used to looking at it? There’s no mockup to check against, no designer to ask; just you, the data, and whatever design judgment you’ve accumulated over the years. What I leaned on was the three lenses. User behavior first: what will real people in real markets actually do with this? I knew German strings would be 40% longer than English, that some markets read right to left, that a checkout flow designed for English speakers in a desktop browser would encounter completely different friction points when a user in Saudi Arabia was navigating it in Arabic on a phone. I knew the edge cases because I’d been cataloging them for years. Performance second: what’s the cost of every decision on the devices our users actually have? Not the specced-out MacBook Pro I was developing on, but the mid-range Android in Jakarta, or the spotty connection in rural Norway. Accessibility third: who gets excluded if I get this wrong? Those lenses didn’t replace the designer, but they gave me a structure for making principled decisions. Instead of guessing what looked good, I was solving for outcomes I could measure or defend. The visual choices I couldn’t reason about, I kept conservative. I matched existing patterns in the system and extrapolated from what the designer had already established rather than inventing something new. Exercising restraint is the counterintuitive part. When the designer is gone, the temptation is to fill the creative vacuum, to make the bold call, to prove you can do both jobs. But that’s exactly the wrong instinct. The design-minded engineer’s job in that situation is to make the product feel continuous with the designer’s existing intent, not to introduce a new voice. Every time I reached for a decision I wasn’t sure about, I asked myself: if the designer were here, would this surprise them? If the answer was yes, I pulled back and found a more conservative path. Boring is better than wrong when you’re operating without a net. When the designer eventually returned and reviewed what I’d built, he requested only minor tweaks. Not “what were you thinking?” Just the micro-level adjustments that separate a designer’s instinct from an engineer’s principled approach. That outcome is the proof of concept for the entire framework. It’s also an honest illustration of where designer instinct is hardest to replicate: the micro-level decisions about spacing, weight, and proportion that feel obvious only after someone with that instinct points them out. Design-minded engineering can get you remarkably close, but recognizing where “close” falls short is part of the skill. Part of developing design fluency is learning to spot where it went wrong. The industry has no shortage of cautionary tales: Snapchat’s 2018 redesign, the hamburger menu epidemic, dark patterns that optimize for conversion while destroying trust, and recently the rise of AI-generated UI that looks plausible and works incoherently. The hamburger menu is an instructive example, because it felt like such an elegant engineering solution at the time. Screen space is limited on mobile, navigation takes up room, so you collapse it behind an icon. Problem solved. Except the data kept telling the same story: users don’t open menus they can’t see. Features hidden behind hamburger menus saw dramatically lower engagement than features visible in the interface. The space-saving argument won on logic but lost on human behavior, and the design-minded engineer’s contribution in that room wasn’t to have a better opinion about navigation but to notice that the argument for hiding things needed to account for whether users would ever find them again. AI is making it easier than ever to generate UI code, and you can prompt your way to a working interface in minutes. That’s exactly why design judgment matters more today than ever. AI is a powerful tool for design-minded engineers. It can generate locale variants, simulate gap states, produce working prototypes during brainstorms, and catch accessibility issues before the design review. But it can’t evaluate whether the result feels right. It can’t decide whether an animation serves the interaction or just decorates it. It can’t tell you that the loading state your component shows for 200ms on a fast connection will hang for four seconds on a train in rural Portugal. The risk I see emerging is subtler than “AI will replace designers.” It’s that engineers will start treating AI as a substitute for design judgment. Need a loading state? Ask the model to generate one. Need an error message? Let it write the copy. Need to decide how a component should behave on mobile? Prompt for options and pick the one that looks reasonable. Each individual decision might be fine, but the cumulative effect is an interface that has no point of view, no coherence, no sense that a human being thought carefully about what the person using it actually needs. It’s design by default rather than design by intent. The design-minded engineer is the counterweight to that drift. They’re the person who looks at the AI-generated output and applies the three lenses: does this serve real user behavior? What’s the performance cost? Who gets left behind? Those questions require human judgment, not better prompts. The execution can be accelerated; the judgment cannot. I’ve been developing this framework across 25 years in some of the most design-demanding engineering environments in the industry. What I’ve learned is that design fluency isn’t a talent you either have or you don’t. It’s a skill that can be taught, practiced, and developed, and it grows in ways that are hard to see in the moment but obvious in retrospect. The engineer who starts paying attention to spacing in their first year starts noticing type hierarchy in their third. By year five, they’re catching interaction patterns that don’t match the design intent before the designer does. By year ten, they’re the engineer the designer wants in the room when the hard decisions get made. By year fifteen, they’re the Staff engineer who catches a broken loading state in code review and can articulate exactly why it matters, not just that it looks wrong, but what it does to the user’s trust in the product. None of that happens overnight, but it starts with a single decision: to care about what you’re building beyond whether it works. The misalignments I catch now in code review, the edge cases I see before they ship, the interactions I can tell are wrong before anyone else does: none of it would have registered with me in 2002. The AKQA designer with the Photoshop overlay taught me to look. That skill isn’t an innate talent, it’s something any engineer can learn to see for themselves with practice. And the engineers who become design-minded are the ones designers stop having to chase.

0 views
Unsung 1 months ago

“The fancy software figures it out for you.”

I want to tell you about something that might seem oddly specific and perhaps too technical, but a) at the end of it you will have a useful phrase somewhere in your brain that will pay off one day, and b) I swear I will make it worth your while. Have you ever seen this problem? The screenshot on the left is fine. But there is something wrong with the one on the right. In light mode, the shadow is wispy and weird. In dark mode, things are even stranger, and the shadow is almost… a glow? I stumbled upon this problem occasionally for years now – there are a few screenshots on the blog with this weird problem, even – but it was never feeling like a deal breaker. However, I finally sat down to figure it out today. Turns out, there are two kinds of approaches to alpha channel/​transparency. The normal one we all know well is called “straight alpha.” But on the right, we were looking at “premultiplied alpha” – something entirely more complicated, where the background is baked into transparency for… reasons. Premultiplied alpha is conceptually – and often literally – dirtier, but it also has benefits: more flexibility, better filtering, sometimes better performance. As far as I understand, premultiplied alpha exists primarily in the world of video and vfx, but occasionally it rears its unconventionally attractive head in our boring static 2D world of screenshots, too. In my case, I finally figured out this was happening whenever I’ve pasted the screenshot from the clipboard to Photoshop instead of Preview – for some reason, a screenshot then got an alpha channel premultiplied against white background. But I wouldn’t be surprised if it happens to some of you under other conditions, too. So, “premultiplied alpha.” That’s the useful phrase. What was the other thing? This is an absolutely hilarious 7-minute video by Captain Disillusion that talks about various challenges with the alpha channel: Captain Disillusion (or, Alan Melikdjanian) is one of my favourite YouTube educators. His work is mostly debunking fake videos – his most well-known one is about the Cricet bracelet , although my personal fav is one about laminar flow – and they’re just constantly interesting and hilarious at the same time. Disillusion also occasionally does a more straightforward “let’s talk about some technical aspects of video production” episode which he bundles under a “CD/” umbrella. Here’s a handy list of all of them: I am sharing this list because you should watch them all. Most are <10minutes, they are consistently entertaining, and even though none of them are about UX design, there is enough overlap between the two universes that you will come out of it all a lot smarter. Pragmatically, in my case, I searched for [premultiplied alpha] + [Photoshop] and quickly learned of a new-to-me menu option: Layer > Matting > Remove White Matte. It turns premultiplied alpha back to straight alpha, and fixes the screenshot. Non-pragmatically? If you want to really understand premultiplied alpha, the last thing I can do is suggest another great internet educator, Bartosz Ciechanowski, who has a more comprehensive interactive web explainer . There will be math. There will also be sliders. You decide. #graphics #humor #youtube Intro to the whole series Aspect ratio Interlacing (and addendum ) Alpha channel Shutter speed

0 views
David Bushell 1 months ago

Web tools are cool

My website has a new page! The URL pathname is an “official” slash page . I’m only listing web tools I use for now. My default apps change too frequently. The list is an evolution of an old post I was secretly maintaining. 👉 Visit my /uses page! Web tools are web-based tools, obviously. Used in a web browser without a download. Some may be installed as progressive web apps but I prefer a progressive browser tabs . Most tools do one thing and do it well. Some of my links are actually just text information, but “web tools and documentation and specifications” is a mouthful. All the tools I’m collating are related to web development. I’d guess I use Squoosh the most, followed by Can I use or this specificity calculator (there are many, I like that one.) Stu Robson’s ReliCSS is a new addition that looks very useful. I realise now I’m not hosting any web tools myself. Many moons ago I maintained a few NPM packages that did stuff ( grunted , mostly). Web tools are so much better. Less malware, for one. I once hosted a to-do app , but who hasn’t? That reminds me, sub-domains are the secret to hosting side projects. I must stop buying short-lived project domains. Anyway, I should build a web tool . Any ideas? Do you have any favourite web tools I should be aware of? I’m not looking to list everything, just stuff I might personally use. P.S. This is definitely not another bookmarks project I’ll forget about. Thanks for reading! Follow me on Mastodon and Bluesky . Subscribe to my Blog and Notes or Combined feeds.

0 views
Unsung 1 months ago

“Area connected to a given node in a multi-dimensional array with some matching attribute”

Anyone using old computers for graphics remembers the strangeness of “flood fill”: The 1950s and 1960s computers were so sluggish that their consoles with blinking lights were not just for show; the operations were slow enough that you could still follow the lights in real time. This ceased to be true soon afterwards. The microcomputer revolution temporarily reset some computing progress, but by the 1980s and 1990s more and more things were happening too fast for us to keep up. But here (this above is Paint in Windows 1.0, and you can try for yourself in a browser !) was one example where you could still see an algorithm working hard. It was mesmerizing and educational, and it was a rare example where perhaps you didn’t mind the computer taking its sweet time. Even messing up like I did above – maybe especially messing up – ended up fascinating to watch. Wikipedia has examples of a few different flood fill algorithms, which are even more interesting: A few years later, Minesweeper had a very memorable flood fill, too (also available in a web emulator today ): But by now Minesweeper retired from sweeping mines, and today computers are so fast that it’s hard for me to imagine any flood fill being anything else but flash flood… …except this is what I just saw in Pixelmator on my Mac: I don’t know if this is a nod toward a classic flood fill, or just a nice unrelated transition. But I found it genuinely delightful, and it’s fast enough that I would imagine it doesn’t bother pros who need to do it often. Sometimes it’s nice to see a computer working when there’s a good reason; some apps like banking apps even insert artificial, visible delays after crucial operations, just so that the users feel comfortable knowing their important transaction went through. But sometimes it’s nice to see a computer working for no reason at all. #above and beyond #graphics #loading states

0 views
Unsung 1 months ago

“Use links, don’t talk about them.”

The classic – but still important – rule of web design says to avoid labeling links “click here.” It’s one of the oldest web design principles . Tim Berners-Lee wrote about it in 1992 ; if you visit this link right now, it might be the oldest page you will have ever visited. The gist of it is simple: the mechanics of following a link are not important, and should be replaced by something that can make the link stand on its own. This is important for screen readers, but also for basic scannability: a “click here” label has a lousy scent and requires you to take in the surroundings to understand what it really does. The rule is, in effect, a variant of “show, don’t tell.” (In modern days, you can also add another transgression: on touch devices one cannot click, but only tap.) There is a similar rule about button copy design. Button labels, too, should be self-sustainable. Below is a good example (just reading the button lets me understand what I’ll achieve by clicking it), juxtaposed with the bad one (“OK” is so generic you have to read the rest of the window). Earlier this week, I was passing some train cars on my coffee walk, and saw this bit of UI: Why are these okay, and “click here” is not? Here’s why, I think: Yes, the ultimate goal is to move a train car, or empty it, or send it on its way. But here, the mechanics matter, too. They’re dangerous. They require preparations. No one says “I’m going to open my laptop and start clicking on links,” but I imagine people say “we have to jack this car” or “we need to lift it.” Even “here” has depth: these are specific tool mounting points. Choosing the wrong “here” will have consequences. But, going back to the web, avoiding “click here” in strings isn’t always easy. Imagine trying to put a link in the sentence “To change your avatar, visit the profile page.” I’m personally never sure how to linkify it well: To change your avatar , visit the profile page. To change your avatar, visit the profile page . To change your avatar, visit the profile page. Linking “change your avatar” seems correct since it points to the eventual outcome, but then it leaves the actual destination dangling and unlinked – like putting an accent on a wrong syllable. “Visit the profile page” is better than “click here,” but it’s still not scannable. Linking the entire sentence seems strange and complicated to me, and I also disagree with Tim Berners-Lee, who on the page I liked to above seems to suggest this should be… To change your avatar , visit the profile page . …just because this might make a user think there are two separate destinations and actions, and contribute a wrong mental model. You could, of course, simplify this to “Change your avatar,” but while that would work in a UI string, it wouldn’t within a larger paragraph of text, or a blog post. #details #flow #popular #web

0 views