Beyond The Hype: What AI Can Really Do For Product Design Beyond The Hype: What AI Can Really Do For Product Design Nikita Samutin 2025-08-18T13:00:00+00:00 2025-08-21T11:03:55+00:00 These days, it’s easy to find curated lists of AI tools for designers, galleries of generated illustrations, and countless […]
Accessibility
Intl API: A Definitive Guide To Browser-Native InternationalizationThe Power Of The <code>Intl</code> API: A Definitive Guide To Browser-Native Internationalization The Power Of The <code>Intl</code> API: A Definitive Guide To Browser-Native Internationalization Fuqiao Xue 2025-08-08T10:00:00+00:00 2025-08-13T15:04:28+00:00 It’s a common misconception that internationalization (i18n) is simply about translating text. While crucial, translation is merely […]
Accessibility
Automating Design Systems: Tips And Resources For Getting Started Automating Design Systems: Tips And Resources For Getting Started Joas Pambou 2025-08-06T10:00:00+00:00 2025-08-07T14:02:50+00:00 A design system is more than just a set of colors and buttons. It’s a shared language that helps designers and developers build […]
Accessibility
Converting Plain Text To Encoded HTML With Vanilla JavaScript Converting Plain Text To Encoded HTML With Vanilla JavaScript Alexis Kypridemos 2024-04-17T13:00:00+00:00 2025-06-25T15:04:30+00:00 When copying text from a website to your device’s clipboard, there’s a good chance that you will get the formatted HTML when pasting […]
Accessibility
2024-04-17T13:00:00+00:00
2025-06-25T15:04:30+00:00
When copying text from a website to your device’s clipboard, there’s a good chance that you will get the formatted HTML when pasting it. Some apps and operating systems have a “Paste Special” feature that will strip those tags out for you to maintain the current style, but what do you do if that’s unavailable?
Same goes for converting plain text into formatted HTML. One of the closest ways we can convert plain text into HTML is writing in Markdown as an abstraction. You may have seen examples of this in many comment forms in articles just like this one. Write the comment in Markdown and it is parsed as HTML.
Even better would be no abstraction at all! You may have also seen (and used) a number of online tools that take plainly written text and convert it into formatted HTML. The UI makes the conversion and previews the formatted result in real time.
Providing a way for users to author basic web content — like comments — without knowing even the first thing about HTML, is a novel pursuit as it lowers barriers to communicating and collaborating on the web. Saying it helps “democratize” the web may be heavy-handed, but it doesn’t conflict with that vision!

