Normalize.css: [role="button"] should be styled with cursor:pointer

Created on 21 Sep 2014  路  24Comments  路  Source: necolas/normalize.css

At the very least, [role="button"] should be styled with cursor: pointer, but I think it would make sense to style other elements the same way, for example:

[role="button"],
button,
input,
label,
select {
    cursor: pointer;
}

If menu was considered in nomalize, then we could also add menuitemin there.

Most helpful comment

Please don't do this. This seems contrary to the goals of normalize.css (as I understand it: improving consistency, not changing standard behaviors).

On this topic, web browsers are fairly consistent:

  • Buttons are cursor: default;
  • Links are cursor: pointer.

The concept for links is that they take you to a different URL. The hand cursor (pointer) indicates that. Buttons don't take you to a different URL (with the notable exception of form submit buttons, though this is less true with scripted or HTML5-validated forms), and thus don't have this style.

Specification

pointer: The cursor is a pointer that indicates a link.

http://www.w3.org/TR/CSS21/ui.html#cursor-props
http://dev.w3.org/csswg/css-ui/#cursor

Declaring cursor: pointer on buttons contradicts the spec. Of course normalize.css is not a user agent, but I'd argue it shouldn't contradict the spec in this way.

UI conventions

Desktop OSes and applications use a default/arrow cursor for most things. They use a pointer/hand cursor for hyperlinks only. Menu bars, toolbar menus, buttons, all use the default pointer.

They don't use the hand (hyperlink) cursor to denote actionable items, but a number of interaction design elements, such as:

  • hover style variations
  • visual affordance (borders, backgrounds, icons, other visual effects)
  • positional affordance (by convention, items in toolbars or menu bars can all be interacted with)

There are rare exceptions. More interestingly, there's a gray area where a button or menu entry takes the user to a different view or "location". For instance in the Windows file explorer, the locations in the left sidebar use a hand cursor, possibly because a) they take the user "somewhere else" and b) they're activated with a single click. Files, folders and links-to-files-or-folders in the main view use a default cursor.

Implementations can be a bit inconsistent. They tend to be 95% right or better in desktop OSes and apps, but much more inconsistent in web applications.

Web antipattern: everything is a "link"

On the web it gets a little bit murky as in the good old days of Ajaxified interfaces, developers would often use the <a> element with a bogus href value in order to create buttons, even if those buttons didn't change the current location (e.g. load more content, toggle the visibility of something, sort a table). A main reason for that was that the button element was seen as something to be used in forms only (wrong, though in both the HTML 4.01 and HTML5 specs that element is defined in the "Forms" section). Another reason is that buttons can be a bit tricky to style, and especially were tricky ten or even a few years ago. Yet another one is that some buttons were "progressively enhanced" links with a functional URL and JS code changing the link's behavior (to act like a button).

Some web applications ended up with 90% of actionable items showing a pointer/hand cursor, i.e. showing the cursor for hyperlinks, even though most of those items behaved as buttons, not as hyperlinks.

There are examples of applications not using this antipattern, though. For instance, the current Gmail UI gets its button-vs-links _mostly_ right (understanding links as "switch to a different view"). On the other hand, Github gets it mostly wrong.

Beyond implementation, this is a design issue were both cursors and visual styles must be considered. Designers should probably categorize actionable items depending on what they do, and come up with styles for each category and subcategory (the two main categories should probably be "Link" and "Button"). Keeping in mind accessibility, they should also make sure that their design system maps to the right HTML (and, if needed, ARIA) semantics.

What could be normalized

I'd argue that the current browser behavior is spec-compliant, and desirable. It could be reinforced further by making sure that buttons use a default cursor, with code such as:

/**
 * Correct cursor style for buttons
 */
[role="button"], /* explicit button semantics */
a[href="#"], a[href="#0"] /* Common patterns for the <a> element used as a button */
{
  cursor: default;
}

I rest my case. :)

All 24 comments

I like the idea. But would be weird to have a cursor: pointer in a, for example, <input type="text" />. I have done this before, but modifying the cursor in :active, for example:

[type='text']:active {
  cursor: text;
}

Anyhow... I'm not sure this would cut it.

