RSSAmplifier

Blog

H.W. Sanden

8yd.noRSS feed ↗54 posts

Latest posts

Poisoning well with Craft CMS

I have done what I can to prevent increased traffic from creepy crawly scraping bots, but it seems mostly useless unless I make things more complicated for humans. When I tried to find answers on how to block headless user agents, all I got were ways to circumvent those blocks. If that’s where we’re at, being annoying is the next step. But I don’t have high hopes that LLMs will be well poisoned. I…

Anti-intellectual tech

When thinking becomes a product, forcing people what to think is the endgame. Tech is no longer a science; it’s about selling faith-based software. An anti-intellectual environment pointing to the future with promises of productivity and gold, anywhere from in the next year to after we die. Its true measure of success lies not in what people can do with the products, but how the products can shape…

Detectives in puffer jackets getting drinks

Venturing into Nordic noir, or Snøballkrim as I refer to it in Norwegian, I wasn’t prepared for the well-worn knitwear of stereotypes within. Since the solstice, this bleak Jadis’ winter mixed with brutal overtones has provided me with light entertainment and a list of things to avoid if I ever write more crime fiction. The main character – investigator, detective, police person – is a hothead in…

Anti-design software

Another piece of software claims to be able to generate web interfaces from graphics. It’s a lie. Such a thing is not possible. Not 25 years ago, not now, not 25 years from now. There are two reasons: Graphics software doesn’t come close to describing interfaces sufficiently. Operating on the premise of the image, the workflow, capabilities and output are inadequate or plain wrong. The problems…

Not the users I have in mind

If most users say that a flow is good, we should make it so; if most say that the contrast is good, we should not take their word for it. Testing isn’t as straightforward as that, but the point is that there are two approaches to making the web: The majority and the minority – the general and the specific – and we need to take both. I have had several discussions on the difference between buttons…

Saying goodbye to chatbots

The typical chatbot experience is like a psychic cold-read session with C-3PO . The inaccuracy with which information is given is only surpassed by the frustration and uncertainty about what isn’t there. Is there more I should know? Why can’t I look at the complete documentation? Why do I have to prompt for things I barely know? What’s making things worse is how we renounce our accountability by…

The Implied Web

People don’t need call-to-action buttons. Interface elements made to get attention and herd people towards clicks increase cognitive effort because they obscure themselves and reduce interfaces to clickable surfaces. The implied web is based on the idea that people read interfaces through the glasses of their needs combined with previous web platform experiences. Driven by tasks, they are open to…

Nesting HTML list elements

There are two ways to nest lists in HTML, but only one communicates correctly. Correct structure Let’s say we are making a table of contents (TOC) for an article page. Beyond the page title of h1 , the article has two heading levels, h2 and h3 . We make the following structure for the first level: <ul> <li> <a>Link to h2</a> </li> <li> <a>Link to h2</a> </li> </ul> For the second level, the nested…

CSS context variants

Without modifiers, props or utilities In Making components with CSS nesting , we looked at different ways to make a keyword list component with and without links. If we want to make that even more reusable, there are also multiple ways to make variants. With BEM, we have the modifier class. With JS components, we can set a prop and build logic that outputs the correct variant. And with utilities,…

Making components with CSS nesting

CSS nesting can help us write better frontends by moving our approach towards thinking more about the bigger picture. It also makes working with fewer class names easier, but does it make BEM and other naming conventions obsolete? A list component One of the areas I have overused classes in the past is lists. Whether it’s been plain types or richer navigation, I have made classes for every element…

CSS experience, structure and utility use

Write CSS as CSS in CSS. It is the best way to learn, and it gives us the best code quality because it leans on language and platform. Anything else tends to turn out not to be CSS at all, maybe fast to write at first but it makes us fall behind on the language and its evolution. Strong beliefs, weakly held We are programming the browser , not painting with code or assembling LEGO. In any kind of…

Grasping CSS: The speed of proficiency

Getting fast at building frontend means going beyond trying to make something work as quickly as possible. Aiming for speed instead of efficiency makes learning CSS more difficult today than it was twenty years ago. It’s not because the language evolved but because the many shortcuts get us stuck in bad practices. Flogging frontend CSS is a language with which we can make something appear in the…