We can build a tool like this ourselves. I’m all for using existing resources where possible, but I’m also for demonstrating how these things work and maybe learning something new in the process.
There are plenty of assumptions and considerations that could go into a plain-text-to-HTML converter. For example, should we assume that the first line of text entered into the tool is a title that needs corresponding <h1> tags? Is each new line truly a paragraph, and how does linking content fit into this?
Again, the idea is that a user should be able to write without knowing Markdown or HTML syntax. This is a big constraint, and there are far too many HTML elements we might encounter, so it’s worth knowing the context in which the content is being used. For example, if this is a tool for writing blog posts, then we can limit the scope of which elements are supported based on those that are commonly used in long-form content: <h1>, <p>, <a>, and <img>. In other words, it will be possible to include top-level headings, body text, linked text, and images. There will be no support for bulleted or ordered lists, tables, or any other elements for this particular tool.
The front-end implementation will rely on vanilla HTML, CSS, and JavaScript to establish a small form with a simple layout and functionality that converts the text to HTML. There is a server-side aspect to this if you plan on deploying it to a production environment, but our focus is purely on the front end.
There are existing ways to accomplish this. For example, some libraries offer a WYSIWYG editor. Import a library like TinyMCE with a single <script> and you’re good to go. WYSIWYG editors are powerful and support all kinds of formatting, even applying CSS classes to content for styling.
But TinyMCE isn’t the most efficient package at about 500 KB minified. That’s not a criticism as much as an indication of how much functionality it covers. We want something more “barebones” than that for our simple purpose. Searching GitHub surfaces more possibilities. The solutions, however, seem to fall into one of two categories:
<h1> and <p> tags.Even if a perfect solution for what we want was already out there, I’d still want to pick apart the concept of converting text to HTML to understand how it works and hopefully learn something new in the process. So, let’s proceed with our own homespun solution.
We’ll start with the HTML structure for the input and output. For the input element, we’re probably best off using a <textarea>. For the output element and related styling, choices abound. The following is merely one example with some very basic CSS to place the input <textarea> on the left and an output <div> on the right:
See the Pen [Base Form Styles [forked]](https://codepen.io/smashingmag/pen/OJGoNOX) by Geoff Graham.
You can further develop the CSS, but that isn’t the focus of this article. There is no question that the design can be prettier than what I am providing here!
We’ll set an onkeyup event handler on the <textarea> to call a JavaScript function called convert() that does what it says: convert the plain text into HTML. The conversion function should accept one parameter, a string, for the user’s plain text input entered into the <textarea> element:
<textarea onkeyup='convert(this.value);'></textarea>
onkeyup is a better choice than onkeydown in this case, as onkeyup will call the conversion function after the user completes each keystroke, as opposed to before it happens. This way, the output, which is refreshed with each keystroke, always includes the latest typed character. If the conversion is triggered with an onkeydown handler, the output will exclude the most recent character the user typed. This can be frustrating when, for example, the user has finished typing a sentence but cannot yet see the final punctuation mark, say a period (.), in the output until typing another character first. This creates the impression of a typo, glitch, or lag when there is none.
In JavaScript, the convert() function has the following responsibilities:
<h1> or <p> HTML tag, whichever is most appropriate.<a> tags, and replace image file names with <img> elements.And from there, we display the output. We can create separate functions for each responsibility. Let’s name them accordingly:
html_encode()convert_text_to_HTML()convert_images_and_links_to_HTML()Each function accepts one parameter, a string, and returns a string.
Use the html_encode() function to HTML encode/sanitize the input. HTML encoding refers to the process of escaping or replacing certain characters in a string input to prevent users from inserting their own HTML into the output. At a minimum, we should replace the following characters:
< with <> with >& with &' with '" with "JavaScript does not provide a built-in way to HTML encode input as other languages do. For example, PHP has htmlspecialchars(), htmlentities(), and strip_tags() functions. That said, it is relatively easy to write our own function that does this, which is what we’ll use the html_encode() function for that we defined earlier:
function html_encode(input) {
const textArea = document.createElement("textarea");
textArea.innerText = input;
return textArea.innerHTML.split("<br>").join("n");
}
HTML encoding of the input is a critical security consideration. It prevents unwanted scripts or other HTML manipulations from getting injected into our work. Granted, front-end input sanitization and validation are both merely deterrents because bad actors can bypass them. But we may as well make them work a little harder.
As long as we are on the topic of securing our work, make sure to HTML-encode the input on the back end, where the user cannot interfere. At the same time, take care not to encode the input more than once. Encoding text that is already HTML-encoded will break the output functionality. The best approach for back-end storage is for the front end to pass the raw, unencoded input to the back end, then ask the back-end to HTML-encode the input before inserting it into a database.
That said, this only accounts for sanitizing and storing the input on the back end. We still have to display the encoded HTML output on the front end. There are at least two approaches to consider:
Let’s use the convert_text_to_HTML() function we defined earlier to wrap each line in their respective HTML tags, which are going to be either <h1> or <p>. To determine which tag to use, we will split the text input on the newline character (n) so that the text is processed as an array of lines rather than a single string, allowing us to evaluate them individually.
function convert_text_to_HTML(txt) {
// Output variable
let out = '';
// Split text at the newline character into an array
const txt_array = txt.split("n");
// Get the number of lines in the array
const txt_array_length = txt_array.length;
// Variable to keep track of the (non-blank) line number
let non_blank_line_count = 0;
for (let i = 0; i < txt_array_length; i++) {
// Get the current line
const line = txt_array[i];
// Continue if a line contains no text characters
if (line === ''){
continue;
}
non_blank_line_count++;
// If a line is the first line that contains text
if (non_blank_line_count === 1){
// ...wrap the line of text in a Heading 1 tag
out += `<h1>${line}</h1>`;
// ...otherwise, wrap the line of text in a Paragraph tag.
} else {
out += `<p>${line}</p>`;
}
}
return out;
}
In short, this little snippet loops through the array of split text lines and ignores lines that do not contain any text characters. From there, we can evaluate whether a line is the first one in the series. If it is, we slap a <h1> tag on it; otherwise, we mark it up in a <p> tag.
This logic could be used to account for other types of elements that you may want to include in the output. For example, perhaps the second line is assumed to be a byline that names the author and links up to an archive of all author posts.
Next, we’re going to create our convert_images_and_links_to_HTML() function to encode URLs and images as HTML elements. It’s a good chunk of code, so I’ll drop it in and we’ll immediately start picking it apart together to explain how it all works.
function convert_images_and_links_to_HTML(string){
let urls_unique = [];
let images_unique = [];
const urls = string.match(/https*://[^s<),]+[^s<),.]/gmi) ?? [];
const imgs = string.match(/[^"'>s]+.(jpg|jpeg|gif|png|webp)/gmi) ?? [];
const urls_length = urls.length;
const images_length = imgs.length;
for (let i = 0; i < urls_length; i++){
const url = urls[i];
if (!urls_unique.includes(url)){
urls_unique.push(url);
}
}
for (let i = 0; i < images_length; i++){
const img = imgs[i];
if (!images_unique.includes(img)){
images_unique.push(img);
}
}
const urls_unique_length = urls_unique.length;
const images_unique_length = images_unique.length;
for (let i = 0; i < urls_unique_length; i++){
const url = urls_unique[i];
if (images_unique_length === 0 || !images_unique.includes(url)){
const a_tag = `<a href="${url}" target="_blank">${url}</a>`;
string = string.replace(url, a_tag);
}
}
for (let i = 0; i < images_unique_length; i++){
const img = images_unique[i];
const img_tag = `<img src="${img}" alt="">`;
const img_link = `<a href="${img}">${img_tag}</a>`;
string = string.replace(img, img_link);
}
return string;
}
Unlike the convert_text_to_HTML() function, here we use regular expressions to identify the terms that need to be wrapped and/or replaced with <a> or <img> tags. We do this for a couple of reasons:
convert_text_to_HTML() function handles text that would be transformed to the HTML block-level elements <h1> and <p>, and, if you want, other block-level elements such as <address>. Block-level elements in the HTML output correspond to discrete lines of text in the input, which you can think of as paragraphs, the text entered between presses of the Enter key.Regular expressions, though they are powerful and the appropriate tool to use for this job, come with a performance cost, which is another reason to use each expression only once for the entire text input.
Remember: All the JavaScript in this example runs each time the user types a character, so it is important to keep things as lightweight and efficient as possible.
I also want to make a note about the variable names in our convert_images_and_links_to_HTML() function. images (plural), image (singular), and link are reserved words in JavaScript. Consequently, imgs, img, and a_tag were used for naming. Interestingly, these specific reserved words are not listed on the relevant MDN page, but they are on W3Schools.
We’re using the String.prototype.match() function for each of the two regular expressions, then storing the results for each call in an array. From there, we use the nullish coalescing operator (??) on each call so that, if no matches are found, the result will be an empty array. If we do not do this and no matches are found, the result of each match() call will be null and will cause problems downstream.
const urls = string.match(/https*://[^s<),]+[^s<),.]/gmi) ?? [];
const imgs = string.match(/[^"'>s]+.(jpg|jpeg|gif|png|webp)/gmi) ?? [];
Next up, we filter the arrays of results so that each array contains only unique results. This is a critical step. If we don’t filter out duplicate results and the input text contains multiple instances of the same URL or image file name, then we break the HTML tags in the output. JavaScript does not provide a simple, built-in method to get unique items in an array that’s akin to the PHP array_unique() function.
The code snippet works around this limitation using an admittedly ugly but straightforward procedural approach. The same problem is solved using a more functional approach if you prefer. There are many articles on the web describing various ways to filter a JavaScript array in order to keep only the unique items.
We’re also checking if the URL is matched as an image before replacing a URL with an appropriate <a> tag and performing the replacement only if the URL doesn’t match an image. We may be able to avoid having to perform this check by using a more intricate regular expression. The example code deliberately uses regular expressions that are perhaps less precise but hopefully easier to understand in an effort to keep things as simple as possible.
And, finally, we’re replacing image file names in the input text with <img> tags that have the src attribute set to the image file name. For example, my_image.png in the input is transformed into <img src='my_image.png'> in the output. We wrap each <img> tag with an <a> tag that links to the image file and opens it in a new tab when clicked.
There are a couple of benefits to this approach:
<figcaption>, <cite>, or similar element. But if, for whatever reason, you are unable to provide explicit attribution, you are at least providing a link to the image source.It may go without saying, but “hotlinking” images is something to avoid. Use only locally hosted images wherever possible, and provide attribution if you do not hold the copyright for them.
Before we move on to displaying the converted output, let’s talk a bit about accessibility, specifically the image alt attribute. The example code I provided does add an alt attribute in the conversion but does not populate it with a value, as there is no easy way to automatically calculate what that value should be. An empty alt attribute can be acceptable if the image is considered “decorative,” i.e., purely supplementary to the surrounding text. But one may argue that there is no such thing as a purely decorative image.
That said, I consider this to be a limitation of what we’re building.
We’re at the point where we can finally work on displaying the HTML-encoded output! We’ve already handled all the work of converting the text, so all we really need to do now is call it:
function convert(input_string) {
output.innerHTML = convert_images_and_links_to_HTML(convert_text_to_HTML(html_encode(input_string)));
}
If you would rather display the output string as raw HTML markup, use a <pre> tag as the output element instead of a <div>:
<pre id='output'></pre>
The only thing to note about this approach is that you would target the <pre> element’s textContent instead of innerHTML:
function convert(input_string) {
output.textContent = convert_images_and_links_to_HTML(convert_text_to_HTML(html_encode(input_string)));
}
We did it! We built one of the same sort of copy-paste tool that converts plain text on the spot. In this case, we’ve configured it so that plain text entered into a <textarea> is parsed line-by-line and encoded into HTML that we format and display inside another element.
See the Pen [Convert Plain Text to HTML (PoC) [forked]](https://codepen.io/smashingmag/pen/yLrxOzP) by Geoff Graham.
We were even able to keep the solution fairly simple, i.e., vanilla HTML, CSS, and JavaScript, without reaching for a third-party library or framework. Does this simple solution do everything a ready-made tool like a framework can do? Absolutely not. But a solution as simple as this is often all you need: nothing more and nothing less.
As far as scaling this further, the code could be modified to POST what’s entered into the <form> using a PHP script or the like. That would be a great exercise, and if you do it, please share your work with me in the comments because I’d love to check it out.
Setting And Persisting Color Scheme Preferences With CSS And A “Touch” Of JavaScript Setting And Persisting Color Scheme Preferences With CSS And A “Touch” Of JavaScript Henry Bley-Vroman 2024-03-25T12:00:00+00:00 2025-06-25T15:04:30+00:00 Many modern websites give users the power to set a site-specific color scheme preference. A basic implementation is straightforward […]
Accessibility
2024-03-25T12:00:00+00:00
2025-06-25T15:04:30+00:00
Many modern websites give users the power to set a site-specific color scheme preference. A basic implementation is straightforward with JavaScript: listen for when a user changes a checkbox or clicks a button, toggle a class (or attribute) on the <body> element in response, and write the styles for that class to override design with a different color scheme.
CSS’s new :has() pseudo-class, supported by major browsers since December 2023, opens many doors for front-end developers. I’m especially excited about leveraging it to modify UI in response to user interaction without JavaScript. Where previously we have used JavaScript to toggle classes or attributes (or to set styles directly), we can now pair :has() selectors with HTML’s native interactive elements.
Supporting a color scheme preference, like “Dark Mode,” is a great use case. We can use a <select> element anywhere that toggles color schemes based on the selected <option> — no JavaScript needed, save for a sprinkle to save the user’s choice, which we’ll get to further in.
First, we’ll support a user’s system-wide color scheme preferences by adopting a “Light Mode”-first approach. In other words, we start with a light color scheme by default and swap it out for a dark color scheme for users who prefer it.
The prefers-color-scheme media feature detects the user’s system preference. Wrap “dark” styles in a prefers-color-scheme: dark media query.
selector {
/* light styles */
@media (prefers-color-scheme: dark) {
/* dark styles */
}
}
Next, set the color-scheme property to match the preferred color scheme. Setting color-scheme: dark switches the browser into its built-in dark mode, which includes a black default background, white default text, “dark” styles for scrollbars, and other elements that are difficult to target with CSS, and more. I’m using CSS variables to hint that the value is dynamic — and because I like the browser developer tools experience — but plain color-scheme: light and color-scheme: dark would work fine.
:root {
/* light styles here */
color-scheme: var(--color-scheme, light);
/* system preference is "dark" */
@media (prefers-color-scheme: dark) {
--color-scheme: dark;
/* any additional dark styles here */
}
}
Now, to support overriding the system preference, let users choose between light (default) and dark color schemes at the page level.
HTML has native elements for handling user interactions. Using one of those controls, rather than, say, a <div> nest, improves the chances that assistive tech users will have a good experience. I’ll use a <select> menu with options for “system,” “light,” and “dark.” A group of <input type="radio"> would work, too, if you wanted the options right on the surface instead of a dropdown menu.
<select id="color-scheme">
<option value="system" selected>System</option>
<option value="light">Light</option>
<option value="dark">Dark</option>
</select>
Before CSS gained :has(), responding to the user’s selected <option> required JavaScript, for example, setting an event listener on the <select> to toggle a class or attribute on <html> or <body>.
But now that we have :has(), we can now do this with CSS alone! You’ll save spending any of your performance budget on a dark mode script, plus the control will work even for users who have disabled JavaScript. And any “no-JS” folks on the project will be satisfied.
What we need is a selector that applies to the page when it :has() a select menu with a particular [value]:checked. Let’s translate that into CSS:
:root:has(select option[value="dark"]:checked)
We’re defaulting to a light color scheme, so it’s enough to account for two possible dark color scheme scenarios:
The first one is a page-preference-aware iteration of our prefers-color-scheme: dark case. A “dark” system-level preference is no longer enough to warrant dark styles; we need a “dark” system-level preference and a “follow the system-level preference” at the page-level preference. We’ll wrap the prefers-color-scheme media query dark scheme styles with the :has() selector we just wrote:
:root {
/* light styles here */
color-scheme: var(--color-scheme, light);
/* page preference is "system", and system preference is "dark" */
@media (prefers-color-scheme: dark) {
&:has(#color-scheme option[value="system"]:checked) {
--color-scheme: dark;
/* any additional dark styles, again */
}
}
}
Notice that I’m using CSS Nesting in that last snippet. Baseline 2023 has it pegged as “Newly available across major browsers” which means support is good, but at the time of writing, support on Android browsers not included in Baseline’s core browser set is limited. You can get the same result without nesting.
:root {
/* light styles */
color-scheme: var(--color-scheme, light);
/* page preference is "dark" */
&:has(#color-scheme option[value="dark"]:checked) {
--color-scheme: dark;
/* any additional dark styles */
}
}
For the second dark mode scenario, we’ll use nearly the exact same :has() selector as we did for the first scenario, this time checking whether the “dark” option — rather than the “system” option — is selected:
:root {
/* light styles */
color-scheme: var(--color-scheme, light);
/* page preference is "dark" */
&:has(#color-scheme option[value="dark"]:checked) {
--color-scheme: dark;
/* any additional dark styles */
}
/* page preference is "system", and system preference is "dark" */
@media (prefers-color-scheme: dark) {
&:has(#color-scheme option[value="system"]:checked) {
--color-scheme: dark;
/* any additional dark styles, again */
}
}
}
Now the page’s styles respond to both changes in users’ system settings and user interaction with the page’s color preference UI — all with CSS!
But the colors change instantly. Let’s smooth the transition.
Instantaneous style changes can feel inelegant in some cases, and this is one of them. So, let’s apply a CSS transition on the :root to “ease” the switch between color schemes. (Transition styles at the :root will cascade down to the rest of the page, which may necessitate adding transition: none or other transition overrides.)
Note that the CSS color-scheme property does not support transitions.
:root {
transition-duration: 200ms;
transition-property: /* properties changed by your light/dark styles */;
}
Not all users will consider the addition of a transition a welcome improvement. Querying the prefers-reduced-motion media feature allows us to account for a user’s motion preferences. If the value is set to reduce, then we remove the transition-duration to eliminate unwanted motion.
:root {
transition-duration: 200ms;
transition-property: /* properties changed by your light/dark styles */;
@media screen and (prefers-reduced-motion: reduce) {
transition-duration: none;
}
}
Transitions can also produce poor user experiences on devices that render changes slowly, for example, ones with e-ink screens. We can extend our “no motion condition” media query to account for that with the update media feature. If its value is slow, then we remove the transition-duration.
:root {
transition-duration: 200ms;
transition-property: /* properties changed by your light/dark styles */;
@media screen and (prefers-reduced-motion: reduce), (update: slow) {
transition-duration: 0s;
}
}
Let’s try out what we have so far in the following demo. Notice that, to work around color-scheme’s lack of transition support, I’ve explicitly styled the properties that should transition during theme changes.
See the Pen [CSS-only theme switcher (requires :has()) [forked]](https://codepen.io/smashingmag/pen/YzMVQja) by Henry.
Not bad! But what happens if the user refreshes the pages or navigates to another page? The reload effectively wipes out the user’s form selection, forcing the user to re-make the selection. That may be acceptable in some contexts, but it’s likely to go against user expectations. Let’s bring in JavaScript for a touch of progressive enhancement in the form of…
Here’s a vanilla JavaScript implementation. It’s a naive starting point — the functions and variables aren’t encapsulated but are instead properties on window. You’ll want to adapt this in a way that fits your site’s conventions, framework, library, and so on.
When the user changes the color scheme from the <select> menu, we’ll store the selected <option> value in a new localStorage item called "preferredColorScheme". On subsequent page loads, we’ll check localStorage for the "preferredColorScheme" item. If it exists, and if its value corresponds to one of the form control options, we restore the user’s preference by programmatically updating the menu selection.
/*
* If a color scheme preference was previously stored,
* select the corresponding option in the color scheme preference UI
* unless it is already selected.
*/
function restoreColorSchemePreference() {
const colorScheme = localStorage.getItem(colorSchemeStorageItemName);
if (!colorScheme) {
// There is no stored preference to restore
return;
}
const option = colorSchemeSelectorEl.querySelector(`[value=${colorScheme}]`);
if (!option) {
// The stored preference has no corresponding option in the UI.
localStorage.removeItem(colorSchemeStorageItemName);
return;
}
if (option.selected) {
// The stored preference's corresponding menu option is already selected
return;
}
option.selected = true;
}
/*
* Store an event target's value in localStorage under colorSchemeStorageItemName
*/
function storeColorSchemePreference({ target }) {
const colorScheme = target.querySelector(":checked").value;
localStorage.setItem(colorSchemeStorageItemName, colorScheme);
}
// The name under which the user's color scheme preference will be stored.
const colorSchemeStorageItemName = "preferredColorScheme";
// The color scheme preference front-end UI.
const colorSchemeSelectorEl = document.querySelector("#color-scheme");
if (colorSchemeSelectorEl) {
restoreColorSchemePreference();
// When the user changes their color scheme preference via the UI,
// store the new preference.
colorSchemeSelectorEl.addEventListener("input", storeColorSchemePreference);
}
Let’s try that out. Open this demo (perhaps in a new window), use the menu to change the color scheme, and then refresh the page to see your preference persist:
See the Pen [CSS-only theme switcher (requires :has()) with JS persistence [forked]](https://codepen.io/smashingmag/pen/GRLmEXX) by Henry.
If your system color scheme preference is “light” and you set the demo’s color scheme to “dark,” you may get the light mode styles for a moment immediately after reloading the page before the dark mode styles kick in. That’s because CodePen loads its own JavaScript before the demo’s scripts. That is out of my control, but you can take care to improve this persistence on your projects.
Where things can get tricky is restoring the user’s preference immediately after the page loads. If the color scheme preference in localStorage is different from the user’s system-level color scheme preference, it’s possible the user will see the system preference color scheme before the page-level preference is restored. (Users who have selected the “System” option will never get that flash; neither will those whose system settings match their selected option in the form control.)
If your implementation is showing a “flash of inaccurate color theme”, where is the problem happening? Generally speaking, the earlier the scripts appear on the page, the lower the risk. The “best option” for you will depend on your specific stack, of course.
:has()?All major browsers support :has() today Lean into modern platforms if you can. But if you do need to consider legacy browsers, like Internet Explorer, there are two directions you can go: either hide or remove the color scheme picker for those browsers or make heavier use of JavaScript.
If you consider color scheme support itself a progressive enhancement, you can entirely hide the selection UI in browsers that don’t support :has():
@supports not selector(:has(body)) {
@media (prefers-color-scheme: dark) {
:root {
/* dark styles here */
}
}
#color-scheme {
display: none;
}
}
Otherwise, you’ll need to rely on a JavaScript solution not only for persistence but for the core functionality. Go back to that traditional event listener toggling a class or attribute.
The CSS-Tricks “Complete Guide to Dark Mode” details several alternative approaches that you might consider as well when working on the legacy side of things.
The End Of My Gatsby Journey The End Of My Gatsby Journey Juan Diego Rodríguez 2024-03-06T08:00:00+00:00 2025-06-25T15:04:30+00:00 A fun fact about me is that my birthday is on Valentine’s Day. This year, I wanted to celebrate by launching a simple website that lets people receive […]
Accessibility
2024-03-06T08:00:00+00:00
2025-06-25T15:04:30+00:00
A fun fact about me is that my birthday is on Valentine’s Day. This year, I wanted to celebrate by launching a simple website that lets people receive anonymous letters through a personal link. The idea came up to me at the beginning of February, so I wanted to finish the project as soon as possible since time was of the essence.
Having that in mind, I decided not to do SSR/SSG with Gatsby for the project but rather go with a single-page application (SPA) using Vite and React — a rather hard decision considering my extensive experience with Gatsby. Years ago, when I started using React and learning more and more about today’s intricate web landscape, I picked up Gatsby.js as my render framework of choice because SSR/SSG was necessary for every website, right?
I used it for everything, from the most basic website to the most over-engineered project. I absolutely loved it and thought it was the best tool, and I was incredibly confident in my decision since I was getting perfect Lighthouse scores in the process.
The years passed, and I found myself constantly fighting with Gatsby plugins, resorting to hacky solutions for them and even spending more time waiting for the server to start. It felt like I was fixing more than making. I even started a series for this magazine all about the “Gatsby headaches” I experienced most and how to overcome them.
It was like Gatsby got tougher to use with time because of lots of unaddressed issues: outdated dependencies, cold starts, slow builds, and stale plugins, to name a few. Starting a Gatsby project became tedious for me, and perfect Lighthouse scores couldn’t make up for that.
So, I’ve decided to stop using Gatsby as my go-to framework.
To my surprise, the Vite + React combination I mentioned earlier turned out to be a lot more efficient than I expected while maintaining almost the same great performance measures as Gatsby. It’s a hard conclusion to stomach after years of Gatsby’s loyalty.
I mean, I still think Gatsby is extremely useful for plenty of projects, and I plan on talking about those in a bit. But Gatsby has undergone a series of recent unfortunate events after Netlify acquired it, the impacts of which can be seen in down-trending results from the most recent State of JavaScript survey. The likelihood of a developer picking up Gatsby again after using it for other projects plummeted from 89% to a meager 38% between 2019 and 2022 alone.

Although Gatsby was still the second most-used rendering framework as recently as 2022 — we are still expecting results from the 2023 survey — my prediction is that the decline will continue and dip well below 38%.

Seeing as this is my personal farewell to Gatsby, I wanted to write about where, in my opinion, it went wrong, where it is still useful, and how I am handling my future projects.
Kyle Mathews started working on what would eventually become Gatsby in late 2015. Thanks to its unique data layer and SSG approach, it was hyped for success and achieved a $3.8 million funding seed round in 2018. Despite initial doubts, Gatsby remained steadfast in its commitment and became a frontrunner in the Jamstack community by consistently enhancing its open-source framework and bringing new and better changes with each version.
So… where did it all go wrong?
I’d say it was the introduction of Gatsby Cloud in 2019, as Gatsby aimed at generating continuous revenue and solidifying its business model. Many (myself included) pinpoint Gatsby’s downfall to Gatsby Cloud, as it would end up cutting resources from the main framework and even making it harder to host in other cloud providers.
The core framework had been optimized in a way that using Gatsby and Gatsby Cloud together required no additional hosting configurations, which, as a consequence, made deployments in other platforms much more difficult, both by neglecting to provide documentation for third-party deployments and by releasing exclusive features, like incremental builds, that were only available to Gatsby users who had committed to using Gatsby Cloud. In short, hosting projects on anything but Gatsby Cloud felt like a penalty.
As a framework, Gatsby lost users to Next.js, as shown in both surveys and npm trends, while Gatsby Cloud struggled to compete with the likes of Vercel and Netlify; the former acquiring Gatsby in February of 2023.
“It [was] clear after a while that [Gatsby] weren’t winning the framework battle against Vercel, as a general purpose framework […] And they were probably a bit boxed in by us in terms of building a cloud platform.”
— Matt Biilmann, Netlify CEO
The Netlify acquisition was the last straw in an already tumbling framework haystack. The migration from Gatsby Cloud to Netlify wasn’t pretty for customers either; some teams were charged 120% more — or had incurred extraneous fees — after converting from Gatsby Cloud to Netlify, even with the same Gatsby Cloud plan they had! Many key Gatsby Cloud features, specifically incremental builds that reduced build times of small changes from minutes to seconds, were simply no longer available in Netlify, despite Kyle Mathews saying they would be ported over to Netlify:
“Many performance innovations specifically for large, content-heavy websites, preview, and collaboration workflows, will be incorporated into the Netlify platform and, where relevant, made available across frameworks.”
— Kyle Mathews
However, in a Netlify forum thread dated August 2023, a mere six months after the acquisition, a Netlify support engineer contradicted Mathews’s statement, saying there were no plans to add incremental features in Netlify.

That left no significant reason to remain with Gatsby. And I think this comment on the same thread perfectly sums up the community’s collective sentiment:
“Yikes. Huge blow to Gatsby Cloud customers. The incremental build speed was exactly why we switched from Netlify to Gatsby Cloud in the first place. It’s really unfortunate to be forced to migrate while simultaneously introducing a huge regression in performance and experience.”

Netlify’s acquisition also brought about a company restructuring that substantially reduced the headcount of Gatsby’s engineering team, followed by a complete stop in commit activities. A report in an ominous tweet by Astro co-founder Fred Schott further exacerbated concerns about Gatsby’s future.

Lennart Jörgens, former full-stack developer at Gatsby and Netlify, replied, insinuating there was only one person left after the layoffs:

You can see all these factors contributing to Gatsby’s usage downfall in the 2023 Stack Overflow survey.

Biilmann addressed the community’s concerns about Gatsby’s viability in an open issue from the Gatsby repository:
“While we don’t plan for Gatsby to be where the main innovation in the framework ecosystem takes place, it will be a safe, robust and reliable choice to build production quality websites and e-commerce stores, and will gain new powers by ways of great complementary tools.”
— Matt Biilmann
He also shed light on Gatsby’s future focus:
- “First, ensure stability, predictability, and good performance.
- Second, give it new powers by strong integration with all new tooling that we add to our Composable Web Platform (for more on what’s all that, you can check out our homepage).
- Third, make Gatsby more open by decoupling some parts of it that were closely tied to proprietary cloud infrastructure. The already-released Adapters feature is part of that effort.”
— Matt Biilmann
So, Gatsby gave up competing against Next.js on innovation, and instead, it will focus on keeping the existing framework clean and steady in its current state. Frankly, this seems like the most reasonable course of action considering today’s state of affairs.
Yes, Gatsby Cloud ended abruptly, but as a framework independent of its cloud provider, other aspects encouraged developers to look for alternatives to Gatsby.
As far as I am concerned, Gatsby’s developer experience (DX) became more of a burden than a help, and there are two main culprits where I lay the blame: dependency hell and slow bundling times.
Go ahead and start a new Gatsby project:
gatsby new
After waiting a couple of minutes you will get your brand new Gatsby site. You’d rightly expect to have a clean slate with zero vulnerabilities and outdated dependencies with this out-of-the-box setup, but here’s what you will find in the terminal once you run npm audit:
18 vulnerabilities (11 moderate, 6 high, 1 critical)
That looks concerning — and it is — not so much from a security perspective but as an indication of decaying DX. As a static site generator (SSG), Gatsby will, unsurprisingly, deliver a static and safe site that (normally) doesn’t have access to a database or server, making it immune to most cyber attacks. Besides, lots of those vulnerabilities are in the developer tools and never reach the end user. Alas, relying on npm audit to assess your site security is a naive choice at best.
However, those vulnerabilities reveal an underlying issue: the whopping number of dependencies Gatsby uses is 168(!) at the time I’m writing this. For the sake of comparison, Next.js uses 16 dependencies. A lot of Gatsby’s dependencies are outdated, hence the warnings, but trying to update them to their latest versions will likely unleash a dependency hell full of additional npm warnings and errors.
In a related subreddit from 2022, a user asked, “Is it possible to have a Gatsby site without vulnerabilities?”

The real answer is disappointing, but as of March 2024, it remains true.
A Gatsby site should work completely fine, even with that many dependencies, and extending your project shouldn’t be a problem, whether through its plugin ecosystem or other packages. However, when trying to upgrade any existing dependency you will find that you can’t! Or at least you can’t do it without introducing breaking changes to one of the 168 dependencies, many of which rely on outdated versions of other libraries that also cannot be updated.
It’s that inception-like roundabout of dependencies that I call dependency hell.
To me, one of the most important aspects of choosing a development tool is how comfortable it feels to use it and how fast it is to get a project up and running. As I’ve said before, users don’t care or know what a “tech stack” is or what framework is in use; they want a good-looking website that helps them achieve the task they came for. Many developers don’t even question what tech stack is used on each site they visit; at least, I hope not.
With that in mind, choosing a framework boils down to how efficiently you can use it. If your development server constantly experiences cold starts and crashes and is unable to quickly reflect changes, that’s a poor DX and a signal that there may be a better option.
That’s the main reason I won’t automatically reach for Gatsby from here on out. Installation is no longer a trivial task; the dependencies are firing off warnings, and it takes the development server upwards of 30 seconds to boot. I’ve even found that the longer the server runs, the slower it gets; this happens constantly to me, though I admittedly have not heard similar gripes from other developers. Regardless, I get infuriated having to constantly restart my development server every time I make a change to gatsby-config.js, gatsby-node.js files, or any other data source.
This new reality is particularly painful, knowing that a Vite.js + React setup can start a server within 500ms thanks to the use of esbuild.

Running gatsby build gets worse. Build times for larger projects normally take some number of minutes, which is understandable when we consider all of the pages, data sources, and optimizations Gatsby does behind the scenes. However, even a small content edit to a page triggers a full build and deployment process, and the endless waiting is not only exhausting but downright distracting for getting things done. That’s what incremental builds were designed to solve and the reason many people switched from Netlify to Gatsby Cloud when using Gatsby. It’s a shame we no longer have that as an available option.
The moment Gatsby Cloud was discontinued along with incremental builds, the incentives for continuing to use Gatsby became pretty much non-existent. The slow build times are simply too costly to the development workflow.
I still believe that Gatsby has awesome things that other rendering frameworks don’t, and that’s why I will keep using it, albeit for specific cases, such as my personal website. It just isn’t my go-to framework for everything, mainly because Gatsby (and the Jamstack) wasn’t meant for every project, even if Gatsby was marketed as a general-purpose framework.
Here’s where I see Gatsby still leading the competition:
I briefly glossed over the good parts of Gatsby in contrast to the bad parts. Does that mean that Gatsby has more bad parts? Absolutely not; you just won’t find the bad parts in any documentation. The bad parts also aren’t deal breakers in isolation, but they snowball into a tedious and lengthy developer experience that pushes away its advocates to other solutions or rendering frameworks.
I’ll go on record saying that I am not replacing Gatsby with another rendering framework, like Next.js or Remix, but just avoiding them altogether. I’ve found they aren’t actually needed in a lot of cases.
Think, why do we use any type of rendering framework in the first place? I’d say it’s for two main reasons: crawling bots and initial loading time.
Most React apps start with a hollow body, only having an empty <div> alongside <script> tags. The JavaScript code then runs in the browser, where React creates the Virtual DOM and injects the rendered user interface into the browser.
Over slow networks, users may notice a white screen before the page is actually rendered, which is just mildly annoying at best (but devastating at worst).
However, search engines like Google and Bing deploy bots that only see an empty page and decide not to crawl the content. Or, if you are linking up a post on social media, you may not get OpenGraph benefits like a link preview.
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
This was the case years ago, making SSR/SSG necessary for getting noticed by Google bots. Nowadays, Google can run JavaScript and render the content to crawl your website. While using SSR or SSG does make this process faster, not all bots can run JavaScript. It’s a tradeoff you can make for a lot of projects and one you can minimize on your cloud provider by pre-rendering your content.
Pre-rendered pages load faster since they deliver static content that relieves the browser from having to run expensive JavaScript.
It’s especially useful when loading pages that are behind authentication; in a client-side rendered (CSR) page, we would need to display a loading state while we check if the user is logged in, while an SSR page can perform the check on the server and send back the correct static content. I have found, however, that this trade-off is an uncompelling argument for using a rendering framework over a CSR React app.
In any case, my SPA built on React + Vite.js gave me a perfect Lighthouse score for the landing page. Pages that fetch data behind authentication resulted in near-perfect Core Web Vitals scores.


Gatsby and rendering frameworks are excellent for programmatically creating pages from data and, specifically, for blogs, e-commerce, and documentation.
Don’t be disappointed, though, if it isn’t the right tool for every use case, as that is akin to blaming a screwdriver for not being a good hammer. It still has good uses, though fewer than it could due to all the reasons we discussed before.
But Gatsby is still a useful tool. If you are a Gatsby developer the main reason you’d reach for it is because you know Gatsby. Not using it might be considered an opportunity cost in economic terms:
“Opportunity cost is the value of the next-best alternative when a decision is made; it’s what is given up.”
Imagine a student who spends an hour and $30 attending a yoga class the evening before a deadline. The opportunity cost encompasses the time that could have been dedicated to completing the project and the $30 that could have been used for future expenses.
As a Gatsby developer, I could start a new project using another rendering framework like Next.js. Even if Next.js has faster server starts, I would need to factor in my learning curve to use it as efficiently as I do Gatsby. That’s why, for my latest project, I decided to avoid rendering frameworks altogether and use Vite.js + React — I wanted to avoid the opportunity cost that comes with spending time learning how to use an “unfamiliar” framework.
So, is Gatsby dead? Not at all, or at least I don’t think Netlify will let it go away any time soon. The acquisition and subsequent changes to Gatsby Cloud may have taken a massive toll on the core framework, but Gatsby is very much still breathing, even if the current slow commits pushed to the repo look like it’s barely alive or hibernating.
I will most likely stick to Vite.js + React for my future endeavors and only use rendering frameworks when I actually need them. What are the tradeoffs? Sacrificing negligible page performance in favor of a faster and more pleasant DX that maintains my sanity? I’ll take that deal every day.
And, of course, this is my experience as a long-time Gatsby loyalist. Your experience is likely to differ, so the mileage of everything I’m saying may vary depending on your background using Gatsby on your own projects.
That’s why I’d love for you to comment below: if you see it differently, please tell me! Is your current experience using Gatsby different, better, or worse than it was a year ago? What’s different to you, if anything? It would be awesome to get other perspectives in here, perhaps from someone who has been involved in maintaining the framework.
A Designer’s Accessibility Advocacy Toolkit A Designer’s Accessibility Advocacy Toolkit Yichan Wang 2024-02-26T18:00:00+00:00 2025-06-25T15:04:30+00:00 Web accessibility can be challenging, particularly for clients unfamiliar with tech or compliance with The Americans With Disabilities Act (ADA). My role as a digital designer often involves guiding clients toward […]
Accessibility
2024-02-26T18:00:00+00:00
2025-06-25T15:04:30+00:00
Web accessibility can be challenging, particularly for clients unfamiliar with tech or compliance with The Americans With Disabilities Act (ADA). My role as a digital designer often involves guiding clients toward ADA-compliant web designs. I’ve acquired many strategies over the years for encouraging clients to adopt accessible web practices and invest in accessible user interfaces. It’s something that comes up with nearly every new project, and I decided to develop a personal toolkit to help me make the case.
Now, I am opening up my toolkit for you to have and use. While some of the strategies may be specific to me and my work, there are plenty more that cast a wider net and are more universally applicable. I’ve considered different real-life scenarios where I have had to make a case for accessibility. You may even personally identify with a few of them!
Please enjoy. As you do, remember that there is no silver bullet for “selling” accessibility. We can’t win everyone over with cajoling or terse arguments. My hope is that you are able to use this collection to establish partnerships with your colleagues and clients alike. Accessibility is something that anyone can influence at various stages in a project, and “winning” an argument isn’t exactly the point. It’s a bigger picture we’re after, one that influences how teams work together, changes habits, and develops a new level of empathy and understanding.
I begin with general strategies for discussing accessibility with clients. Following that, I provide specific language and responses you can use to introduce accessibility practices to your team and clients and advocate its importance while addressing client skepticism and concerns. Use it as a starting point and build off of it so that it incorporates points and scenarios that are more specific to your work. I sincerely hope it helps you advance accessible practices.
We’ll start with a few ways you can position yourself when interacting with clients. By adopting a certain posture, we can set ourselves up to be the experts in the room, the ones with solutions rather than arguments.
I tend to establish my expertise and tailor the information to the client’s understanding of accessibility, which could be not very much. For those new to accessibility, I offer a concise overview of its definition, evaluation, and business impact. For clients with a better grasp of accessible practices, I like to use the WCAG as a point of reference for helping frame productive discussions based on substance and real requirements.
I connect accessibility to the client’s goals instead of presenting accessibility as a moral imperative. No one loves being told what to do, and talking to clients on their terms establishes a nice bridge for helping them connect the dots between the inherent benefits of accessible practices and what they are trying to accomplish. The two aren’t mutually exclusive!
In fact, there are many clear benefits for apps that make accessibility a first-class feature. Refer to the “Accessibility Benefits” section to help describe those benefits to your colleagues and clients.
I outline accessibility goals early, typically when defining the project scope and requirements. Baking accessibility into the project scope ensures that it is at least considered at this crucial stage where decisions are being made for everything from expected outcomes to architectural requirements.
User stories and personas are common artifacts for which designers are often responsible. Use these as opportunities to define accessibility in the same breath as defining who the users are and how they interact with the app. Framing stories and outcomes as user interactions in an “as-when-then-so” format provides an opening to lead with accessibility:
As a user, when I __________, then I expect that __________, so I can _________.
Fill in the blanks. I think you’ll find that user’s expected outcomes are typically aligned with accessible experiences. Federico Francioni published his take on developing inclusive user personas, building off other excellent resources, including Microsoft’s Inclusive Design guidelines.
I maintain a database of resources for clients interested in learning more about accessibility. Sharing anecdotes, such as clients who’ve seen benefits from accessibility or examples of companies penalized for non-compliance, can be very impactful.
Microsoft is helpful here once again with a collection of brief videos that cover a variety of uses, from informing your colleagues and clients on basic accessibility concepts to interviews with accessibility professionals and case studies involving real users.
There are a few go-to resources I’ve bookmarked to share with clients who are learning about accessibility for the first time. What I like about these is the approachable language and clarity. “Learn Accessibility” from web.dev is especially useful because it’s framed as a 21-part course. That may sound daunting, but it’s organized in small chunks that make it manageable, and sometimes I will simply point to the Glossary to help clients understand the concepts we discuss.
And where “Learn Accessibility” is focused on specific components of accessibility, I find that the Inclusive Design Principles site has a perfect presentation of the concepts and guiding principles of inclusion and accessibility on the web.
Meanwhile, I tend to sit beside a client to look at The A11Y Project. I pick a few resources to go through. Otherwise, the amount of information can be overwhelming. I like to offer this during a project’s planning phase because the site is focused on actionable strategies that help scope work.
User research that is specific to the client’s target audience is more convincing than general statistics alone. When possible, I try to understand those user’s needs, including what they expect, what sort of technology they use to browse online, and where they are geographically. Painting a more complete picture of users — based on real-life factors and information — offers a more human perspective and plants the first seeds of empathy in the design process.
Web analytics are great for identifying who users are and how they currently interact with the app. At the same time, they are also wrought with caveats as far as accuracy goes, depending on the tool you use and how you collect your data. That said, I use the information to support my user persona decisions and the specific requirements I write. Analytics add nice brush strokes to the picture but do not paint the entire view. So, leverage it!
The big caveat with web analytics? There’s no way to identify traffic that uses assistive tech. That’s a good thing in general as far as privacy goes, but it does mean that researching the usability of your site is best done with real users — as it is with any user research, really. The A11Y Project has excellent resources for testing screen readers, including a link to this Smashing Magazine article about manual accessibility testing by Eric Bailey as well as a vast archive of links pointing to other research.
That said, web analytics can still be very useful to help accommodate other impairments, for example, segmenting traffic by age (for improving accessibility for low vision) and geography (for improving performance gaps for those on low-powered devices). WebAIM also provides insights in a report they produced from a 2018 survey of users who report having low vision.
Chances are that your project will fall at least somewhat short of your accessibility plans. It happens! I see plenty of situations where a late deadline translates into rushed work that sacrifices quality for speed, and accessibility typically falls victim to degraded quality.
I keep track of these during the project’s various stages and attempt to document them. This way, there’s already a roadmap for inclusive and accessible improvements in subsequent releases. It’s scoped, backlogged, and ready to drop into a sprint.
For projects involving large sites with numerous accessibility issues, I emphasize that partial accessibility compliance is not the same as actual compliance. I often propose phased solutions, starting with incremental changes that fit within the current scope and budget.
And remember, just because something passes a WCAG success criterion doesn’t necessarily mean it is accessible. Passing tests is a good sign, but there will always be room for improvement.
Accessibility is a broad topic, and we can’t assume that everyone knows what constitutes an “accessible” interface. Often, when I get pushback from a colleague or client, it’s because they simply do not have the same context that I do. That’s why I like to keep a handful of answers to commonly asked questions in my back pocket. It’s amazing how answering the “basics” leads to productive discussions filled with substance rather than ones grounded in opinion.
When we say “web accessibility,” we’re generally talking about making online content available and usable for anyone with a disability, whether it’s a permanent impairment or a temporary one. It’s the practice of removing friction that excludes people from gaining access to content or from completing a task. That usually involves complying with a set of guidelines that are designed to remove those barriers.
The Web Content Accessibility Guidelines (WCAG) are created by a working group of the World Wide Web Consortium (W3C) called the Web Accessibility Initiative (WAI). The W3C develops guidelines and principles to help designers, developers, and authors like us create web experiences based on a common set of standards, including those for HTML, CSS, internationalization, privacy, security, and yes, accessibility, among many, many other areas. The WAI working group maintains the accessibility standards we call WCAG.
Twenty-seven percent of the U.S. population has a disability, emphasizing the widespread need for accessible web design. WCAG primarily focuses on three groups:
When we make web experiences that solve these issues based on established guidelines, we’re not only doing good for those who are directly impacted by impairment but those who may be impaired in less direct ways as well, such as establishing large target sizes for those tapping a touchscreen phone with their hands full, or using proper color contrast for those navigating a screen in bright sunlight. Everyone needs — and benefits from — accessibility!
The Americans with Disabilities Act (ADA) is regulated by the Civil Rights Division of the U.S. Department of Justice, which was established by the Civil Rights Act of 1957. Even though there is a lot of bureaucracy in that last sentence, it’s reassuring to know the U.S. government not only believes in web accessibility but enforces it as well.
Non-compliance can result in legal action, with first-time ADA violations leading to fines of up to $75,000, increasing to $150,000 for subsequent violations. The number of lawsuits for alleged ADA breaches has surged in recent years, with more than 4,500 lawsuits filed in 2023 against sites that fail to comply with WCAG AA 2.1 alone — roughly 500 more lawsuits than 2022!
Web accessibility is something we can test against. Many tools have been created to audit sites on the spot based on WCAG success criteria that specify accessible requirements. That would be a standards-based evaluation using WCAG as a reference point for auditing compliance.
WebAIM has an excellent page that compares different types of accessibility testing, reporting, and tooling. They are also quick to note that automated testing, while convenient, is not a comprehensive way to audit accessibility. Automated tools that scan websites may be able to pick up instances where mistakes in the HTML might contribute to accessibility issues and where color contrasts are insufficient. But they cannot replace or perfectly imitate a real-life person. Testing in real browsers with real people continues to be the most effective way to truly evaluate accessible web experiences.
This isn’t to say automated tools should not be part of an accessibility testing suite. In fact, they often highlight areas you may have overlooked. Even false positives are good in the sense that they force you to pause and look more closely at something. Some of the most widely used automated tools include the following:
These are just a few of the most frequent tools I use in my own testing, but there are many more, and the WAI maintains an extensive list of available tools that are worth considering. But again, remember that automated testing is not a one-to-one replacement for testing with real users.
Checklists can be handy for ensuring you are covering your bases:
When discussing accessibility, I find the most effective arguments are ones that are framed around the interests of clients and stakeholders. That way, the discussion stays within scope and helps everyone see that proper accessibility practices actually benefit business goals. Speaking in business terms is something I openly embrace because it typically supports my case.
The following are a few ways I would like to explain the positive impacts that accessibility has on business goals.
Sometimes, the most convincing approach is to offer examples of companies that have committed to accessible practices and come out better for it. And there are plenty of examples! I like to use case studies and reports in a similar industry or market for a more apples-to-apples comparison that stakeholders can identify with.
That said, there are great general cases involving widely respected companies and brands, including This American Life and Tesco, that demonstrate benefits such as increased organic search traffic, enhanced user engagement, and reduced site load times. For a comprehensive guide on framing these benefits, I refer to the W3C’s resource on building the business case for accessibility.
Let me share how focusing on accessibility can directly benefit your business. For instance, in 2005, Legal & General revamped their website with accessibility in mind and saw a substantial increase in organic search traffic exceeding 50%. This isn’t just about compliance; it’s about reaching a wider audience more effectively. By making your site more accessible, we can improve user engagement and potentially decrease load times, enhancing the overall user experience. This approach not only broadens your reach to include users with disabilities but also boosts your site’s performance in search rankings. In short, prioritizing accessibility aligns with your goal to increase online visibility and customer engagement.
The “curb-cut effect” refers to how features originally designed for accessibility end up benefiting a broader audience. This concept helps move the conversation away from limiting accessibility as an issue that only affects the minority.
Features like voice control, auto-complete, and auto-captions — initially created to enhance accessibility — have become widely used and appreciated by all users. This effect also includes situational impairments, like using a phone in bright sunlight or with one hand, expanding the scope of who benefits from accessible design. Big companies have found that investing in accessibility can spur innovation.
Let’s consider the ‘curb-cut effect’ in the context of your website. Originally, curb cuts were designed for wheelchair users, but they ended up being useful for everyone, from parents with strollers to travelers with suitcases. Similarly, many digital accessibility features we implement can enhance the experience for all your users, not just those with disabilities. For example, features like voice control and auto-complete were developed for accessibility but are now widely used by everyone. This isn’t just about inclusivity; it’s about creating a more versatile and user-friendly website. By incorporating these accessible features, we’re not only catering to a specific group but also improving the overall user experience, which can lead to increased engagement and satisfaction across your entire customer base.
I would like to highlight the SEO benefits that come with accessible best practices. Things like nicely structured sitemaps, a proper heading outline, image alt text, and unique link labels not only improve accessibility for humans but for search engines as well, giving search crawlers clear context about what is on the page. Stakeholders and clients care a lot about this stuff, and if they are able to come around on accessibility, then they’re effectively getting a two-for-one deal.
Focusing on accessibility can boost your website’s SEO. Accessible features, like clear link names and organized sitemaps, align closely with what search engines prioritize. Google even includes accessibility in its Lighthouse reporting. This means that by making your site more accessible, we’re also making it more visible and attractive to search engines. Moreover, accessible websites tend to have cleaner, more structured code. This not only improves website stability and loading times but also enhances how search engines understand and rank your content. Essentially, by improving accessibility, we’re also optimizing your site for better search engine performance, which can lead to increased traffic and higher search rankings.
Incorporating accessibility into web design can significantly elevate how users perceive a brand’s image. The ease of use that comes with accessibility not only reflects a brand’s commitment to inclusivity and social responsibility but also differentiates it in competitive markets. By prioritizing accessibility, brands can convey a personality that is thoughtful and inclusive, appealing to a broader, more diverse customer base.
Implementing web accessibility is more than just a compliance measure; it’s a powerful way to enhance your brand image. In the competitive landscape of e-commerce, having an accessible website sets your brand apart. It shows your commitment to inclusivity, reaching out to every potential customer, regardless of their abilities. This not only resonates with a diverse audience but also positions your brand as socially responsible and empathetic. In today’s market, where consumers increasingly value corporate responsibility, this can be a significant differentiator for your brand, helping to build a loyal customer base and enhance your overall brand reputation.
I mentioned earlier how developing accessibility enhances SEO like a two-for-one package. However, there are additional cost savings that come with implementing accessibility during the initial stages of web development rather than retrofitting it later. A proactive approach to accessibility saves on the potential high costs of auditing and redesigning an existing site and helps avoid expensive legal repercussions associated with non-compliance.
Retrofitting a website for accessibility can be quite expensive. Consider the costs of conducting an accessibility audit, followed by potentially extensive (and expensive) redesign and redevelopment work to rectify issues. These costs can significantly exceed the investment required to build accessibility into the website from the start. Additionally, by making your site accessible now, we can avoid the legal risks and potential fines associated with ADA non-compliance. Investing in accessibility early on is a cost-effective strategy that pays off in the long run, both financially and in terms of brand reputation. Besides, with the SEO benefits that we get from implementing accessibility, we’re saving lots of money and work that would otherwise be sunk into redevelopment.
Still getting pushback? There are certain arguments I hear time and again, and I have started keeping a collection of responses to them. In some cases, I have left placeholder instructions for tailoring the responses to your project.
“Our users don’t need it.”
Statistically, 27% of the U.S. population does have some form of disability that affects their web use. [Insert research on your client’s target audience, if applicable.] Besides permanent impairments, we should also take into account situational ones. For example, imagine one of your potential clients trying to access your site on a sunny golf course, struggling to see the screen due to glare, or someone in a noisy subway unable to hear audio content. Accessibility features like high contrast modes or captions can greatly enhance their experience. By incorporating accessibility, we’re not only catering to users with disabilities but also ensuring a seamless experience for anyone in less-than-ideal conditions. This approach ensures that no potential client is left out, aligning with the goal to reach and engage a wider audience.
“Our competitors aren’t doing it.”
It’s interesting that your competitors haven’t yet embraced accessibility, but this actually presents a unique opportunity for your brand. Proactively pursuing accessibility not only protects you from the same legal exposure your competitors face but also positions your brand as a leader in customer experience. By prioritizing accessibility when others are not, you’re differentiating your brand as more inclusive and user-friendly. This both appeals to a broader audience and showcases your brand’s commitment to social responsibility and innovation.
“We’ll do it later because it’s too expensive.”
I understand concerns about timing and costs. However, it’s important to note that integrating accessibility from the start is far more cost-effective than retrofitting it later. If accessibility is considered after development is complete, you will face additional expenses for auditing accessibility, followed by potentially extensive work involving a redesign and redevelopment. This process can be significantly more expensive than building in accessibility from the beginning. Furthermore, delaying accessibility can expose your business to legal risks. With the increasing number of lawsuits for non-compliance with accessibility standards, the cost of legal repercussions could far exceed the expense of implementing accessibility now. The financially prudent move is to work on accessibility now.
“We’ve never had complaints.”
It’s great to hear that you haven’t received complaints, but it’s important to consider that users who struggle to access your site might simply choose not to return rather than take the extra step to complain about it. This means you could potentially be missing out on a significant market segment. Additionally, when accessibility issues do lead to complaints, they can sometimes escalate into legal cases. Proactively addressing accessibility can help you tap into a wider audience and mitigate the risk of future lawsuits.
“It will affect the aesthetics of the site.”
Accessibility and visual appeal can coexist beautifully. I can show you examples of websites that are both compliant and visually stunning, demonstrating that accessibility can enhance rather than detract from a site’s design. Additionally, when we consider specific design features from an accessibility standpoint, we often find they actually improve the site’s overall usability and SEO, making the site more intuitive and user-friendly for everyone. Our goal is to blend aesthetics with functionality, creating an inclusive yet visually appealing online presence.
This section looks at frequent scenarios I’ve encountered in web projects where accessibility considerations come into play. Each situation requires carefully balancing the client’s needs/wants with accessibility standards. I’ll leave placeholder comments in the examples so you are able to address things that are specific to your project.
When clients request features they’ve seen online — like unfocusable carousels and complex auto-playing animations — it’s crucial to discuss them in terms that address accessibility concerns. In these situations, I acknowledge the appealing aspects of their inspirations but also highlight their accessibility limitations.
That’s a really neat feature, and I like it! That said, I think it’s important to consider how users interact with it. [Insert specific issues that you note, like carousels without pause buttons or complex animations.] My recommendation is to take the elements that work well &mdahs; [insert specific observation] — and adapt them into something more accessible, such as [Insert suggestion]. This way, we maintain the aesthetic appeal while ensuring the website is accessible and enjoyable for every visitor.
This is where we deal with things like non-descriptive page titles, link names, form labels, and color contrasts for a better “reading” experience.
Sometimes, clients want page titles to be drastically different than the link in the navigation bar. Usually, this is because they want a more detailed page title while keeping navigation links succinct.
I understand the need for descriptive and engaging page titles, but it’s also essential to maintain consistency with the navigation bar for accessibility. Here’s our recommendation to balance both needs:
- Keyword Consistency: You can certainly have a longer page title to provide more context, but it should include the same key terms as the navigation link. This ensures that users, especially those using screen readers to announce content, can easily understand when they have correctly navigated between pages.
- Succinct Titles With Descriptive Subtitles: Another approach is to keep the page title succinct, mirroring the navigation link, and then add a descriptive tagline or subtitle on the page itself. This way, the page maintains clear navigational consistency while providing detailed context in the subtitle. These approaches aim to align the user’s navigation experience with their expectations, ensuring clarity and accessibility.
A common issue with web content provided by clients is the use of non-descriptive calls to action with phrases and link labels, like “Read More” or “Click Here.” Generic terms can be confusing for users, particularly for those using screen readers, as they don’t provide context about what the link leads to or the nature of the content on the other end.
I’ve noticed some of the link labels say things like “Read More” or “Click Here” in the design. I would consider revising them because they could be more descriptive, especially for those relying on screen readers who have to put up with hearing the label announced time and again. We recommend labels that clearly indicate where the link leads. [Provide a specific example.] This approach makes links more informative and helps all users alike by telling them in advance what to expect when clicking a certain link. It enhances the overall user experience by providing clarity and context.
Proper form labels are a critical aspect of accessible web design. Labels should clearly indicate the purpose of each input field, whether it’s required, and the expected format of the information. This clarity is essential for all users, especially for those using screen readers or other assistive technologies. Plus, there are accessible approaches to pairing labels and inputs that developers ought to be familiar with.
It’s important that each form field is clearly labeled to inform users about the type of data expected. Additionally, indicating which fields are required and providing format guidelines can greatly enhance the user experience. [Provide a specific example from the client’s content, e.g., we can use ‘Phone (10 digits, no separators)’ for a phone number field to clearly indicate the format.] These labels not only aid in navigation and comprehension for all users but also ensure that the forms are accessible to those using assistive technologies. Well-labeled forms improve overall user engagement and reduce the likelihood of errors or confusion.
Clients will occasionally approach me with color palettes that produce too low of contrast when paired together. This happens when, for instance, on a website with a white background, a client wants to use their brand accent color for buttons, but that color simply blends into the background color, making it difficult to read. The solution is usually creating a slightly adjusted tint or shade that’s used specifically for digital interfaces — UI colors, if you will. Atul Varma’s “Accessible Color Palette Builder” is a great starting point, as is this UX Lift lander with alternatives.
We recommend expanding the brand palette with color values that work more effectively in web designs. By adjusting the tint or shade just a bit, we can achieve a higher level of contrast between colors when they are used together. Colors render differently depending on the device and screen they are on, and even though we might be using colors consistent with brand identity, those colors will still display differently to users. By adding colors that are specifically designed for web use, we can enhance the experience for our users while staying true to the brand’s essence.
Proactively suggesting features like sitemaps, pause buttons, and focus indicators is crucial. I’ll provide tips on how to effectively introduce these features to clients, emphasizing their importance and benefit.
Sitemaps play a crucial role in both accessibility and SEO, but clients sometimes hesitate to include them due to concerns about their visual appeal. The challenge is to demonstrate the value of site maps without compromising the site’s overall aesthetic.
I understand your concerns about the visual appeal of sitemaps. However, it’s important to consider their significant role in both accessibility and SEO. For users with screen readers, a sitemap greatly simplifies site navigation. From an SEO perspective, it acts like a directory, helping search engines effectively index all your pages, making your site more discoverable and user-friendly. To address the aesthetic aspect, let’s look at how major companies like Apple and Microsoft incorporate sitemaps. Their designs are minimal yet consistent with the site’s overall look and feel. [If applicable, show how a competitor is using sitemaps.] By incorporating a well-designed sitemap, we can improve user experience and search visibility without sacrificing the visual quality of your website.
Carousels are contentious design features. While some designers are against them and have legitimate reasons for it, I believe that with the right approach, they can be made accessible and effective. There are plenty of resources that provide guidance on creating accessible carousels.
When a client requests a home page carousel in a new site design, it’s worth considering alternative solutions that can avoid the common pitfalls of carousels, such as low click-through rates, increased load times, content being pushed below the fold, and potentially annoying auto-advancing features.
I see the appeal of using a carousel on your homepage, but there are a few considerations to keep in mind. Carousels often have low engagement rates and can slow down the site. They also tend to move key content below the fold, which might not be ideal for user engagement. An auto-advancing carousel can also be distracting for users. Instead, we could explore alternative design solutions that effectively convey your message without these drawbacks. [Insert recommendation, e.g., For instance, we could use a hero image or video with a strong call-to-action or a grid layout that showcases multiple important segments at once.] These alternatives can be more user-friendly and accessible while still achieving the visual and functional goals of a carousel.
If we decide to use a carousel, I make a point of discussing the necessary accessibility features with the client right from the start. Many clients aren’t aware that elements like pause buttons are crucial for making auto-advancing carousels accessible. To illustrate this, I’ll show them examples of accessible carousel designs that incorporate these features effectively.
Further Reading
Any animation that starts automatically, lasts more than five seconds, and is presented in parallel with other content, needs a pause button per WCAG Success Criterion 2.2.2. A common scenario is when clients want a full-screen video on their homepage without a pause button. It’s important to explain the necessity of pause buttons for meeting accessibility standards and ensuring user comfort without compromising the website’s aesthetics.
I understand your desire for a dynamic, engaging homepage with a full-screen video. However, it’s essential for accessibility purposes that any auto-playing animation that is longer than five seconds includes a pause button. This is not just about compliance; it’s about ensuring that all visitors, including those with disabilities, can comfortably use your site.
The good news is that pause buttons can be designed to be sleek and non-intrusive, complementing your site’s aesthetics rather than detracting from them. Think of it like the sound toggle buttons on videos. They’re there when you need them, but they don’t distract from the viewing experience. I can show you some examples of beautifully integrated pause buttons that maintain the immersive feel of the video while ensuring accessibility standards are met.
That’s it! This is my complete toolkit for discussing web accessibility with colleagues and clients at the start of new projects. It’s not always easy to make a case, which is why I try to appeal from different angles, using a multitude of resources and research to support my case. But with practice, care, and true partnership, it’s possible to not only influence the project but also make accessibility a first-class feature in the process.
Please use the resources, strategies, and talking points I have provided. I share them to help you make your case to your own colleagues and clients. Together, incrementally, we can take steps toward a more accessible web that is inclusive to all people.
And when in doubt, remember the core principles we covered:
Vanilla JavaScript, Libraries, And The Quest For Stateful DOM Rendering Vanilla JavaScript, Libraries, And The Quest For Stateful DOM Rendering Frederik Dohr 2024-02-22T18:00:00+00:00 2025-06-25T15:04:30+00:00 In his seminal piece “The Market For Lemons”, renowned web crank Alex Russell lays out the myriad failings of our industry, […]
Accessibility
2024-02-22T18:00:00+00:00
2025-06-25T15:04:30+00:00
In his seminal piece “The Market For Lemons”, renowned web crank Alex Russell lays out the myriad failings of our industry, focusing on the disastrous consequences for end users. This indignation is entirely appropriate according to the bylaws of our medium.
Frameworks factor highly in that equation, yet there can also be good reasons for front-end developers to choose a framework, or library for that matter: Dynamically updating web interfaces can be tricky in non-obvious ways. Let’s investigate by starting from the beginning and going back to the first principles.
Everything on the web starts with markup, i.e. HTML. Markup structures can roughly be divided into three categories:
For example, an article’s header might look like this:
<header>
<h1>«Hello World»</h1>
<small>«123» backlinks</small>
</header>
Variable parts are wrapped in «guillemets» here: “Hello World” is the respective title, which only changes between articles. The backlinks counter, however, might be continuously updated via client-side scripting; we’re ready to go viral in the blogosphere. Everything else remains identical across all our articles.
The article you’re reading now subsequently focuses on the third category: Content that needs to be updated at runtime.
Imagine we’re building a simple color browser: A little widget to explore a pre-defined set of named colors, presented as a list that pairs a color swatch with the corresponding color value. Users should be able to search colors names and toggle between hexadecimal color codes and Red, Blue, and Green (RGB) triplets. We can create an inert skeleton with just a little bit of HTML and CSS:
See the Pen [Color Browser (inert) [forked]](https://codepen.io/smashingmag/pen/RwdmbGd) by FND.
We’ve grudgingly decided to employ client-side rendering for the interactive version. For our purposes here, it doesn’t matter whether this widget constitutes a complete application or merely a self-contained island embedded within an otherwise static or server-generated HTML document.
Given our predilection for vanilla JavaScript (cf. first principles and all), we start with the browser’s built-in DOM APIs:
function renderPalette(colors) {
let items = [];
for(let color of colors) {
let item = document.createElement("li");
items.push(item);
let value = color.hex;
makeElement("input", {
parent: item,
type: "color",
value
});
makeElement("span", {
parent: item,
text: color.name
});
makeElement("code", {
parent: item,
text: value
});
}
let list = document.createElement("ul");
list.append(...items);
return list;
}
Note:
The above relies on a small utility function for more concise element creation:function makeElement(tag, { parent, children, text, ...attribs }) { let el = document.createElement(tag); if(text) { el.textContent = text; } for(let [name, value] of Object.entries(attribs)) { el.setAttribute(name, value); } if(children) { el.append(...children); } parent?.appendChild(el); return el; }You might also have noticed a stylistic inconsistency: Within the
itemsloop, newly created elements attach themselves to their container. Later on, we flip responsibilities, as thelistcontainer ingests child elements instead.
Voilà: renderPalette generates our list of colors. Let’s add a form for interactivity:
function renderControls() {
return makeElement("form", {
method: "dialog",
children: [
createField("search", "Search"),
createField("checkbox", "RGB")
]
});
}
The createField utility function encapsulates DOM structures required for input fields; it’s a little reusable markup component:
function createField(type, caption) {
let children = [
makeElement("span", { text: caption }),
makeElement("input", { type })
];
return makeElement("label", {
children: type === "checkbox" ? children.reverse() : children
});
}
Now, we just need to combine those pieces. Let’s wrap them in a custom element:
import { COLORS } from "./colors.js"; // an array of `{ name, hex, rgb }` objects
customElements.define("color-browser", class ColorBrowser extends HTMLElement {
colors = [...COLORS]; // local copy
connectedCallback() {
this.append(
renderControls(),
renderPalette(this.colors)
);
}
});
Henceforth, a <color-browser> element anywhere in our HTML will generate the entire user interface right there. (I like to think of it as a macro expanding in place.) This implementation is somewhat declarative1, with DOM structures being created by composing a variety of straightforward markup generators, clearly delineated components, if you will.
1 The most useful explanation of the differences between declarative and imperative programming I’ve come across focuses on readers. Unfortunately, that particular source escapes me, so I’m paraphrasing here: Declarative code portrays the what while imperative code describes the how. One consequence is that imperative code requires cognitive effort to sequentially step through the code’s instructions and build up a mental model of the respective result.
At this point, we’re merely recreating our inert skeleton; there’s no actual interactivity yet. Event handlers to the rescue:
class ColorBrowser extends HTMLElement {
colors = [...COLORS];
query = null;
rgb = false;
connectedCallback() {
this.append(renderControls(), renderPalette(this.colors));
this.addEventListener("input", this);
this.addEventListener("change", this);
}
handleEvent(ev) {
let el = ev.target;
switch(ev.type) {
case "change":
if(el.type === "checkbox") {
this.rgb = el.checked;
}
break;
case "input":
if(el.type === "search") {
this.query = el.value.toLowerCase();
}
break;
}
}
}
Note:
handleEventmeans we don’t have to worry about function binding. It also comes with various advantages. Other patterns are available.
Whenever a field changes, we update the corresponding instance variable (sometimes called one-way data binding). Alas, changing this internal state2 is not reflected anywhere in the UI so far.
2 In your browser’s developer console, check document.querySelector("color-browser").query after entering a search term.
Note that this event handler is tightly coupled to renderControls internals because it expects a checkbox and search field, respectively. Thus, any corresponding changes to renderControls — perhaps switching to radio buttons for color representations — now need to take into account this other piece of code: action at a distance! Expanding this component’s contract to include
field names could alleviate those concerns.
We’re now faced with a choice between:
Since we’ve already defined our markup composition in one place, let’s start with the second option. We’ll simply rerun our markup generators, feeding them the current state.
class ColorBrowser extends HTMLElement {
// [previous details omitted]
connectedCallback() {
this.#render();
this.addEventListener("input", this);
this.addEventListener("change", this);
}
handleEvent(ev) {
// [previous details omitted]
this.#render();
}
#render() {
this.replaceChildren();
this.append(renderControls(), renderPalette(this.colors));
}
}
We’ve moved all rendering logic into a dedicated method3, which we invoke not just once on startup but whenever the state changes.
3 You might want to avoid private properties, especially if others might conceivably build upon your implementation.
Next, we can turn colors into a getter to only return entries matching the corresponding state, i.e. the user’s search query:
class ColorBrowser extends HTMLElement {
query = null;
rgb = false;
// [previous details omitted]
get colors() {
let { query } = this;
if(!query) {
return [...COLORS];
}
return COLORS.filter(color => color.name.toLowerCase().includes(query));
}
}
Note:
I’m partial to the bouncer pattern.
Toggling color representations is left as an exercise for the reader. You might passthis.rgbintorenderPaletteand then populate<code>with eithercolor.hexorcolor.rgb, perhaps employing this utility:function formatRGB(value) { return value.split(","). map(num => num.toString().padStart(3, " ")). join(", "); }
This now produces interesting (annoying, really) behavior:
See the Pen [Color Browser (defective) [forked]](https://codepen.io/smashingmag/pen/YzgbKab) by FND.
Entering a query seems impossible as the input field loses focus after a change takes place, leaving the input field empty. However, entering an uncommon character (e.g. “v”) makes it clear that something is happening: The list of colors does indeed change.
The reason is that our current do-it-yourself (DIY) approach is quite crude: #render erases and recreates the DOM wholesale with each change. Discarding existing DOM nodes also resets the corresponding state, including form fields’ value, focus, and scroll position. That’s no good!
The previous section’s data-driven UI seemed like a nice idea: Markup structures are defined once and re-rendered at will, based on a data model cleanly representing the current state. Yet our component’s explicit state is clearly insufficient; we need to reconcile it with the browser’s implicit state while re-rendering.
Sure, we might attempt to make that implicit state explicit and incorporate it into our data model, like including a field’s value or checked properties. But that still leaves many things unaccounted for, including focus management, scroll position, and myriad details we probably haven’t even thought of (frequently, that means accessibility features). Before long, we’re effectively recreating the browser!
We might instead try to identify which parts of the UI need updating and leave the rest of the DOM untouched. Unfortunately, that’s far from trivial, which is where libraries like React came into play more than a decade ago: On the surface, they provided a more declarative way to define DOM structures4 (while also encouraging componentized composition, establishing a single source of truth for each individual UI pattern). Under the hood, such libraries introduced mechanisms5 to provide granular, incremental DOM updates instead of recreating DOM trees from scratch — both to avoid state conflicts and to improve performance6.
4 In this context, that essentially means writing something that looks like HTML, which, depending on your belief system, is either essential or revolting. The state of HTML templating was somewhat dire back then and remains subpar in some environments.
5 Nolan Lawson’s “Let’s learn how modern JavaScript frameworks work by building one” provides plenty of valuable insights on that topic. For even more details, lit-html’s developer documentation is worth studying.
6 We’ve since learned that some of those mechanisms are actually ruinously expensive.
The bottom line: If we want to encapsulate markup definitions and then derive our UI from a variable data model, we kinda have to rely on a third-party library for reconciliation.
At the other end of the spectrum, we might opt for surgical modifications. If we know what to target, our application code can reach into the DOM and modify only those parts that need updating.
Regrettably, though, that approach typically leads to calamitously tight coupling, with interrelated logic being spread all over the application while targeted routines inevitably violate components’ encapsulation. Things become even more complicated when we consider increasingly complex UI permutations (think edge cases, error reporting, and so on). Those are the very issues that the aforementioned libraries had hoped to eradicate.
In our color browser’s case, that would mean finding and hiding color entries that do not match the query, not to mention replacing the list with a substitute message if no matching entries remain. We’d also have to swap color representations in place. You can probably imagine how the resulting code would end up dissolving any separation of concerns, messing with elements that originally belonged exclusively to renderPalette.
class ColorBrowser extends HTMLElement {
// [previous details omitted]
handleEvent(ev) {
// [previous details omitted]
for(let item of this.#list.children) {
item.hidden = !item.textContent.toLowerCase().includes(this.query);
}
if(this.#list.children.filter(el => !el.hidden).length === 0) {
// inject substitute message
}
}
#render() {
// [previous details omitted]
this.#list = renderPalette(this.colors);
}
}
As a once wise man once said: That’s too much knowledge!
Things get even more perilous with form fields: Not only might we have to update a field’s specific state, but we would also need to know where to inject error messages. While reaching into renderPalette was bad enough, here we would have to pierce several layers: createField is a generic utility used by renderControls, which in turn is invoked by our top-level ColorBrowser.
If things get hairy even in this minimal example, imagine having a more complex application with even more layers and indirections. Keeping on top of all those interconnections becomes all but impossible. Such systems commonly devolve into a big ball of mud where nobody dares change anything for fear of inadvertently breaking stuff.
There appears to be a glaring omission in standardized browser APIs. Our preference for dependency-free vanilla JavaScript solutions is thwarted by the need to non-destructively update existing DOM structures. That’s assuming we value a declarative approach with inviolable encapsulation, otherwise known as “Modern Software Engineering: The Good Parts.”
As it currently stands, my personal opinion is that a small library like lit-html or Preact is often warranted, particularly when employed with replaceability in mind: A standardized API might still happen! Either way, adequate libraries have a light footprint and don’t typically present much of an encumbrance to end users, especially when combined with progressive enhancement.
I don’t wanna leave you hanging, though, so I’ve tricked our vanilla JavaScript implementation to mostly do what we expect it to:
See the Pen [Color Browser [forked]](https://codepen.io/smashingmag/pen/vYPwBro) by FND.
Web Development Is Getting Too Complex, And It May Be Our Fault Web Development Is Getting Too Complex, And It May Be Our Fault Juan Diego Rodríguez 2024-02-07T13:00:00+00:00 2025-06-25T15:04:30+00:00 Front-end development seemed simpler in the early 2000s, didn’t it? The standard website consisted mostly of […]
Accessibility
2024-02-07T13:00:00+00:00
2025-06-25T15:04:30+00:00
Front-end development seemed simpler in the early 2000s, didn’t it? The standard website consisted mostly of static pages made of HTML and CSS seasoned with a pinch of JavaScript and jQuery. I mean, who doesn’t miss the cross-browser compatibility days, right?
Fast forward to today, and it looks like a parallel universe is taking place with an overwhelming number of choices. Which framework should you use for a new project? Perhaps more established ones like React, Angular, Vue, Svelte, or maybe the hot new one that came out last month? Each framework comes with its unique ecosystem. You also need to decide whether to use TypeScript over vanilla JavaScript and choose how to approach server-side rendering (or static site generation) with meta-frameworks like Next, Nuxt, or Gatsby. And we can’t forget about unit and end-to-end testing if you want a bug-free web app. And we’ve barely scratched the surface of the front-end ecosystem!
But has it really gotten more complex to build websites? A lot of the frameworks and tooling we reach for today were originally crafted for massive projects. As a newcomer, it can be frightening to have so many to consider, almost creating a fear of missing out that we see exploited to sell courses and tutorials on the new hot framework that you “cannot work without.”
All this gives the impression that web development has gotten perhaps too complex. But maybe that is just an exaggeration? In this article, I want to explore those claims and find out if web development really is that complex and, most importantly, how we can prevent it from getting even more difficult than we already perceive it to be.
As someone who got into web development after 2010, I can’t testify to my own experience about how web development was from the late 1990s through the 2000s. However, even fifteen years ago, learning front-end development was infinitely simpler, at least to me. You could get a website started with static HTML pages, minimal CSS for styling, and a sprinkle of JavaScript (and perhaps a touch of jQuery) to add interactive features, from toggled sidebars to image carousels and other patterns. Not much else was expected from your average developer beyond that — everything else was considered “going the extra mile.” Of course, the awesome native CSS and JavaScript features we have today weren’t around back then, but they were also unnecessary for what was considered best practice in past years.
Large and dynamic web apps certainly existed back then — YouTube and Facebook, to name a couple — but they were developed by massive companies. No one was expected to re-create that sort of project on their own or even a small team. That would’ve been the exception rather than the norm.
I remember back then, tend to worry more about things like SEO and page optimization than how my IDE was configured, but only to the point of adding meta tags and keywords because best practices didn’t include minifying all your assets, three shaking your code, caching your site on edge CDNs, or rendering your content on the server (a problem created by modern frameworks along hydration). Other factors like accessibility, user experience, and responsive layouts were also largely overlooked in comparison to today’s standards. Now, they are deeply analyzed and used to boost Lighthouse scores and impress search engine algorithms.
The web and everything around it changed as more capabilities were added and more and more people grew to depend on it. We have created new solutions, new tools, new workflows, new features, and whatever else new that is needed to cater to a bigger web with even bigger needs.
The web has always had its problems in the past that were worthy of fixing: I absolutely don’t miss tables and float layouts, along with messy DOM manipulation. This post isn’t meant to throw shade on new advances while waxing nostalgic about the good days of the “old wild web.” At the same time, though, yesterday’s problems seem infinitely simpler than those we face today.
JavaScript frameworks, like Angular and React, were created by Google and Facebook, respectively, to be used in their own projects and satisfy the needs that only huge web-based companies like them have. Therein lies the main problem with web complexity: JavaScript frameworks were originally created to sustain giant projects rather than smaller ones. Many developers vastly underestimate the amount of time it takes to build a codebase that is reliable and maintainable with a JavaScript framework. However, the alternative of using vanilla JavaScript was worse, and jQuery was short for the task. Vanilla JavaScript was also unable to evolve quickly enough to match our development needs, which changed from simple informative websites to dynamic apps. So, many of us have quickly adopted frameworks to avoid directly mingling with JavaScript and its messy DOM manipulation.
Back-end development is a completely different topic, subject to its own complexities. I only want to focus on front-end development because that is the discipline that has perhaps overstepped its boundaries the most by bleeding into traditional back-end concerns.
It was only logical for JavaScript frameworks to grow in size over time. The web is a big place, and no one framework can cover everything. But they try, and the complexity, in turn, increases. A framework’s size seems to have a one-to-one correlation with its complexity.
But the core framework is just one piece of a web app. Several other technologies make up what’s known as a tech “stack,” and with the web gaining more users and frameworks catering to their needs, tech stacks are getting bigger and bigger. You may have seen popular stacks such as MEAN (MongoDB, Express, Angular, and Node) or its React (MERN) and Vue (MEVN) variants. These stacks are marketed as mature, test-proofed foundations suitable for any front-end project. That means the advertised size of a core framework is grossly underestimated because they rely on other micro-frameworks to ensure highly reliable architectures, as you can see in stackshare.io. Besides, there isn’t a one-size-fits-all stack; the best tool has always depended — and will continue to depend — on the needs and goals of your particular project.
This means that each new project likely requires a unique architecture to fulfill its requirements. Giant tech companies need colossal architectures across all their projects, and their stacks are highly engineered accordingly to secure scalability and maintenance. They also have massive customer bases, so maintaining a large codebase will be easier with more revenue, more engineers, and a clearer picture of the problem. To minimize waste, the tech stacks of smaller companies and projects can and should be minimized not only to match the scale of their needs but to the abilities of the developers on the team as well.
The idea that web development is getting too complex comes from buying into the belief that we all have the same needs and resources as giant enterprises.
“
Trying to imitate their mega stacks is pointless. Some might argue that it’s a sacrifice we have to make for future scalability and maintenance, but we should focus first on building great sites for the user without worrying about features users might need in the future. If what we are building is worth pursuing, it will reach the point where we need those giant architectures in good time. Cross that bridge when we get there. Otherwise, it’s not unlike wearing Shaquille O’Neal-sized sneakers in hopes of growing into them. They might not even last until then if it happens at all!
We must remember that the end-user experience is the focus at the end of the day, and users neither care about nor know what stack we use in our apps. What they care about is a good-looking, useful website where they can accomplish what they came for, not the technology we use to achieve it. This is how I’ve come to believe that web development is not getting more complex. It’s developers like us who are perpetuating it by buying into solutions for problems that do not need to be solved at a certain scale.
Let me be really clear: I am not saying that today’s web development is all bad. Indeed, we’ve realized a lot of great features, and many of them are thanks to JavaScript frameworks that have pushed for certain features. jQuery had that same influence on JavaScript for many, many years.
We can still create minimum viable products today with minimal resources. No, those might not make people smash the Like button on your social posts, but they meet the requirements, nothing more and nothing less. We want bigger! Faster! Cheaper! But we can’t have all three.
If anything, front-end development has gotten way easier thanks to modern features that solve age-old development issues, like the way CSS Flexbox and Grid have trivialized layouts that used to require complex hacks involving floats and tables. It’s the same deal with JavaScript gaining new ways to build interactions that used to take clever workarounds or obtuse code, such as having the Intersection Observer API to trivialize things like lazy loading (although HTML has gained its own features in that area, too).
We live in this tension between the ease of new platform features and the complexity of our stacks.
“
Each project, regardless of its simplicity, desperately needs a JavaScript framework. A project without a complex framework is like serving caviar on a paper plate.
At least, that’s what everyone seems to think. But is that actually true? I’d argue on the contrary. JavaScript frameworks are best used on bigger applications. If you’re working on a smaller project, a component-based framework will only complicate matters, making you split your website into a component hierarchy that amounts to overkill for small projects.
The idea of needing a framework for everything has been massively oversold. Maybe not directly, but you unconsciously get that feeling whenever a framework’s name pops in, as Edge engineer Alex Russell eloquently expresses in his article, “The Market For Lemons”:
“These technologies were initially pitched on the back of “better user experiences” but have utterly failed to deliver on that promise outside of the high-management-maturity organisations in which they were born. Transplanted into the wider web, these new stacks have proven to be expensive duds.”
— Alex Russell
Remember, the purpose of a framework is to simplify your life and save time. If the project you’re working on is smaller, the time you supposedly save is likely overshadowed by the time you spend either setting up the framework or making it work with the rest of the project. A framework can help make bigger web apps more interactive and dynamic, but there are times when a framework is a heavy-handed solution that actually breeds inefficient workflows and introduces technical debt.
Step back and think about this: Are HTML, CSS, and a touch of JavaScript enough to build your website or web application? If so, then stick with those. What I am afraid of is adding complexity for complexity’s sake and inadvertently raising the barrier to entry for those coming into web development. We can still accomplish so much with HTML and CSS alone, thanks again to many advances in the last decade. But we give the impression that they are unsuitable for today’s web consumption and need to be enhanced.
The perceived standard that teams must adopt framework-centered architectures puts a burden not only on the project itself but on a developer’s well-being, too. As mentioned earlier, most teams are unable to afford those architectures and only have a few developers to maintain them. If we undermine what can be achieved with HTML and CSS alone and set the expectations that any project — regardless of size — needs to have a bleeding edge stack, then the weight to meet those expectations falls on the developer’s shoulders, with the great responsibility of being proficient in all areas, from the server and database to front end, to design, to accessibility, to performance, to testing, and it doesn’t stop. It’s what has been driving “The Great Divide” in front-end development, which Chris Coyier explains like this:
“The divide is between people who self-identify as a (or have the job title of) front-end developer yet have divergent skill sets. On one side, an army of developers whose interests, responsibilities, and skillsets are heavily revolved around JavaScript. On the other, an army of developers whose interests, responsibilities, and skillsets are focused on other areas of the front end, like HTML, CSS, design, interaction, patterns, accessibility, and so on.”
— Chris Coyier
Under these expectations, developers who focus more on HTML, CSS, design, and accessibility rather than the latest technology will feel less valued in an industry that appears to praise those who are concerned with the stack. What exactly are we saying when we start dividing responsibilities in terms of “full-stack development” or absurd terms like “10x development”? A while back, Brad Frost began distinguishing these divisions as “front-of-the-front-end” and “back-of-the-front-end”.
Mandy Michael explains what impact the chase for “full-stack” has had on developers trying to keep up:
“The worst part about pushing the “know everything” mentality is that we end up creating an industry full of professionals suffering from burnout and mental illness. We have people speaking at conferences about well-being, imposter syndrome, and full-stack anxiety, yet despite that, we perpetuate this idea that people have to know everything and be amazing at it.”
— Mandy Michael
This isn’t the only symptom of adopting heavy-handed solutions for what “vanilla” HTML, CSS, and JavaScript already handle nicely. As the expectations for what we can do as front-end developers grow, the learning curve of front-end development grows as well. Again, we can’t learn and know everything in this vast discipline. But we tell ourselves we have to, and thanks to this mentality, it’s unfortunately common to witness developers who may be extremely proficient with a particular framework but actually know and understand little of the web platform itself, like HTML semantics and structure.

The fact that many budding developers tend to jump straight into frameworks at the expense of understanding the basics of HTML and CSS isn’t a new worry, as Rachel Andrew discussed back in 2019:
“That’s the real entry point here, and yes, in 2019, they are going to have to move on quickly to the tools and techniques that will make them employable, if that is their aim. However, those tools output HTML and CSS in the end. It is the bedrock of everything that we do, which makes the devaluing of those with real deep skills in those areas so much more baffling.”
— Rachel Andrew
And I want to clarify yet again that modern Javascript frameworks and libraries aren’t inherently bad; they just aren’t designed to replace the web platform and its standards. But we keep pushing them like we want them to!
“Vendor lock-in” happens when we depend too deeply on proprietary products and services to the extent that switching to other products and services becomes a nearly impossible task. This often occurs when cloud services from a particular company are deeply integrated into a project. It’s an issue, especially in cloud computing, since moving databases once they are set up is expensive and lengthy.
Vendor lock-in in web development has traditionally been restricted to the back end, like with cloud services such as AWS or Firebase; the front-end framework, meanwhile, was a completely separate concern. That said, I have noticed a recent trend where vendor lock-in is reaching into meta-frameworks, too. With the companies behind certain meta-frameworks offering hosting services for their own products, swapping hosts is increasingly harder to do (whether the lock-in is designed intentionally or not). Of course, companies and developers will be more likely to choose the hosting service of the company that made a particular framework used on their projects — they’re the experts! — but that only increases the project’s dependency on those vendors and their services.
A clear example is the relationship between Next and Vercel, the parent cloud service for Next. With the launch of Next 13, it has become increasingly harder to set up a Next project outside of Vercel, leading to projects like Open Next, which says right on its website that “[w]hile Vercel is great, it’s not a good option if all your infrastructure is on AWS. Hosting it in your AWS account makes it easy to integrate with your backend [sic]. And it’s a lot cheaper than Vercel.” Fortunately, the developers’ concerns have been heard, and Next 14 brings clarity on how to self-host Next on a Node server.
Another example is Gatsby and Gatsby Cloud. Gatsby has always offered helpful guides and alternative hosting recommendations, but since the launch of Gatsby Cloud in 2019, the main framework has been optimized so that using Gatsby and Gatsby Cloud together requires no additional hosting configurations. That’s fantastic if you adopt both, but it’s not so great if all you need is one or the other because integrating the framework with other hosts — and vice versa — is simply harder. It’s as if you are penalized for exercising choice.
And let’s not forget that no team expected Netlify to acquire Gatsby Cloud in February 2023. This is a prime case where the vendor lock-in problem hits everybody because converting from one site to another comes at a cost. Some teams were charged 120% more after converting from Gatsby Cloud to Netlify — even with the same plan they had with Gatsby Cloud!
What’s the solution? The common answer I hear is to stop using paid cloud services in favor of open-sourced alternatives. While that’s great and indeed a viable option for some projects, it fails to consider that an open-source project may not meet the requirements needed for a given app.
And even then, open-source software depends on the community of developers that maintain and update the codebase with little to no remuneration in exchange. Further, open source is equally prone to locking you into certain solutions that are designed to solve a deficiency with the software.
There are frameworks and libraries, of course, that are in no danger of being abandoned. React is a great example because it has an actively engaged community behind it. But you can’t have the same assurance with each new dependency you add to a project. We can’t simply keep installing more packages and components each time we spot a weak spot in the dependency chain, especially when a project is perfectly suited for a less complex architecture that properly leverages the web platform.
Choosing technology for your stack is an exercise of picking your own poison. Either choose a paid service and be subject to vendor lock-in in the future, or choose an open-source one and pray that the community continues to maintain it.
“
Those are virtually the only two choices. Many of the teams I know or have worked on depend on third-party services because they cannot afford to develop them on their own; that’s a luxury that only massive companies can afford. It’s a problem we have to undergo when starting a new project, but one we can minimize by reducing the number of dependencies and choosing wisely when we have to.
Why exactly have modern development stacks gotten so large and complex? We can point a finger at the “Development Paradox.” With each new framework or library, a new problem crops up, and time-starved developers spend months developing a new tool to solve that problem. And when there isn’t a problem, don’t worry — we will create one eventually. This is a feedback loop that creates amazing solutions and technologies but can lead to over-engineered websites if we don’t reign it in.
This reminds me of the famous quote:
“The plain fact is that if you don’t have a problem, you create one. If you don’t have a problem, you don’t feel that you are living.”
— U.G. Krishnamurti
Let’s look specifically at React. It was originally created by Facebook for Facebook to develop more dynamic features for users while improving Facebook’s developer experience.
Since React was open-sourced in 2013 (and nearly re-licensed in 2017, if it weren’t for the WordPress community), hundreds of new utilities have been created to address various React-specific problems. How do you start a React project? There’s Create React App and Vite. Do you need to enhance your state management? There is Redux, among other options. Need help creating forms? There is a React Hook Form. And perhaps the most important question: Do you need server-side rendering? There’s Next, Remix, or Gatsby for that. Each solution comes with its own caveats, and developers will create their own solutions for them.
It may be unfair to pick on React since it considers itself a library, not a framework. It’s inevitably prone to be extended by the community. Meanwhile, Angular and Vue are frameworks with their own community ecosystems. And this is the tip of the iceberg since there are many JavaScript frameworks in the wild, each with its own distinct ideology and dependencies.
Again, I don’t want you to get the wrong idea. I love that new technologies emerge and find it liberating to have so many options. But when building something as straightforward as a webpage or small website — which some have started referring to as “multi-page applications” — we have to draw a line that defines how many new technologies we use and how reliable they are. We’re quite literally mashing together third-party code written by various third-party developers. What could go wrong? Please don’t answer that.
Remember that our users don’t care what’s in our stacks. They only see the final product, so we can save ourselves from working on unnecessary architectures that aren’t appreciated outside of development circles. It may seem counterintuitive in the face of advancing technology, but knowing that the user doesn’t care about what goes behind the scenes and only sees the final product will significantly enhance our developer experience and free you from locked dependencies. Why fix something that isn’t broken?
We’ve covered several reasons why web development appears to be more complex today than in years past, but blaming developers for releasing new utilities isn’t an accurate portrayal of the real problem. After all, when developing a site, it’s not like we are forced to use each new technology that enters the market. In fact, many of us are often unaware of a particular library and only learn about it when developing a new feature. For example, if we want to add toast notifications to our web app, we will look for a library like react-toastify rather than some other way of building them because it “goes with” that specific library. It’s worth asking whether the app needs toast notifications at all if they introduce new dependencies.
Imagine you are developing an app that allows users to discover, review, and rate restaurants in their area. The app needs, at a bare minimum, information about each restaurant, a search tool to query them, and an account registration flow with authentication to securely access the account. It’s easy to make assumptions about what a future user might need in addition to these critical features. In many cases, a project ends up delayed because we add unnecessary features like SSR, notifications, offline mode, and fancy animations — sometimes before the app has even converted its first registered user!
I believe we can boil down the complexity problem to personal wishes and perceived needs rather than properly scoping a project based on user needs and experiences.
That level of scope creep can easily turn into an over-engineered product that will likely never see the light of launching.

What can we do to simplify our own projects? The following advice is relevant when you have control over your project, either because it’s a personal one, it’s a smaller one for a smaller team, or you have control over the decisions in whatever size organization you happen to be in.
The hardest and most important step is having a sense of detection when your codebase is getting unnecessarily complicated. I deem it the hardest step because there is no certainty of what the requirements are or what the user needs; we can only make assumptions. Some are obvious, like assuming the user will need a way to log into the app. Others might be unclear, like whether the app should have private messaging between users. Others are still far-fetched, like believing users need extremely low latency in an e-commerce page. Other features are in the “nice to have” territory.
That is regarding the user experience, but the same questions emerge on the development side:
These are valid questions that should be considered when developing a site, but they can distract us from our main focus: getting things done.
“Done is better than perfect.”
— Sheryl Sandberg
And, hey, even the largest and most sophisticated apps began as minimal offerings that iterated along the way.

We also ought to be asking ourselves what would happen if a particular feature or dependency isn’t added to the project. If the answer is “nothing,” then we should be shifting our attention to something else.
Another question worth asking: “Why are we choosing to add [X]?” Is it because that’s what is popular at the moment, or because it solves a problem affecting a core feature? Another aspect to take into consideration is how familiar we are with certain technologies and give preference to those we know and can start using them right away rather than having to stop and learn the ins and outs of a new framework.
Choose the right tool for the job, which is going to be the one that meets the requirements and fits your mental model. Focus less on a library’s popularity and scalability but rather on getting your app to the point where it needs to scale in the first place.
It’s incredibly difficult to not over-engineer web apps given current one-size-fits-all and fear-of-missing-out mentalities. But we can be more conscious of our project goals and exercise vigilance in guarding our work against scope creep. The same can be applied to the stack we use, making choices based on what is really needed rather than focusing purely on what everyone else is using for their particular work.
After reading the word “framework” exactly 48 times in this article, can we now say the web is getting too complex? It has been complex by nature since its origins, but complexity doesn’t translate to “over-engineered” web apps. The web isn’t intrinsically over-engineered, and we only have ourselves to blame for over-engineering our projects with overly-wrought solutions for perceived needs.
B2B website design with appropriate UX and UI can increase lead generation and support prospective customers at every stage of the purchase process. There are key characteristics of B2B websites and B2B customers as well as effective UX and UI design practices that can help […]
AccessibilityB2B website design with appropriate UX and UI can increase lead generation and support prospective customers at every stage of the purchase process.
There are key characteristics of B2B websites and B2B customers as well as effective UX and UI design practices that can help you convert new users into leads.
Nowadays, it’s extremely important to provide customers with more helpful and relevant shopping experiences. Brands have to get creative and find new, more meaningful ways to connect with consumers. To follow the latest 4 COVID-era trends and to further improve products and consumer experience, it makes sense to dive into the broad theme of what distinctive needs characterize B2B customers compared to B2C customers. Understanding these unique characteristics and the needs of your target audience is the key to the successful creation and implementation of the most relevant UX (user experience) and UI (user interface) web design decisions. Let’s start!

First of all, unlike most B2C customers, B2B clients often research potential purchase for several weeks. The reason is that B2B customers often involve multiple people in this process, from both the vendor’s company and their own.
B2B purchases are often big–ticket items or service contracts. The sites’ products and services are often extremely specialized, with complex specifications. Finally, decisions made on B2B websites can have long-term implications — after all, customers aren’t just making one-time purchases. They’re often buying into a long-term vendor relationship that includes support, follow-ups, and future enhancements and add-ons.
Research and multicriteria decision-making dominate the B2B user experience. B2B websites must provide a much wider range of information than what’s common in the B2C sector. A B2B website has to offer simple facts that can be easily and quickly understood by an early prospect who’s just looking around to see what’s available.
Creating a well-designed and informative B2B customer journey map can greatly enhance this process, providing a clear roadmap for engaging and converting prospects at each stage of their buying journey.
Another major difference is that B2C users typically buy for themselves. Therefore, they use a one-person decision process: a single user provides the budget and approval, researches the options, makes the decision, completes the purchase, receives the shipment, and uses the product. In contrast, in B2B, each of these steps might involve different people and different departments. That’s why among B2B salespeople there are widely used terms like “choosers” and “users”. Later, as companies and individuals send transactional emails, these become more personalized and precise.
But a B2B website must address many different types of users with various needs. That’s why this added complexity only strengthens the argument for B2B websites to emphasize usability in their UX design.
In the meantime, you should also take security measures such as regarding DDoS attacks, cyberattacks, etc.
It doesn’t matter whether you close the sale online or offline, supporting your target users’ purchase process is essential to converting prospects into paying customers. The key component in effective B2B marketing and sales is establishing credibility among prospective clients.
The nature of B2B products and services often demands long sales cycles that can take months or even years. Additionally, depending on the purchase phase, customers will have different needs. Therefore, B2B websites must consider all these variables, in order to:

Usually, B2B customers start with a company problem that needs solving, not with a product they’ll have to justify purchasing. Especially when this is a new challenge to their business, this initial research phase is all about seeking out common solutions and identifying the top vendors. Some buyers skip this step for industries or problems that they are already familiar with.
What a good B2B website design needs at this stage:
At this stage, users want to find lists of top vendors, learn more about the shortlisted companies, get a feel for them, call if necessary to fill in missing details, and refine research by getting answers to specific questions. Colleagues will often share options and collaborate to help put together a rubric or requirements for assessing the shortlisted companies.
What a good B2B website design needs at this stage:
This stage features a heavy collaboration with colleagues from multiple departments to narrow the list of companies and make a final decision. Many B2B customers create presentation materials for the leadership to explain their decision in order to be granted authorization.
What a good B2B website design needs at this stage:
Customers engage with sales representatives to negotiate a price or make an online purchase.
What a good B2B website design needs at this stage:
In the initial aftermath of the purchase, your customers will have higher support needs from your B2B website, ranging from technical support to questions about migrating from a competitor’s product to requesting adjustments.
What a good B2B website design needs at this stage:
Providing top-notch customer support is therefore essential in this stage. If you’re using email to do that, using an email verifier to ensure good deliverability might be a good idea.
At this stage, your customers will be looking to extend the life of their purchase as much as possible. For large mechanical equipment, this often means buying parts, accessories, or consumables; sometimes users will want to upgrade service contracts to accommodate company growth. For software, this can mean purchasing upgrades, modules, and other stopgap solutions to make an older product retain usefulness until the next major purchasing cycle.
What a good B2B website design needs at this stage:
The process starts again when a service contract ends or equipment reaches the end of its life.
What a good B2B website design needs at this stage:
Understanding the purchasing phases for B2B customers is extremely important when you plan to implement user-centered design processes (UCD) while working on a website project. At the same time, if you already have a website, you can instantly identify the stages where your users’ needs are poorly covered.
B2B customers are ruthlessly focused on just one thing: how you can solve their problems. Your prospects come to you because their business faces a challenge they cannot deal with on their own, due to the lack of time, resources, or skills. Whether your prospects just need to replace the toner in the office copier, or they look for a partner to help them develop and implement a business strategy, they want to solve a problem. That’s why you should remember to always emphasize these topics on your B2B website and prove you know these challenges inside–out with solutions included.
It’s also a great practice to consider the context of the buyer’s problem and describe your products or services in a way that precedes any questions a client might have. Don’t just say “our cartridges contain 0.8ml of ink”, but rather “with our product, you can print up to 600 pages”. Another great example is Apple’s genius approach to marketing and their famous “1,000 songs in your pocket slogan” — they could have said “5GB of storage”, but instead they’ve turned the information around to make it more relevant to an average customer while addressing the issue of limited space on a device.
Another angle is to consider how people form their queries on Google. Most of the time, they’re not looking for specific models of printers — they will search for solutions to their problems (“why does my printer have lines”) or search for models with specific, non–technical characteristics (“which printer has the cheapest inks”) which also suggests an issue (in this case, limited budget). That’s why it’s important to target all these questions in advance and always be one step ahead of the customer.
Customers need to know immediately whether your organization has the capability to solve their problems. Provide signals on your site to let people know you cater to them.
It is worth emphasizing your unique value proposition too. Determine which elements of your business approach are key differentiators, then advertise them on the homepage and other relevant site areas. In this case, the price can be a key factor, but you should also include:
Don’t forget to mention how you solved customer problems in the past. B2B prospects are seeking solutions to their challenges, and while a perfectly written copy might capture their attention, they will still demand proof.
Case studies, testimonials, reviews, and other ways of demonstrating success in past ventures are critical to turning skeptical website visitors into paying customers. For instance, you can offer reviews conducted by external, reputable sources or provide short and true-to-life case studies.
To summarize, demonstrating how you solve your prospect’s problems is a smart approach that can convince users to take specific actions and help you generate new leads on your B2B website.
Most B2B websites don’t sell to prospects immediately upon their first visit. With a long sales cycle, B2B websites have to be able to provide valuable information to prospects on a recurring basis in order to close the sale. In fact, the sites that provide the most helpful information to prospects are ones that they return to over and over again as they near the purchasing phase of the sales cycle. This recurring engagement is a crucial part of the customer success process, ensuring that businesses build strong relationships with their clients and guide them through the sales journey effectively.
Providing business value for customers and showcasing valuable content for them is one of digital marketing’s main tasks. There’s lots of talk these days about content strategy (which should be supported by content marketing) and its value for B2B websites.
Content is generated on a recurring basis to both build SEO (Search Engine Optimization) value and to draw returning visitors to your website. Content strategy is only valuable if it helps your prospects understand the business challenges that you solve, and why your expertise helps them.
Focus your efforts on describing common challenges your prospects face and how your company solves these issues. Remember when writing the content that many of your best prospects may have no idea who you are, but if you have a blog post that offers a simple breakdown of their problem, they’re more likely to revisit your website and put you on their shortlist. Providing useful resources differentiates you from your competitors by establishing your organization as having expertise and credibility — qualities every organization seeks.
Considering all of the above, you can use such types of resources as:
So to increase organic search traffic and lead generation on your B2B website, you should optimize the content on the entire site not only for search engines but also for your specific target audience.
A first impression can make or break potential transactions. People judge the company’s competence by the way the website looks. An organized and coherent website instills trust and proves competence. UI designers should keep in mind the “less is more” concept — cluttered design and bad information architecture will only lead to confusion. That’s why in the design process, this concept helps to prioritize user interface (UI) elements and, accordingly, reduce the number of unnecessary elements on each page layout.
Also, people have different expectations for what websites should look like depending on the industry. For example, people expect a website in creative industries to reflect a company’s philosophy. Technology companies aren’t held up to the same aesthetic standards as design agencies. More emphasis is placed on clean designs that express professionalism and expertise.
On the other hand, your UI design impacts the audience’s perception of your organization. In a split second, users interact with an interface and decide whether the website is worth their effort. When there’s a mismatch between a site’s user interface design and the company’s business image, people assume that the organization doesn’t have what they want and go elsewhere. UI design also serves another important purpose: people can instantly identify whether they’re on the right web page.
Every UI or web designer should remember that a B2B website design isn’t about a lifestyle brand, it needs to convey professional expertise and competence. Carefully consider whether trendy design patterns and visual styles support a message of stability and reliability — especially since many design trends come and go. Pay attention to core design principles and visual guidelines that help users understand your website: visual hierarchy, negative space and balance, and element affordance.
No matter where your organization falls on the creativity spectrum, it’s important to have a simple interaction design. Simple interaction models match people’s mental models by behaving in expected ways. Business customers need websites to streamline their processes, answering their questions quickly and easily. Although creative designs can be delightful, simplicity must come first.
Make your UI design more user-friendly and provide subtle cues. Even when users think a website has what they want, scrolling takes effort, and they typically do it only if they see the proper visual cues. How you place critical elements on the web page can dictate whether people scroll or not. Placing indicators such as headers or content that peeks out into the display’s viewable area suggests that there’s more content below.
Make sure that your site loads quickly. If it takes more than six seconds to load, the users abandon the site. To avoid that, remove unnecessary elements and media that negatively impact page speed. Buggy or unstable elements that take too long to load reduce the user experience and prospect’s impression of your organization. Optimize file sizes and minimize loading time, especially when designing for business audiences.
Also, make sure you pick the best web hosting provider.
Use a reasoned, neutral voice on your website. Avoid excessive marketing-speak and meaningless sales phrases. Business customers prefer a straightforward tone that describes the company’s business without hyperbole. Easy access to information and even-handed comparison of products or services make participants feel like the company has nothing to hide.
Write and present content in a way that optimizes scanning, for example by using such elements as headings, subheadings, large type, bold text, highlighted text, bulleted lists, graphics, and captions. Write text that is short and to the point. Don’t overload people with too much text; that can feel overwhelming and intimidating. Instead, use concise and simple language, as well as break up large blocks of information into short paragraphs.
Offer the About Us section regardless of your company’s size. Sometimes small and medium-sized businesses neglect to have an About Us section on their website, thinking it’s not important.
Surprise — it is. According to B2B Web Usability Report from 2015, 52% of respondents indicated that they want to see the About Us section on the vendor website home page. Only two other pages — Contact and Products & Services — got higher results (64% and 86%, respectively).
The About Us page is particularly important to companies whose brand is not widely recognized. On the other hand, household names can afford to neglect this section.
Users prefer consistent navigational structures, especially in business situations where time is scarce. Consistent navigation helps users visualize their current location in site structure and identify alternative options, making it easier to find information and keep track of where they are. Make sure that links in header and footer navigation are named and grouped correctly both on desktop and mobile devices.
Whether you use all of these practices or just a few, remember to keep in mind that you create a B2B website design for your target audience. If you don’t know the specific problems and needs of your target audience, you should run user research first, or else you’ll totally misjudge your prospects and give the wrong impression.
If you’d like to learn more about shaping your content towards a specific audience and how to generate leads, read this article on Customer Acquisition Strategy. Without that knowledge, even all those tips on UX/UI design won’t save you from lack of engagement.
So keep all that in mind and design away!
Agile was founded based on values and principles. It’s not a methodology or a philosophy to get things done but rather a framework, and a collection of beliefs teams use to make decisions. The Agile principles will help you guide your team on the right […]
AccessibilityAgile was founded based on values and principles. It’s not a methodology or a philosophy to get things done but rather a framework, and a collection of beliefs teams use to make decisions.
The Agile principles will help you guide your team on the right path, even when you’re unsure of your next step. In this article, we will explain the 12 Agile principles and how these help software teams adapt, optimize, and improve the development of software products or services.

Agile refers to methodologies focused on iterative development where processes and solutions occur through continual collaboration among cross-functional teams.
Instead of following a well-defined and strict plan, Agile teams focus on continual improvement and efficiency. They work under “sprints,” which consist of specific tasks or deliverables boxed in a time frame. Each sprint typically lasts from two to four weeks, but this depends on the product in development. What’s worth noting is that sprints are not used in every single Agile approach. Kanban, for example, doesn’t use it.
In software development, Agile transformed entirely the way teams structured processes. Before Agile, software development life cycles like Waterfall focused on delivering software through a linear and rigid process.
With Agile, there’s no set of rules, procedures, or hierarchy that needs to be followed. The Agile software development life cycle (SDLC) focuses on breaking the process into manageable actions that can be continually improved until it reaches its primary goal. What matters is to deliver the best result possible.
A group of 17 engineers created Agile, focusing on building an efficient foundation to manage projects. However, since its inception, Agile has been more than a series of methodologies.
With 4 core values and 12 principles, Agile has become a globally accepted mindset for managing projects.
The Agile manifesto has 4 values and the 12 supporting principles that lead the Agile approach to software development.
1. Individuals and Interactions Over Processes and Tools
You can have high-tech tools and solid processes, but it’s the team that determines a project’s success. This value focuses on the importance of having teams with fluid communication who can respond to changes and customer needs. No matter if your team uses Slack, Microsoft Teams, or a virtual phone system, you simply must communicate clearly to work well.
2. Working Software Over Comprehensive Documentation
One of the reasons software development was slower and ineffective was due to all the technical specifications, requirements, documents, extensive planning, etc. Some Agile requirements are presented as a user story, which helps speed up the process. Documentation is still valuable, but working software is even more valuable in Agile.
3. Customer Collaboration Over Contract Negotiation
Agile aims to have customers engaged and who collaborate throughout the development process. Instead of having a negotiation period to outline all project details, it focuses on having a collaborative relationship from the start resulting in customers being heavily involved in the process. This makes it easy for Agile teams to quickly implement the customer’s feedback, understanding their needs and requirements.
4. Responding to Change Over Following a Plan
What characterizes Agile is that it embraces change. Instead of having a very strict and specific plan of development, the project should focus on delivering value. The definition of what value means for the project will vary, along with the project scope.

What are the 12 principles of Agile?
The 12 Agile Manifesto Principles are designed to help teams focus on what’s important, such as efficiently delivering valuable software, embracing change, working collaboratively, and prioritizing the customer’s needs, among other things.
These are the 12 principles of Agile explained:
Understanding customers’ changing expectations is one of the priorities in Agile teams. Instead of having a linear structure, where they engage with customers only at the start and end of the project, Agile emphasizes the importance of having a continuous cycle of feedback and improvement.
Agile understands that a customer’s needs might change or evolve, so instead of focusing on a rigid plan, teams focus on a series of iterations followed by customer feedback. This way, it’s easier for the product to be aligned with customer expectations and allows the team to focus only on valuable features.
Example:
As this principle focuses on the continuous feedback cycle, Agile teams often build a minimum viable product (MVP), and its response informs future releases. Product teams can test and validate their ideas by using MVP and experimentations. Teams do not release a final product, but iterations continue to make improvements until the product has reached a certain level of satisfaction.
One of the main characteristics of an Agile project is its adaptability. This second principle means that teams need to be willing to make changes to stay competitive even when the project is advanced.
Often, software teams think that the most reliable way to achieve a successful product is to make a solid plan and stick to it. But for Agile, it’s the other way around. Allowing change is necessary for teams to gain a competitive advantage.
Agile teams embrace change and are continually reconsidering their strategies and processes to ensure the quality of the product.
Adaptation and the willingness to change are part of Agile’s core strengths. Allowing change becomes necessary for teams to gain a competitive advantage.
A good way for strengthening your adaptation skills though may be taking part in agile project management training online. Especially, if you haven’t worked in the Agile methodology just yet. Learning directly from experts can particularly speed up the whole process.
Example:
Instead of prioritizing having well-documented plans, the Agile team focuses on observing the market, the customer needs, studying them in-depth, and being aware of the competitive threats they might face along the way.
As mentioned, for Agile, the clients’ and stakeholders’ feedback is fundamental. Instead of waiting to build a final product to present it, Agile focuses on delivering work frequently.
This means that Agile teams work with “sprints” where tasks and goals are usually planned in the short term.
Sprints allow customers to see how the product is evolving and for the team to evaluate if there are improvements to be made. The idea is to achieve goals on smaller scales that will ultimately contribute to the product as a whole. Teams are aware of the specific goals they need to reach while adapting and changing the product until it fulfills the customer’s expectations.
Example:
Software development teams work in sprints with a set timeframe between 2 and 4 weeks.
The fourth Agile principle focuses on unifying departments, prioritizing collaboration regularly. The idea is that customers, key stakeholders, and leadership work hand in hand with developers, strengthening the communication channels to ensure everyone is on the same page.
During the development of a product, business and tech groups work together consistently, building trust and transparency throughout the process. It also helps give immediate feedback to developers making sure that new arising requirements and details for existing ones are taken into consideration.
While, for some teams who haven’t applied Agile, having everyone involved through all the stages might seem like it will cost more time, in the long term, it’s more beneficial because it optimizes processes. It helps teams recognize gaps between business and tech teams early enough to avoid future problems.
Transparency while delivering a product is crucial on both sides. Businesses should be aware of development status and blockers as much as developers need to be aware of all market/business or organizational restraints of the project.
Example:
Agile teams prioritize regular meetings. For instance, every day, they have a daily meeting that takes only 15 minutes, and each member of the group shares what they are currently working on and if they have had any roadblocks.
Usually, at the start of the project, where the planning and first steps take place, the team is motivated and ready to get started. However, it is harder for individuals to stay motivated and focused on the final goal when problems arise.
Agile principle 5 emphasizes the importance of choosing the right people with the right skills and roles to be part of the project to achieve success. And it also encourages team leaders to give them the necessary tools and resources.
Motivating team members is also about listening to their ideas and showing that it’s important. Giving team members the confidence to speak up is also a way to help them improve their performance.
This principle also focuses on trust, which translates into avoiding micromanagement. A key aspect of the Agile framework is to empower team members through trust and autonomy.
Example:
Team leaders need to ensure that developers understand strategy and requirements before development starts. Not necessarily focusing on how something will be built, but more on the “what” and “why”. The delivery team is who determines the “how” through the process.
The goal is to provide support when roadblocks appear and brainstorm on possible solutions through the sprints, not micromanaging.
The sixth Agile principle translates primarily into two things: Communication and collaboration. The most effective way for teams to be on the same page is to communicate continually.
While this principle focuses on the face-to-face aspects, something to keep in mind is that it was written two decades ago, when Zoom and other remote tools weren’t part of the panorama.
In today’s world, applying this principle is not for face-to-face exclusively, but it highlights the importance of meaningful connections and conversations. While email and texting are fast and easier alternatives, video calls, and even regular phone calls are the best channels for remote teams to communicate effectively.
Example:
This principle is applied in software teams through daily meetings, brainstorming sessions, sprint planning meetings, frequent demos, and pair programming.
To understand this principle, let’s rewind to pre-Agile times to understand how teams used to measure success.
As mentioned, in many cases, software development was a hierarchical and linear process. This meant that teams, instead of working through iterations, left most of the testing and refactoring to the final stage. In the end, this left unhappy customers and many problems to review and improve, and that took time.
Agile focuses on maintaining a working software, measuring the progress of what has been completed. Each feature and addition is reviewed by the tech team and the client. So when it’s time to work on the next steps, the client is happy, and revisions and testing have already taken place.
Working software is not the final product, but it refers to each iteration. Agile teams work on Minimum Viable Features. That way, they measure success by delivering a working product that satisfies customers.
Example:
Software teams design and release Minimum Viable Features instead of fully-fledged features to get feedback and validate the product while building software. This makes agile teams have the capacity to adapt to change and gain a competitive advantage, as explained in the previous principles.
The key concept in this principle is “sustainable development.” What Agile means by this is that project managers and leaders should set realistic and clear expectations, even if that means that a project will take longer than expected.
In some cases, software development teams set high expectations trying to fulfill all requirements in a short period. And the problem is that putting in extra time to meet deadlines quickly burns out the team, impacting the quality of the outcome, morale, and motivation.
The idea is to strengthen morale by encouraging a healthy work-life balance with realistic goals. It’s not about finishing projects fast, but about making them at a constant rate.
Example:
Before every sprint takes place, teams need to consider the amount of work they can commit to. Instead of overpromising and not fulfilling expectations, teams should set realistic goals without adding more tasks through the process. Once a sprint starts, teams stick to the goals and tasks they have already established.
This principle focuses on constantly reviewing the product after every iteration. Agile promotes continuous attention to technical excellence and good quality design.
The purpose of this principle is to encourage teams to avoid shortcuts just because they want to finish a project faster. Most of the time, shortcuts become more costly in the long run.
Example:
Developers and the product management team work hand in hand to understand if the technical debt is acceptable. Usually, they will need to allocate development resources to refactoring efforts.
This Agile principle focuses on keeping processes as simple as possible. In other words, it talks about working smart, not hard.
Agile teams recognize what adds value to a project and what doesn’t, which enables them to maximize the resources that best serve their project. Too many features and planning are avoided at all costs. The idea is to avoid distractions and streamline the cycle to make it more efficient.
For Agile, simplifying and focusing on the things that truly matter is what has the most impact. In a product management context, leaders should always be focused on prioritizing, even if that means making difficult decisions.
Example:
Product managers are strongly aligned with organizational goals, and the customer wants and needs. This makes them selective in the user stories and features they pick. With prioritization techniques, they ensure that the strategies they implement always have a purpose and a “why” behind them.
Self-organizing teams are made up of a committed and motivated group able to plan, estimate and complete the work autonomously while engaging with the customers. This also breaks down the traditional vertical management style.
This Agile principle focuses on self-organizing teams that work under a more flat and horizontal management style. This translates into autonomous teams capable of acting faster, as they don’t need permission for every decision they make.
Example:
In practice, Agile teams are autonomous groups in an organization that have full control over their projects and take ownership in such areas.
This last Agile principle encourages leaders to take time to evaluate what the team has done, how they’ve performed, and how they can improve.
Agile focuses on delivering products through continual improvement, always considering feedback. Similar to this process, teams need to frequently evaluate their process and see ways to make it more efficient.
Example:
The idea behind this principle is to have sessions where the team reflects on their performance and discuss ways management and technical skills can be improved.
Agile Principles focus on providing guidelines to ensure teams focus on the right things. These are the 12 Agile Principles, explained in simpler terms:
1. Customer satisfaction through early and continuous delivery of software.
2. Focus on working on smaller and achievable tasks.
3. Adhere to a timeframe for the delivery of a working product.
4. Stakeholders need to frequently collaborate throughout the entire development process to ensure the project moves in the right direction.
5. Create a supportive environment that motivates team members.
6. Constant communication is key to a project’s success.
7. Progress is measured by working software.
8. Maintain a constant and realistic pace of development.
9. Always keep an eye out for technical details.
10. Simplicity is key.
11. Promote self-organization.
12. Reflect on the team’s performance to continue improving.
Thousands of organizations across the world claim to be Agile. However, as explained in the article, Agile is not a methodology or a philosophy; it is a framework.
Understanding the values and the principles of Agile provides teams with a foundation to make the right decisions, create quality software, and solid cross-functional teams.
In fact, it’s projected that in 2022 the mobile app revenue worldwide will reach $808.7 billion, and in 2023 it’ll reach the astonishing number of $935.2 billion. Compared to 2014, the revenue difference would be $837.5 billion. Quite impressive, isn’t it? There’s also a wide choice […]
AccessibilityIn fact, it’s projected that in 2022 the mobile app revenue worldwide will reach $808.7 billion, and in 2023 it’ll reach the astonishing number of $935.2 billion. Compared to 2014, the revenue difference would be $837.5 billion. Quite impressive, isn’t it?
There’s also a wide choice of available options when it comes to the development of web or mobile applications. What’s the difference though? Do they actually differ, even if they look the same? In this article, we’ll cover all sorts of information about web apps, mobile apps, and how they’re built. What’s more, we’ll try to resolve the web app vs mobile app clash once and for all!

Have you ever been confused about what a web app and a mobile app are? After all, they look very similar, right? The devil is in the details, so to speak.
Web apps and mobile apps, although they share some similarities to each other, they’re two different types of applications. At first glance, you may notice very few differences between the two as they almost look entirely the same. Design, custom logos, color scheme, functions, icons, they’re probably placed in the same spots. To bring these components to life, the use of cutting-edge AI tools can be of great assistance.
But don’t let this fool you, these two applications are even made differently. One classifies as a web application, and the other is a native mobile app.
The core difference is that native mobile apps are dedicated applications for specific mobile platforms, i.e. Android or iOS, whereas web apps can be accessed through different internet browsers on a computer or on a mobile device.
A great example of how a native app looks compared to a web application would be Uber Eats. You can access it through your mobile device by downloading an application or by accessing the website through your phone’s browser. They will look similar but will be different.
One more noticeable difference between a mobile and a web application would be the ability of native mobile apps to work offline, to a limited extent of course.
Native apps are built from scratch for the mentioned platforms. Users can download them through either App Store or Google Play. That fact alone increases the safety of the app. They require updates that can be done manually or automatically, depending on your preferences. That’s not the case with web apps though, as they are updated by the creators, whenever an update is ready, and it doesn’t take as much time as for the mobile apps.
Coming back to native apps, if you’d like to release an application with paid services for – let’s say – iOS, you’d have to pay a large fee to Apple for every made transaction.
Before proceeding to the actual building process, it’d be wise to plan your strategy ahead. What we mean is that you could follow one of the software development lifecycle models that would make the development and entire process easier and less complicated, as you would have every step planned and written down.
What’s more, think about your team, what roles would you need for your project. Two roles that you’d definitely need would be a web developer and web designer.
Mobile apps are a much faster solution than a typical web application when it comes to performance. Let’s focus on the latter for now. What differentiates a native app from a web app besides the platform? Well, a number of functionalities or time spent on the creation. Your typical programming language or syntaxes for web apps would be either JavaScript, HTML, or CSS. With the help of CMS (like WordPress, Drupal, or Umbraco), devs can build them at a much faster rate.
Things are a little bit different for mobile apps. With more functionalities, native apps have to be developed in a specific programming language with the help of IDE – Integrated Development Environments (though IDEs are not limited to native apps). Additionally, the chosen programming language depends on the target device. For example, if you want to create an application for iOS, you would have to use Swift or Objective-C language. The same situation happens for IDE, as the default for creating apps for iOS would be Xcode. On the contrary to web apps, native mobile apps can be created with SDK – software development kits that are provided by Google and Apple. They can make the mobile app development much better and easier.
How about devices that run on Android? Well, in this case, you’d probably use Java or Kotlin programming languages along with Eclipse IDE or Android Studio software development kits.
There’s also HarmonyOS that’s worth mentioning but it’s much less popular than iOS or Android. So what languages would you use for creating Harmony apps for Huawei? The answer is either C, C++, Java, JavaScript, or Kotlin.
What should you do in a situation where you want to release the native app on multiple platforms? In this particular case, the best solution would be to use one of the cross-platform languages, like Flutter. By doing so you can develop a hybrid app that will land on every mobile platform.
To do so, you can use either React Native, Xamarin, or Cordova.

Examples of native apps: Spotify, Pokemon Go, WhatsApp

Examples of web apps: LinkedIn, Yahoo.
There’s a common ground though, and it’s called progressive web apps. Is it a good solution? Let’s find out.
A progressive web app (PWA) is a web application that combines features of both native mobile apps and web apps. What exactly? For starters, the ability of mobile apps to work offline. Even though it’s still a web application, it features something called Application Cache that allows it to work without an internet connection. Similar to web apps, they cannot be downloaded but accessed through an internet browser. Though they still can be added to the home screen.
Many programmers additionally use web frameworks like Angular or React to help them build their applications.
PWAs philosophy is based on three core pillars, they have to be:

Examples of PWAs: Starbucks, Trivago, The Washington Post.
Hybrid mobile apps may seem similar to PWAs, but they’re definitely not the same. Hybrid apps are a mix of both native and web apps, but they can be downloaded from the app store on either Android or iOS.
It’s a great option for those who wish to try out their idea before investing a lot of money. By developing the MVP release, you can see how your app is doing, take suggestions or release fixes.

Examples of hybrid apps: Instagram, Gmail, Twitter.
Are you perhaps stuck on deciding whether it’s better to create a web app, PWA, or a mobile app? Check out these facts that may help you make the choice!
As we mentioned before in this article, the number of mobile users grows year by year, month after month, and day by day. In fact, there are more mobile phone users than ones using desktops.
But what factors should you take into consideration when choosing one of the two options?
If you’d like to start with a mobile app then you better have your wallet at hand. Developing a mobile app instead of a web app requires a higher budget. Additionally, if you’d like to release the application on iOS and Android simultaneously, that will cost extra, both in terms of money and time.
Bottom line is that developing a website application or PWA first is a cheaper option (that of course depends on your idea and goal).
When it comes to speed, web applications lose (though the difference is minimal). Even though PWAs are still faster than web apps, native apps win the race because they’re launched directly from your device.
There’s a downside to it though. In order to access the mobile app, you have to download it first, whereas to access a website app you only need to type in the address and wait for it to load. For PWAs you don’t even have to launch your browser (with the exception of the first time). You can pin the shortcut to your home screen and access it from there.
Another advantage in favor of a mobile app is the ability to work offline, though probably with limited functions.
A well-written website application should work just fine on every platform, whether it’s Windows, Linux, macOS, Android, or iOS. On the other hand, even a well-written native app can work only on one platform. If you’d like it to work on a different one, you’d have to develop a new code from scratch. Definitely a downside of mobile apps.
Since the start of the SARS-CoV-2 pandemic, our lives have changed drastically. Many of us had to give up on social interactions for the time being. Plenty of employees have been sent to work from home and it’s not the only thing that has changed.
People started using their smartphones or mobile devices even more than they used to. The actual amount of hours spent on mobile apps by an average person is 4.2 hours daily which is a 30% increase compared to 2019. That’s more than half of a typical day of work.
The reason for bringing this up is that the web itself is less browsed by the users, but applications are on the top right now.
Unlike mobile apps, web apps can be easily found on the internet due to the fact that they can be indexed by search engines. In order to have your app rank high when it comes to downloads and ratings, take proper screenshots showcasing the design and functionalities of your app. Without such actions, it would be much harder to find the application in the app store, compared to the website.
Before allocating your budget to either mobile or web applications, think about your target audience. Do you want to develop a business web application for your company? Or perhaps you wish to create a social media platform that could potentially gather people with similar interests? Or maybe you want to start a pet store and develop an e-commerce website for it?
If the former is the case, then creating a web application would be a wiser choice. If your idea is more like the latter, then only the sky’s the limit.
It’s time to summarize all the things we learned about native, web, hybrid, and progressive web apps so far.
As we mentioned before, your go-to app should be chosen based on your idea and target.

Everyone heard about Starbucks. It’s one of the most popular coffee shops in the world. Let’s jump right into the time machine and head back to the year 2009.
You can hear Flo Rida’s or Pitbull’s songs all around, David Guetta is just becoming popular, and Starbucks just released their myStarbucks app. It lets the users find coffee shops in their proximity, learn about different coffee types, and more.
That was just the beginning of Starbucks’ online presence. In 2011, Starbucks released a loyalty program aimed at people who use the Card Mobile app. That move enabled users to make payments through their phones. In the following year 2012, Starbucks integrated their native app with Square and Apple passbook, the former is a payment system for mobile devices, and the latter is a place where you can keep your loyalty card information.
That’s still not everything. In 2017, Starbucks decided that it was time for a change. With new app ideas, the company released a PWA with everything that the user needs, like images, animations, and of course, offline accessibility. Customers could finally learn about the offered products, and their nutritional values, and could customize their orders, all done without internet access.
It turned out to be a huge success, as Starbucks doubled its daily active users. Moreover, compared to the huge and heavy iOS app (148MB), their PWA only weighs 233kB.
Everyone either has an account on Instagram or knows someone that does. It’s one of the biggest success stories regarding mobile apps. The picture-sharing platform gained a massive number of 100,000 users. To make matters more interesting, it even happened in the first week of its initial launch.
Released in 2010, Instagram continues to be one of the most popular social media platforms. Nothing speaks of success more than money, after all, Instagram was bought by Facebook in 2012, for approximately $1,000,000,000. Just wow.
From the companies’ point of view, now they can post to Instagram from a desktop for better quality and share engaging content to attract new audiences and interact with existing customers.
Pinterest is yet another success story of a low-performing website turned PWA. The company wasn’t doing very well. They had a slow-performing website with not as many views, and a poor conversion rate of 1%.
Even though Pinterest already had iOS and Android apps, they still couldn’t manage to get the wanted results. That’s when the idea of a progressive web app started to form.
Pinterest just hit a jackpot! Their core metrics increased, and users spent 40% more of their time on the app compared to the website. Even better, the company noted a 44% increase in revenue coming from the ads, as well as a 60% increase in user engagement.
After all, their PWA only weighs 150kB.
The Trivago situation is a little bit different. They didn’t suffer from low numbers of views or lack of interest. Quite the opposite, actually. They were getting more and more visits from mobile users and it was time to think about the future.
Creating a native mobile app from scratch seemed like an expensive and problematic idea. The question of whether people will actually download the app has been one of the issues. Another one was the noticeable connection problems among the mobile visitors. These facts forced Trivago to rethink the idea.
Since native apps are out of the question, the company decided to place its bet on a progressive web application. The number of advantages like browser accessibility, push notifications, offline access, or the ability to add a shortcut to your home screen, had solidified the idea.
Was it a good idea? Did they succeed? They definitely did! Up to 2019, Trivago has been added to the home screen more than 500,000 times! Available in 55 countries and in 33 languages, the company’s user engagement increased by 150%. And that’s not all. Their repeated visits increased from 0.8% to 2%, and the push notifications contributed to increasing the conversion by 97%.
I promise, we’re almost here, but before we head to conclusions, let’s summarize what we’ve learned so far:
And here we are! We went through quite a lot of information here, starting from the difference between a mobile app and a web app, through planning, building, properties, and pros and cons of PWAs, hybrid, native, and web apps, to the dilemma, verdict, and some real-life success stories.
After reading this article you should be able to tell the difference between all those apps and decide which one would suit you and your business best.
With this list of 10 best web development blogs, with a treat of best YouTube channels and podcasts, you’ll be able to stay up to date with the latest web standards on all fronts — front end, back end, as well as UX/UI design, and every […]
AccessibilityWith this list of 10 best web development blogs, with a treat of best YouTube channels and podcasts, you’ll be able to stay up to date with the latest web standards on all fronts — front end, back end, as well as UX/UI design, and every other branch pertaining to the web development services.
Your experience doesn’t matter; if you’re a code newbie looking for new skills or you’re a veteran in the coding world looking for latest news, new standards or solutions to unconventional problems, this list is still for you. And even if you’re neither, and you simply want to discover all the things web development is about, stay on this page and read on!

Main Topics: Code, Content, Design, Industry & Business, Process, User Experience
Audience: Front end Developers, Project Managers, UX/UI Designers, Graphic Designers, Content Creators
A List Apart is a webzine that’s been active for 23 years now, with a focus on web design and development, web content and its meaning, best practices and standards of modern web. Most of the content consists of opinion articles, ranging from future trends to environmental impact of IT and career advice. That’s why this site is wonderful for people who are not involved directly with web development — they can prepare themselves for better teamwork, understand common practices and be able to spot frauds during recruitment.
The articles are of the highest quality. They do invite writers to submit their pieces, but they’re all diligently checked over, reviewed, and edited. It’s not easy to submit a guest post, but they promise that it’s very rewarding. So you can expect to find articles from other IT professionals, keen on sharing their coding expertise.
A List Apart doesn’t stop at blogging. They also organise An Event Apart, a conference in San Francisco (which you can also join online) that’s known for being informative, educational, as well as inspirational. For some, it’s an event you can’t miss, especially since the invited speakers are well–known industry leaders.
And if you’re looking for knowledge condensed in one place, check out their book: A Book Apart, for those who design, write, and code.

Main Topics: Tutorials, Resources, Code, Design, User Experience
Audience: Front end Developers, UX/UI Designers
Codrops is a fantastic source for front end developers, full of inspiration, useful tutorials, free resources that we all love, and articles with practical advice.
Their tutorials are long and comprehensive, and easy to follow through. They have plenty of embedded images, experimental videos, and lines of code shown in action. So if you want to learn fancy tricks, from creating infinite circular galleries to kinetic typography and glitch effects, this is your go–to site. Just like when you need inspiration: Codrops regularly posts Inspirational Websites Roundup, UI Interactions & Animations Roundup, and many others to spark your creativity.
If you’re not experienced enough to jump straight into tutorials and want to start with the CSS basics, there’s a CSS Reference library with the most important properties and information for you. All for free!
And if you want to know what’s happening in the tech world, check out their Collective, bundles of posts highlighting the latest news and resources.
For non–coding people, it’s a good site to see what can be done, and what the possibilities are.

Main Topics: Resources, Design, Content, User Experience
Audience: Front end Developers, UX/UI Designers, Graphic Designers, Content Creators
CSS Author is a front end coding blog that’s a goldmine of resources for web developers and web designers alike, with occasional publications useful for graphic designers and content writers as well. It has a staggering amount of “freebies”: you can find mockups, icons, and templates for WordPress and CMS, such as Magento or Drupal, etc. They’re all available for personal and commercial use.
This site acts as a good place to find free libraries, plugins, bootstraps, and tools for developers working with HTML, CSS, Java Script, jQuery, PHP.

Main Topics: Tutorials, Resources, Code, User Experience
Audience: Front end Developers, UX/UI Designers
CSS–Tricks is a site you can count on to be constantly posting, sometimes even several times a day. They focus on CSS, HTML, and Java Script in the form of tutorials, guides, tricks, and articles. They range from animation, typography, accessibility, web performance, serverless, and many more. And if you’d rather watch a video than read — there’s more than 200 video posts to choose from.
When it comes to resources, there’s an Almanac with CSS Selectors and CSS Properties with lots of examples and demos. If you’d like some concrete knowledge in one place, the author of the site, Chris Coyier, has two books that are available to MVP Supporters.

Main Topics: Tips and Guides, Code, Mobile Development, User Experience
Audience: Full–Stack Developers, UX/UI Designers, Content Creators
David Walsh is a personal blog, run by a professional senior full stack engineer
working for MetaMask, who also used to work for Mozilla for eight years. So you can be sure that the guy knows what he’s talking about.
Besides tips and guides mostly on JavaScript (React, Node.js, jQuery), HTML5, CSS3, you can also find sneak peeks into a life in a web development industry, some career advice, and even interviews with other experienced developers. He’s a firm believer that practice triumphs over theory, and that experiments are a worthy pursuit. This approach has resulted in almost 83,000 followers on Twitter.
If you want to discover what a successful web developer needs to make an impact, following David’s blog is a good choice. Especially since new articles just keep on coming, even though the blog has been up for more than a decade.
There’s also some advice on technical SEO, so Content Creators should definitely take a closer look.

Main Topics: Tutorials, Code, Graphic Design, Content, User Experience, Industry & Business, Career Advice
Audience: Full–Stack Developers, UX/UI Designers, Graphic Designers, Content Creators, Project Managers
Dev.to isn’t really a blog and more of a community of software developers, but we couldn’t not mention it.
On the contrary to all the previous blogs, anyone can contribute to dev.to. All the posts published on the feed are tagged for easier navigation, and it’s easy to notice the popularity of Java Script, React.Js, Python, CSS, HTML, Node.js, PHP, Vue.js, and Ruby. There’s also a lot of content for beginners, as well as posts centered around career, testing, machine learning, and security, among others.
If you like podcasts, dev.to has hundreds of them, along with videos in the form of practical tutorials, guides, tips, and useful tricks. You can also find full blog posts that are often cross shared in places like Medium or Hacker Noon. And if you have trouble understanding a concept, you can ask the community to explain it to you “like you’re five years old”. It works wonders and is great even for non–tech people.

Main Topics: Software Development, Project Management, Industry & Business, Career Advice
Audience: Software developers, Tech Leads, Project Managers, Recruiters, CEOs, Startup Founders
Joel on Software is another personal blog of an accomplished software engineer, Joel Spolsky, a creator of the project management software Trello and a Stack Exchange network. He shares his perspective not only on software development itself, but also on business, project management, recruitment, and getting started in the tech field, served with practical advice on career.
When it comes to the blog, which has been online for over a decade, it has more than 1000 useful articles. Anyone can find valuable content for themselves, from developers and tech leads to project managers, CEOs, and recruiters. Part of that knowledge has been captured into five books, available on Amazon.

Main Topics: Code, Web Application Development, Graphic Design, User Experience, Industry
Audience: Full–Stack Developers, UI/UX Designers, Entrepreneurs
SitePoint is bursting with books, online courses, and tech talks on topics of Java Script, HTML, CSS, PHP, Python, WordPress, Design & UX, App Development. The library is curated by the experts in web design and web development, so you can trust their input.
This web development blog focuses on a much wider range of subjects. You can learn more about the next wave of web technologies, such as Deno, Eleventy, Gatsby, Rust, WebAssembly, and many others. Reading the blog also ensures that you’re staying up to date with the future of the web and the state of the technology industry.
Not only web developers will benefit from paying attention to this blog, but designers as well. If you want to master Adobe XD, Figma or Sketch, along with any other similar programs, check out their materials. And even those that only want to polish their skills with Notion, Airtable, Obsidian, and other productivity tools, should also take a look.
It’s also a good place for people looking for a web development job or who want to advance their already prospering career. You can find articles full of advice for juniors and seniors alike, along with current job listings for remote positions.
And lastly, if you have questions that are still left unanswered after perusing the blog’s content, you can easily ask the community.

Main Topics: Code, Mobile App Development, User Experience, Graphic Design
Audience: Full–Stack Developers, Mobile Developers, UX/UI Designers, Graphic Designers
Smashing Magazine is an online magazine of the highest quality, geared towards professional web designers and developers, offering them practical and useful content to improve their skills.
Their goal is to support the virtual community of the coding world with news on the latest web technologies, from app development, responsive web design to accessibility and usability, among many others.
New articles are published several times a week on a wide variety of topics, to keep front end developers, designers, animators, and illustrators more than satisfied. And of course, you can find articles to keep up with the latest trends and opinion articles as food for thought, along with productivity tips
Besides the articles, you can also jump right into guides, books, and online workshops. Not all of them are for free — to access them, you need to buy a membership. There are three levels: for $3, $5 and $9 a month or $30, $50 and $90 a year.
Don’t forget to check out this site’s podcasts. “The Smashing Podcast” runs around 1 hour each, so be prepared to gain a lot of new insight.
Smashing Magazine also takes care to post current job openings and present–day conferences.
Nowadays, blogging sites are not the only source of knowledge that’s worthy of our notice. Several times we’ve mentioned videos and podcasts, that’s why it would have been remiss of us not to list our favourites.
FreeCodeCamp is a non–profit organization, supported by donors, with a mission to help people become developers for free. Besides a youtube channel, they run their own site with even more resources, and they also organize study group sessions around the world. They even offer certifications to give you an easier start in the industry.
FreeCodeCamp is perfect for self–learners. You can find there long and comprehensive courses for beginners on Python, SQL, Java Script, C++, C, Penetration Testing, HTML, Data Structure, React, HTML5, CSS3, Django, PHP, APIs, Laravel, and many more. Some of them even last for 15 hours.
Traversy Media is perfect for people who already know some basics and wish to learn something new in a quick manner without delving too deeply into each concept. Offered courses last from 20 minutes to 2 hours, with the more comprehensive ones available on Udemy. HTML, CSS, JavaScript, React, Async.js, Laravel, Rust, Ruby, Ruby on Rails, and many more — they’re all waiting to be learned and mastered while building projects from scratch.
If you prefer your courses divided into small, digestible parts, look up The Net Ninja. It’s perfect for beginners who want to learn bits and pieces on the run or in between other tasks. The overall tone is light and fun, due to the enthusiastic nature of the host, who is also very thorough and methodical in his approach.
You can choose what to learn next from over 1000 tutorials, that delve into Java Script, Firebase, Flutter, HTML & CSS, Laravel, MongoDB, Node.js, PHP, React, Vue.js, and many more. You can find both beginner and advanced material, so better keep a close eye on this channel.
If you’re even more pressed for time, look up Fireship, a channel created by Jeff Delaney on the topic of building web applications of highest quality fast. His longest series is called “100 Seconds of Code”, which is straight to the point while being very informative. It’s perfect for those who want to grasp various concepts quickly before delving into them, or for those who simply want a reminder.
Besides that, you can find out more about development tools, pro tips, productivity tips, 15–25 minutes beginner guides, both for front end and back end, from Java Script to API and cloud infrastructure.
If you’d like to take a step back from tutorials and to find out what’s happening during tech conferences without attending any, go to Coding Tech. They partner with many different conferences around the world and have their explicit permission to publish videos on youtube. Among their partners are ConFoo, JavaScriptLA, Pixels Camp, PyData, React Amsterdam, You Gotta Love Frontend, and many others. So if you want to stay on top of trends in the tech world, gain some valuable career tips while developing your hard and soft skills, subscribe without further delay.
JavaScript Talks was created with accessibility in mind. To bring conferences to those, who cannot attend them themselves, who can’t watch the videos due to visual impairment, or who simply don’t have the time to sit down and press play. It’s also a solution to those who lack a proper internet connection for one reason or another.
Thanks to this initiative, many people around the world can get access to Java Script conference talks, discover what’s new and, of course, to learn.
JS Party is a weekly podcast with a heavy focus on Java Script, but including as well Go, Ruby, Python, Node.js, and others. Besides talking about all things code, they also have episodes on developer’s culture, startups, sustainability, web development tools, and many others.
This podcast is well known for being informative (each episode lasts for an hour), yet at the same time, entertaining. With lots of banter involved.
Interested in React? Then React Talks are perfect for you, with over 100 episodes, 1 hour long each. Every episode has a new guest invited to share their experience and expertise with React, from starting their career to leading some exciting projects to analyzing the newest and upcoming trends. If you like hearing stories concerning the web development world, listen to this one.
Syntax is a podcast created by Full–Stack Developers Wes Bos and Scott Tolinski. It’s updated several times a month and each episode tends to last anywhere from 20 to 60 minutes. It’s well known for being fun, knowledgeable, and suited for both beginners and more experienced developers, improving their soft and hard skills.
Besides talking about their own experience as developers and dishing out career and portfolio tips, they explain Java Script and its frameworks, additionally venturing into HTML, CSS, Deno, development tools, freelancing, and many more.
Web Rush is another weekly JavaScript–centric podcast, run by John Papa, Ward Bell, Craig Shoemaker, and Dan Wahlin. They invite guests to share their stories of web development, challenges they’ve faced and the solutions they came up with. It’s full of practical advice and hands–on approach, making people excited to experiment on their own.
So if you’re curious about Google Maps behind the scenes, developing apps and themes for Shopify, or how to get started as a developer, check out this podcast.

Minimal commitment in website design won’t cut it. You need to stay up to date, which may seem like a challenge in the field that just keeps growing and changing. And if you’re not a web developer, but a graphic designer or a content creator, or an owner of your own website, it’s good to be aware of what’s happening on that front. This way you’ll create better content, by knowing what’s possible, what are the restrictions of web design, and what doesn’t work well in the long run.
And if you’re at the point of your coding journey where you can call yourself a professional, consider setting up your own web development blog or at least contributing to one. It’s a great way of giving back to the community and helping out those who are just starting. If you’re worried about creating competition for yourself, don’t — keep in mind the ongoing shortage of IT professionals that threatens the entire field and contribute to a better world instead.