Hi Thierry,
I am not sure that all <input /> and <select> should be styled with cursor: pointer. By the way, why do we not include <textarea> in this selector? IMHO, putting this sort of cursor on all form elements will not improve the usability.
Otherwise, I am OK with your idea to add [role="button"] and label even if for label I will be more specific by adding the attribut [for] in the selector.
Currently at work we use:

label[for],
input[type=radio],
input[type=checkbox],
button,
input[type=reset],
input[type=button],
input[type=submit] {
  cursor: pointer;
}
input[type=file]::-webkit-file-upload-button {
  cursor: pointer;
}

@7studio: :+1:

@7studio @battaglr I agree that my example is too broad, but the issue was really open for [role="button"].

I do not see the need to use [for] with label though as this element could wrap a control and thus not have a for attribute. May be I'm missing something though, why would label alone be a problem?

Also, why going for ::-webkit-file-upload-button since the _whole thing_ is clickable, it'd make more sense in my opinion to give that feedback to the user.

I think in my next project I'll go with something like this:

[role="button"],
button,
input[type="button"],
input[type="checkbox"],
input[type="file"],
input[type="image"],
input[type="radio"],
input[type="reset"],
input[type="submit"],
label {
    cursor: pointer;
}

@thierryk: good point about the label, didn't think of that. I believe that your latest example would be a nice addition to the code-base. :wink:

@thierryk I use [for] with label because I never wrap a control inside. :smile: It's just a safety to be sure that the label try to match with the id of a control.
Historically with IE 6, we needed to set [for] and [id] all the time. :grin: I just kept this way.
Maybe I will reconsider my point of view concerning ::-webkit-file-upload-button. It's really interesting to have other opinions on his work.
Thanks.

This would also be useful with working around Safari Mobile's element clickability issue, so long as you're accessibility-minded enough to have added the role to your non-<button> button.

Trying to think about any times you wouldn't want pointer鈥therwise, this sounds good.

Please don't do this. This seems contrary to the goals of normalize.css (as I understand it: improving consistency, not changing standard behaviors).

On this topic, web browsers are fairly consistent:

  • Buttons are cursor: default;
  • Links are cursor: pointer.

The concept for links is that they take you to a different URL. The hand cursor (pointer) indicates that. Buttons don't take you to a different URL (with the notable exception of form submit buttons, though this is less true with scripted or HTML5-validated forms), and thus don't have this style.

Specification

pointer: The cursor is a pointer that indicates a link.

http://www.w3.org/TR/CSS21/ui.html#cursor-props
http://dev.w3.org/csswg/css-ui/#cursor

Declaring cursor: pointer on buttons contradicts the spec. Of course normalize.css is not a user agent, but I'd argue it shouldn't contradict the spec in this way.

UI conventions

Desktop OSes and applications use a default/arrow cursor for most things. They use a pointer/hand cursor for hyperlinks only. Menu bars, toolbar menus, buttons, all use the default pointer.

They don't use the hand (hyperlink) cursor to denote actionable items, but a number of interaction design elements, such as:

  • hover style variations
  • visual affordance (borders, backgrounds, icons, other visual effects)
  • positional affordance (by convention, items in toolbars or menu bars can all be interacted with)

There are rare exceptions. More interestingly, there's a gray area where a button or menu entry takes the user to a different view or "location". For instance in the Windows file explorer, the locations in the left sidebar use a hand cursor, possibly because a) they take the user "somewhere else" and b) they're activated with a single click. Files, folders and links-to-files-or-folders in the main view use a default cursor.

Implementations can be a bit inconsistent. They tend to be 95% right or better in desktop OSes and apps, but much more inconsistent in web applications.

Web antipattern: everything is a "link"

On the web it gets a little bit murky as in the good old days of Ajaxified interfaces, developers would often use the <a> element with a bogus href value in order to create buttons, even if those buttons didn't change the current location (e.g. load more content, toggle the visibility of something, sort a table). A main reason for that was that the button element was seen as something to be used in forms only (wrong, though in both the HTML 4.01 and HTML5 specs that element is defined in the "Forms" section). Another reason is that buttons can be a bit tricky to style, and especially were tricky ten or even a few years ago. Yet another one is that some buttons were "progressively enhanced" links with a functional URL and JS code changing the link's behavior (to act like a button).

Some web applications ended up with 90% of actionable items showing a pointer/hand cursor, i.e. showing the cursor for hyperlinks, even though most of those items behaved as buttons, not as hyperlinks.

