DEV Community

loading...
Cover image for Stop choosing DX over UX. Or maybe not?

Stop choosing DX over UX. Or maybe not?

stereobooster
Hello, I'm a full stack web developer. Follow me on Twitter!
Originally published at stereobooster.com on ・3 min read

Stop choosing DX over UX.

Devon Govett (@devongovett)

By no means I want to dunk on Devon. This is just an example of sentiment flowing around the internet. So you, reader, would understand where I coming from.

DX - developer experience. UX - user experience, usability.

Let’s talk about button

Using <button> instead of <div> for a clickable elements is a good for UX (and accessibility). Yet a lot of front-end developers keep using divs or spans or something else. Why is that?

My guess is that because it is much easier to work with div then button, because div doesn’t have built in styles. Developers taking short cut here, and probably unconsciously, selecting better DX.

If using button would be as easy as using div, I guess a lot of people would use it. Maybe if we would thought about DX in the first place, UX would be better, because developers would have more time to spend on solving actual user’s problems instead of fighting with tooling and lack of standard libraries?

The code

If you wonder how hard it can be to use button <button> instead of <div>. Here is the snippet with “CSS reset”, which removes all quirks from the button:

import styled from "styled-components";

if (typeof document !== "undefined") {
  // https://alxgbsn.co.uk/2011/10/17/enable-css-active-pseudo-styles-in-mobile-safari/
  document.addEventListener("touchstart", function () {}, false);
}

export const focusRing = (color: string = "blue", inset?: boolean) => ({
  /* Remove excess padding and border in Firefox 4+ */
  "::-moz-focus-inner": {
    border: 0,
    padding: 0,
  },
  ":focus": {
    outline: "none",
  },
  ":focus-visible": {
    // https://css-tricks.com/platform-news-rounded-outlines-gpu-accelerated-svg-animations-how-css-variables-are-resolved/#rounded-outlines-are-coming-to-firefox
    "box-shadow": inset
      ? `inset 0 0 0 3px ${color}`
      : `0 0 0 2px #fff, 0 0 0 5px ${color}`,
  },
  transition: `box-shadow 100ms ease-in-out`,
});

/**
 * reset built-in styles of a button https://css-tricks.com/overriding-default-button-styles/
 *
 * Don't forget to provide styles for:
 *
 * - default state
 * - `:hover`
 * - `:active` (See also https://bugzilla.mozilla.org/show_bug.cgi?id=68851)
 * - `:disabled`
 * - `:focus-visible`
 *
 */
export const BaseButton = styled.button`
  ${focusRing()}

  display: inline-block;
  border: none;
  margin: 0;
  padding: 0;
  width: auto;
  overflow: visible;

  background: transparent;

  /* inherit font & color from ancestor */
  color: inherit;
  font: inherit;
  text-align: inherit;
  text-transform: inherit;

  /* Corrects font smoothing for webkit */
  -webkit-font-smoothing: inherit;
  -moz-osx-font-smoothing: inherit;

  cursor: pointer;
  :disabled {
    cursor: default;
  }

  /* Corrects inability to style clickable input types in iOS */
  -webkit-appearance: none;

  user-select: none;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
`;

BaseButton.defaultProps = {
  type: "button",
  // @ts-ignore https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button#attr-autocomplete
  autocomplete: "off",
};
Enter fullscreen mode Exit fullscreen mode

Source code on the Github. My previous post about button.

Links in the code:

What to do?

If you have components library in your company, add BaseButton to it. And your team can follow the best practice easily:

- const MyButton = styled.div` ... `
+ const MyButton = styled(BaseButton)` ... `

- <div onClick={...} />
+ <BaseButton onClick={...} />
Enter fullscreen mode Exit fullscreen mode

A bit of DX may improve life for developers and users.

Discussion (10)

Collapse
moopet profile image
Ben Sinclair

I'm not sure I agree with your axioms.

If I want something to act like a button, I'll use a button.
I'm not sure that people think it's more difficult than using a div.

Using a div means you have to replicate all the features that button already provides. You have to reinvent the wheel. You can't have it act like a native button widget, with all the familiarity that invokes.

I don't think people use div because it's technically easier to implement - it's not - I think they use it because they haven't learned about button.

Cynically, if someone made a library called "newTrendyButton" and released it to the world and all it was was actually, you know, a straight-up HTML button, then I think people would use it, and when you listed its features they'd all be very impressed and write tweets about it.