Grasping CSS: The concept of logic

The key to understanding CSS is to get past the notion that frontend development is about producing visuals. Visuals are one aspect, but we never make them directly. We make it easier for ourselves when we stop thinking about the interface as significantly related to the image. Two different techniques producing the same visual result will be of varying quality. One can be lengthy, fragile and…

Signing git commits with existing SSH key

Getting verified commits on GitHub by signing git commits using an existing SSH key requires specific steps that current documentation fails to explain clearly, especially if you don’t want to regenerate keys or make a GPG key. How to sign and verify commits with an existing SSH key Anyone can commit using any name and email address they want. Signing and verifying commits enable us to confirm…

Separating concerns with complex CSS selectors

Separating concerns I recently used CSS has() to show and hide buttons based on the content of a sibling of the parent . I considered using two classes to refer to one element; one to style a container and another one to check for content inside it. Using them separately, we can change the styling class name without affecting the other. That’s the rationale behind separating classes for JS and…

From 15 lines of JS to 3 lines of CSS has()

Using CSS has() to write complex selectors is fun, especially when we compare the logic to JavaScript and can see how different the two languages are at doing the same. A colleague and I recently made two buttons to expand and collapse all the levels in a documentation schema, and we didn’t want to show the two buttons in cases where there were no expanding levels. We needed conditional checking…

AI’s superficial ripoff for consumption

Images, text, music and other products from various so-called AI models will never be the artistic output it mimics because it’s not about creating; it’s just consumption. In terms of process, there is little difference between putting on a movie or song that already exists and prompting what in reality are large language models (LLM) for something of the same completeness. Without process,…

The dissonant, unverifiable, dull output of ChatGPT

Suppose you ask the so-called artificial intelligence (“AI”) why you like your favourite band. It will look at other bands you like, find the one closest to your favourite by predefined category parameters, and spit out that band name as an answer. It won’t be entirely wrong – the two have some connection, and we like them both, but it’s also far from correct. One band isn’t the source of the…

Creativity without collaboration tools

My career-long aversion to post-it notes peaked after an intense period of workshops. Small, contained, limited and limiting; the tiny, sticky paper is the antithesis of a yes phase and attracts more lint than ideas. Anti creativity Post-its play a crucial role in many stupid things: Writing down passwords and sticking them onto the screen. Contributing a couple of words without context. Quickly…

Getting people to participate equally

Getting people to participate in meetings, workshops and their field of expertise goes beyond removing gates and lowering thresholds. We must also work with the participants’ inner threshold, whether too high or too low, because there is no correlation between one person’s words per meeting and the quality of their ideas. Preventing people from participating Gatekeeping Gatekeeping is about the…

How pointer coursor affects our usability decisions

Most interfaces, design systems and UI frameworks seem to be made by someone who has only heard stories of interfaces. It’s what we get when imitating each other. It’s what we get when bad practices become expectations. It’s what we get when making decisions without reasoning. We know what interfaces look like and how to get them working, but we don’t know why they should be in certain ways. The…

Set up a global chart.js config

I needed to make a distributable global base config for the React version of chart.js that still allowed for local overriding. The nice thing about chart.js is that this is possible. On the other hand, it’s chaining-heavy, and the documentation for it is basic and lacks relevant use cases. The way to define one global property is to use the complete chained object for each setting, like…

Programming unique accessibility

Arguing against accessibility isn’t only about the inability to see things from the perspective of others. It might also come from mistaking universal accessibility for tailoring, thinking the interface will be less convenient or harder to use for some. A car might be custom-built for one person, which is OK since it is that person’s car, compared to public transport intended for everyone . On the…

Target this pointer event

With e.target , this and a bit of CSS, we can cover several use cases where we need to both register a click, or event, on an element and then do something with the same element. Single button Let’s say we have a single button with the id loner that we want to hide when clicking it. We can solve that in the following way by using e.target const singleButton = document.querySelector("#loner")…

Iterating instead of redesigning

When we work as if interfaces can reach completion, our fixes and new features tend to turn into redesign projects. We set out to make things right this time around; we might improve them but also change them to a degree where we introduce new issues. This form of redesign not only makes testing both less viable and valuable, but it also hinders building the team’s experience. We can counter this…