There are examples of applications not using this antipattern, though. For instance, the current Gmail UI gets its button-vs-links _mostly_ right (understanding links as "switch to a different view"). On the other hand, Github gets it mostly wrong.

Beyond implementation, this is a design issue were both cursors and visual styles must be considered. Designers should probably categorize actionable items depending on what they do, and come up with styles for each category and subcategory (the two main categories should probably be "Link" and "Button"). Keeping in mind accessibility, they should also make sure that their design system maps to the right HTML (and, if needed, ARIA) semantics.

What could be normalized

I'd argue that the current browser behavior is spec-compliant, and desirable. It could be reinforced further by making sure that buttons use a default cursor, with code such as:

/**
 * Correct cursor style for buttons
 */
[role="button"], /* explicit button semantics */
a[href="#"], a[href="#0"] /* Common patterns for the <a> element used as a button */
{
  cursor: default;
}

I rest my case. :)

@fvsch even if "it is in the spec", I disagree. Most users don't know the difference between a button and a link, the cursor: pointer gives them the information that "something is going to happen when you will click on it".

So that's why I use this in my CSS :

label,
button,
input[type="submit"],
input[type="button"],
input[type="reset"] {
cursor: pointer;
}

@fvsch I get your point, but you have to remember that on touch-only devices, the click handler can only be triggered when CSS cursor property is set to pointer.
though I agree, this shouldn't be in normalize.css

100% agree with @fvsch.

@nico3333fr "something is going to happen when you will click on it" you'll have that with the graphic of the button. If nobody ever click on the button, you have an ergonomic issue.

This shouldn't be in normalize, I think that normalize is here to NORMALIZE something not MODIFY it.

If you want your a[href="#"] totally looks like a button then use button[type="button"], IMO.

@nico3333fr I wouldn't generalize too quickly about "most users".

Also if your users need a hand cursor to understand that something can be clicked (which is a very questionable premise, since desktop OSes and apps do without it just fine!), then your design is utterly broken on touch devices, and you need to fix your visual language ASAP. ;)

@fvsch I do agree anyway, but tell this to communication agencies that make designs so "flat" that you don't recognise a button :)

@nico3333fr so it's because designers don't know how to make a button that we have to rape HTML's semantic? Nice. :-1:

@nico3333fr even on flat UI (eg: ios) you know where to click when you see Edit, Cancel or < Messages.

@DaPo "rape HTML semantics" :o
A

@nico3333fr don't change anything about the fact that a a[role="button"] don't need a cursor: pointer; :)

@fvsch made a few good points, but this suggestion:

[role="button"], /* explicit button semantics */
a[href="#"], a[href="#0"] /* Common patterns for the <a> element used as a button */
{
  cursor: default;
}

seems to go against the spirit of nomalize the same way as cursor: pointer on label, button, etc. do.
As @fvsch put it, Normalize is about improving consistency, not changing standard behaviors.

So I'd downvote my previous suggestion even though I'll keep using this myself. As I do see the benefit of the visual cue and do not believe users associate this to _links_ per se. After all, there are countless examples in the wild where we use pointer on elements that don't link to a different page. I'm thinking of dropdown menus, accordion menus, tabpanel, CTA buttons, etc. For years, we've trained people to associate the pointer to a _generic_ trigger, this has became common practice.

@thierryk because we seem OK with the point of view of @fvsch, we should open a new issue for proposing to remove these two parts of normalize.css:

button,
html input[type="button"], /* 1 */
input[type="reset"],
input[type="submit"] {
  cursor: pointer; /* 3 */
}
/**
 * Re-set default cursor for disabled elements.
 */

button[disabled],
html input[disabled] {
  cursor: default;
}

What do you think about that?

@7studio Yes, I agree, that makes sense to me.

Yes let's remove some of the opinionated styles instead.

<style> .cell {cursor: grab;} </style> <input type="text" class="grab" value="Se connecter" onclick="window.open('https://github.com', '_blank', 'toolbar=yes,scrollbars=yes,resizable=yes,top=100,left=100,width=1000,height=550')">

Please don't spam.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

visicode picture visicode  路  5Comments

GregBoss picture GregBoss  路  5Comments

denis-sokolov picture denis-sokolov  路  4Comments

visicode picture visicode  路  7Comments

gitowiec picture gitowiec  路  6Comments