Devices and browsers have their own systems - for example if you made your own select replacement and someone used it on iOS, they'd get a different experience to the one they get in native apps or on other websites. If you have a good reason for that, you can override the select element, but I honestly think the case for this is small.

Users see something that looks like a button and it behaves like a button. Developers see a button and it behaves like a button.

Collapse
stereobooster profile image
stereobooster Author • Edited

My argument is a pure speculation. We would never know the truth, unless we're gonna do big poll asking "Hey, do you know HTML supports buttons natively? If yes, why don't you use it?"

But from my experience, when I was less experienced, I tried to use semantic HTML and resorted to divs as soon as it didn't work as I would expect (because I know divs are working at least CSS-vice)

Collapse
ashleyjsheridan profile image
Ashley Sheridan • Edited

But this isn't really working. You are making some look the way you want, but by using a div you are:

  • Removing focus handling. A div isn't a native interactive component, so it doesn't receive focus, and won't have focus styles
  • Removing keyboard handling, so now all those users who rely on keyboard navigation are stuck
  • Remove any screen reader support. A screen reader can't announce the element as a button, can't convey what state it's in

I'm not really sure why anyone would reach for a div when form elements in HTML are so well known and have been in use for decades. As for styling, there are literally thousands of guides online to show how to do it, and plenty of ready-made solutions that even the laziest developer can copy/paste into their own websites.

Thread Thread
stereobooster profile image
stereobooster Author

I'm not really sure why anyone would reach for a div when form elements in HTML are so well known and have been in use for decades.

apparently it is not so wide knowledge, if you take a look around, there are plenty webiste using divs instead of button

There are even dedicated articles about it, for example web.dev/use-semantic-html/#use-but...

Thread Thread
ashleyjsheridan profile image
Ashley Sheridan

But even in your example in this post, you're not showing the full picture, despite already using Javascript to modify the CSS of a button. What you're doing by removing the "quirks" is you're removing the very features of a button that people rely on to actually use the button.

Thread Thread
stereobooster profile image
stereobooster Author

Not sure what you're talking about

Thread Thread
ashleyjsheridan profile image
Ashley Sheridan

You've removed the hover and focus styles, and left in a comment from the original React example that warns about making sure they get set correctly, but you don't do that. Focus styles are absolutely essential for those users who rely on keyboard for navigation. Try it yourself, visit a website and move around without a mouse. Notice how the visual focus indicator moves to each interactive element as you tab to it? Now imagine how difficult that navigation would be if there were no focus rings or borders on elements.

Never remove focus styles. You can change them if you feel you need something more in keeping with your design, but never remove them.

Thread Thread
stereobooster profile image
stereobooster Author

You've removed ... focus styles,

":focus-visible": {
    "box-shadow": inset
      ? `inset 0 0 0 3px ${color}`
      : `0 0 0 2px #fff, 0 0 0 5px ${color}`,
  },
Enter fullscreen mode Exit fullscreen mode

(Safari and IE require polyfill)

You've removed the hover

That is how CSS reset works - everything is removed, developer suppose to provide their own style

const MyButton = styled(BaseButton)`
  border: 1px solid black;
  :hover {
     background: pink;
  }
`
Enter fullscreen mode Exit fullscreen mode

There is even a comment

reset built-in styles of a button https://css-tricks.com/overriding-default-button-styles/

Don't forget to provide styles for:

 - default state
 - `:hover`
 - `:active` (See also https://bugzilla.mozilla.org/show_bug.cgi?id=68851)
 - `:disabled`
 - `:focus-visible`
Enter fullscreen mode Exit fullscreen mode
Collapse
thekashey profile image
Anton Korzunov

Stop choosing DX over UX.

The problem exists because someone "started".
Before we value User(paying money to the business) and Business needs(paying us) over our own "developer happiness". There were a lot of solutions a little harder for developers, but providing amazing results and value to the end users.

Those solutions of the past, and their analogs of today are generally ignored by the developers due to many reasons.
And the "Bad DX" is one of them.

So, that's a classical Chicken/Egg problem. What do you think?

Collapse
stereobooster profile image
stereobooster Author

Discussion went to abstract realm. I'm not sure I understand what you trying to say.

Classical example of "choosing DX over UX" is CSS-in-JS. It provides much better DX, than plain CSS, but worse UX, because any CSS-in-JS (with runtime) is slower than plain CSS.

And stop choosing DX over UX in this case would be to use CSS-in-JS without runtime, like vanilla-extract.