JS, SSG and CMS: Pick what you need

HTML, CSS and JS are not the output of our work, it is the matter we must know, account for and work with. Even if we produce it indirectly through frameworks, server rendering, templates or other languages. These are some of my experiences with picking such frontend tools. First criterion Out tools must enable us to generate code on a level that at least matches what we otherwise would have…

Sequential-functional teams

"Every team needs a role x " can mean two things, either plainly "we need expertise x to make y " or more complicated "if you don’t have role x , you don’t have expertise x ". The first meaning is easy enough to agree or even disagree with. The second one is a problem for the cross-functional team, its members and their process. Teams by role If we put together a team based on a set of roles, each…

Craft CMS, React, TypeScript and back again

I threw out React and saved the user from downloading 175 kB JavaScript spread across 1 bundle and 8 chunks. Almost 600 lines of code written for React was converted to under 200 lines of Twig code and 25 lines of JS. Additionally, I removed: 200 lines of PHP to generate the JSON output. React and react-waypoint. Duplicated SVG code ( Craft can flexibly inline SVGs instead). I have previously…

CS50 and my final project

I completed Harvard’s CS50x: CS50’s Introduction to Computer Science on the last day of October 2021 and received a passing grade a couple of weeks later. It’s a course about "abstraction, algorithms, data structures, encapsulation, resource management, security, software engineering, and web programming". In addition to ten labs and problems sets along the way, there’s a final project where you…

Code knowledge to design

Successfully designing web interfaces requires the intentional picking of HTML elements. As interfaces aren’t clickable visuals, we can’t avoid code and we can’t hand things off to be "translated" into code. Knowledge to use Knowing HTML doesn’t mean knowing each element by heart. Knowing HTML means having a combined knowledge enabling us to use the right elements and communicate what they are and…

Date input height in Safari

input type="date" in Safari renders an input much taller than others. Why not let it render like other inputs? The reasons are unknown. Luckily, it can be fixed by targeting the -webkit-datetime-edit pseudo-element. There seems to be a couple of extra px of padding and a custom line height or a line height that isn’t given the same value as the other inputs. The fix input::-webkit-datetime-edit {…

UI sketches, not just a waste of time

Sketches – complete drawings as interface blueprints – have no place in interface design. Their fixed nature is fundamentally different to that of the fluid interface. Yet, that doesn’t mean such drawings are always entirely useless. Fidelity and intent Although I stopped making them several years ago, and people don’t ask me for them or try to hand me any, sketches can be useful when made with…

Friendly and unfriendly px unit use

Our job is not to control what every user gets but to give the interface the ability to perform the calculations it needs to provide enough flexibility. Solidified image vs user-relative instructions Technically and ideally, an interface is a set of instructions that should work with whatever technology the user prefers or requires. We can use different approaches, techniques and units to achieve…

Fluid web typography with clamp() and vw needs calc()

Setting the font size like clamp(1.875rem, 3vw, 3.75rem) defeats the purpose of using rem. We must throw calc() into the mix to make it user-friendly. The clamp() function sets three sizes: a min size, an in-between size and a max size. A common example: h1 { font-size: clamp(1.875rem, 3vw, 3.75rem); } The second argument’s use of a single vw is problematic. It makes the in-between size relative…

Keep using system fonts

“System fonts” sounds boring, like a choice not made. It has the air of “something an engineer would pick”; it doesn’t feel like a design decision. And it doesn’t allow us to put “friendly, well-rounded and warm font” in our presentations. All that is either wrong or pointless because: Using system fonts is the only conclusion to a user-based chain of reasoning for many interfaces, especially…

Design system docs without colour

Colour pages tend to be listed as one of the first items in a documentation because they are basic properties present in all other elements. But this turns them into base elements and makes the palette – and not users and functionality – the starting and reference points for new elements Read the full article " Design system docs without colour " on the Bring dev blog

Contributing to Style Stage

Style Stage is a project showcasing different ways to style one page just by switching the CSS. My contribution, Sysfonts , is meant to demonstrate the use of system fonts because that is, in my opinion, the best option for applications, both browser-living and native. I think they work pretty good on more text-based sites as well. I have written an article about system vs. custom fonts . What I…

Breaking and wrapping text with CSS

Overflow, wrap and break Overflow happens when an element is bigger than its container. Wrap is when an element continues on the next line instead of overflowing. Text wrapping happens by default at characters like spaces and hyphens, but not inside words. That works in most cases, but sometimes we need to control if and where wrapping should occur. Break is when wrapping happens inside a word;…

The uselessness of donut charts

Donut charts are not good at communicating. They look cool but are just as useless as pie charts. A donut is not just a pie chart with a hole; it’s a distorted stacked bar biting its tail. Hard to read In terms of shape, there are some warning signs. Comparing shapes It’s difficult to compare circles. They don’t give an immediate impression of any difference between two almost equal sizes, while…

Principle for responsive tables

When I set out to solve responsive tables, I figured it would take a whole team a couple of weeks and we would build a microscopic component to provide clever shuffling of div elements. Instead, my conclusion led me to the opposite. Responsive tables are less about making them responsive and more about presenting them in responsive environments. Read about the principle and the explanation over at…

Hugo timestamp with relURL

I’m fairly new to Hugo , but I’ve worked with my fair share of template languages to feel reasonably at home. Enough to both see familiar patterns, but also wonder "why have they done it like that?" Although the documentation could be a lot better, my biggest gripe now is the patchy support of syntax highlighting and formatting. When my team tried to combine a timestamp with a relative url we got…

Web typography: Header spacing

Never settle for default spacing The default spacing places headers in the middle between two paragraphs. It is as if the headers don't really belong anywhere. The header becomes a visual separator, and the semantic connection to the text that follows it becomes unclear. The meaningful structure falls apart. The distance also makes the paragraphs' normal line-height look too tight. It tempts you…

Feedback in the age of pedants

When to point out mistakes Never If it is one typo in some notes. In the middle of a presentation. Immediately after the presentation. If your only feedback is typo based. If you wouldn't have appreciated feedback at the given time. If something is not finished and you have not been asked to give feedback. If your feedback is feelings-based. If you are trying to impress someone. If the nerd alert…

Craft CMS, React, TypeScript and useful overkill

This site's setup is was unnecessarily complex . It runs on the PHP based Craft CMS outputting JSON through its Element API, that is fetched and displayed using React written with TypeScript compiled to JavaScript. And that's only the front page, the articles still use Twig templating, the default for Craft. The workflow isn't inefficient, but I could have made it simpler by just keeping Twig or…

Code – the superior design tool

The article is published on the Norwegian developer site, Kode24: Kode som overlegent designverktøy The English version can be read at the Bring developer blog: Code – the superior design tool

From SCSS and back to regular CSS

After having used SCSS/SASS for about five years, I recently quit. It's a great tool, but other tools with the possibility to use only what you need have taken over. And CSS has changed as well. When I started using SCSS, it was for browser prefix mixins, I had some heavy stuff going on just for supporting flexbox. And even then a lot of the parameters had to be duplicated because the values…

Scramble ramble: Passwords, salt and hash

Passwords should be set, not sent – and other things I thought about when someone talked about password-emailing as a natural part of the user registration. I'm no security expert, but that's a big no-no. Only the user should have the password A password can't be secure unless it has been set by the user, it doesn't matter if it's at registration or if it has been forgotten. Online stores, banks,…

Zombie CSS, dependency cravings

The article can be found at the Bring developer blog: developer.bring.com/blog/zombie-css/

componentDidUpdate(): No prevState without prevProps

Before React Hooks , I used the React lifecycle method componentDidUpdate() . A common way to use it is/was to fetch data based on changes made by the user. Let’s say, selecting a date. If the user selects the same date as the current date, it’s nice to not go fetch the same data again. Avoiding blinking interfaces and unnecessary network requests. In order to do that, we compare the current date…

What I learnt in my first two years as a comic artist

For years I wrote a bunch of nonsensical short texts. At 25-30 pages, of what I consider glimpses into different characters' life and times, I decided to make a comic called Husbråk . Instead of being crippled by the fact that I hadn't done much of it before, I wanted to utilise the process to improve my skills. Year one: Just draw I started drawing. First, a few demos to figure out frames, sizes…