Anchor or button [duplicate] - html

This question already has an answer here:
Why are buttons discouraged from navigation?
(1 answer)
Closed last year.
What element should I use for JavaScript actions?
Actions that does something like play/pause/stop/new/open/save/print/close, etc.
<a id="play" href="#">Play</a>
Play
<button id="play" tabindex="0">Play</button>
<div id="play" role="button" tabindex="0">Play</div>
I see many people use anchors <a> with a href="#" but that doesn't feel very semantic, it feels like anchors are for hyperlinks that point to a resource, not for actions that does stuff. Then you have to hack it around with event.preventDefault (i.e. return false).
I rarely see people use the <button> element, but isn't it what is supposed to be used?

TLDR; you can open an anchor link in a new Tab/Window but not a button.
Here is a rule of thumb:
For navigation just use anchor it's alright to style it as a
button and let it use it's href attribute well.
For quick actions (play,pause,stop,+1 like) just use button it
doesn't have href for a reason!
Consider this code.
const [anchor] = document.getElementsByTagName('a')
const [button] = document.getElementsByTagName('button')
anchor.addEventListener('click', e => {
console.log('anchor clicked')
e.preventDefault()
}, false)
button.addEventListener('click', e => {
console.log('button clicked')
})
a {
text-decoration: none;
padding: 2px;
}
button {
background: none;
border: none;
font-size: 16px;
}
.btn {
background-color: blue;
color: white;
display: inline-block;
text-align: center;
}
<a class="btn" href="#">
Anchor
</a>
<hr/>
<button class="btn" type="button">
Button
</button>
Styling
They both look almost alike (with minimal justifications) the only problem is that you'll have to undo some stylings that come with button like border & background but with anchor you don't get the clicking popping animation that you'd get with button.
Functionality
But since the anchors <a> need <a href="some/path"> to work even if it's just #, unless you need to navigate after clicking the anchor you'll have to use e.preventDefault() in your javascript to prevent it.

The best way to decide which element has the best semantics for a JS based user interaction is to ask what you want to happen if the JS fails (which it will.
Think progressive enhancement. Think unobtrusive JavaScript.
Should the user just go to another page? Use a link. The href will be the fallback from when the JS fails.
Should the user go to another page while sending some data or making a POST request? Use a button, put it in a form.
Is it impossible to have any kind of server fallback? Use a <button type="button"> and consider generating it from JS/DOM instead of HTML.

Then you have to hack it around with event.preventDefault
You could set the href to javascript:void(0) rather than #, which would prevent execution without having to use event.preventDefault()
But buttons are probably better for this sort of thing

This is more of a preference thing.
Personally, I prefer to either use the <button> tag or make my own.
If it makes more sense to you to use the <button> tag, use it. If it works, it's not wrong. =)

Related

HTML Validation: Why is it not valid to put an interactive element inside an interactive element?

Disclaimer: I understand that it is not valid HTML. I am trying to understand why is it not allowed?
W3C suggests that an interactive element like button or a mustn't contain another interactive element.
I could find a lot of resources mentioning this rule and some workarounds, also some resources related to how this impacts accessibility and screenreaders, but almost all of those resources talk about the fact that this is a requirement but do not explain why.
https://adrianroselli.com/2016/12/be-wary-of-nesting-roles.html
https://codepen.io/vloux/pen/wXGyOv
Nesting <a> inside <button> doesn't work in Firefox
https://github.com/dequelabs/axe-core/issues/601
I wasn't really able to find an explanation for why is it not allowed? does it lead to any usability problems?
This is a related question:
Why should interactive element not be used within an anchor?
The accepted answer is satisfactory but is not enough to make this rule a requirement. The described situation can be avoided using proper event handling.
Also, if nested interactive content is invalid, how are we supposed to have something like this:
A card which is clickable as a whole, and also has a clickable secondary CTA inside it.
I know a workaround would be to have a primary and secondary CTA inside the card, but shouldn't the above be allowed as well?
Here is a fiddle:
https://jsfiddle.net/t9qbwas5/2/
<button type="button" class="card">
The card itself is the primary CTA.
<br/>
<br/>
some important content to read through.
some important content to read through.
some important content to read through.
<div class="cta">
Secondary CTA
</div>
</button>
.cta {
padding: 4px;
background: #00a9a9;
color: white;
width: 80px;
margin: auto;
margin-top: 8px;
margin-bottom: 8px;
}
.card {
width: 200px;
display: flex;
flex-direction: column;
justify-content: center;
text-align: center;
}
In the above example, I am achieving this by using a clickable div inside the button, but that is not semantic (?) and also functionality wise, it is an interactive element inside another one. I am trying to understand that even if I use this workaround, is it fundamentally wrong to have nested interactive elements? is it a bad design/usability practice?
The answer is actually quite simple in principle. When you click on the interactive element inside another interactive element which function should you trigger?
In your example if I click on Secondary CTA should it fire the function for secondary CTA or should it fire the function for the card?
The fiddle below should demonstrate the problem, tab into the first button and press enter, then tab into the CTA and press Enter.
Obviously you could work around this but I think it demonstates the point.
$('.card').on('click', function(){
console.log("card");
});
$('.cta').on('click', function(){
console.log("cta");
});
.cta {
padding: 4px;
background: #00a9a9;
color: white;
width: 80px;
margin: auto;
margin-top: 8px;
margin-bottom: 8px;
}
.card {
width: 200px;
display: flex;
flex-direction: column;
justify-content: center;
text-align: center;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button type="button" class="card">
The card itself is the primary CTA.
<br/>
<br/>
some important content to read through.
some important content to read through.
some important content to read through.
<div class="cta" tabindex="0">
Secondary CTA
</div>
</button>
This principle then continues through to Screen Readers and other Augmentative and alternative communication (AAC) devices.
Should they take into account the parent element when describing the child element? Should they allow the use of Space to activate if you nest a checkbox within a <button>, should Enter then affect only the button or both?
A card which is clickable as a whole, and also has a clickable secondary CTA inside it.
Although visually imaginable and technically possible, it's not accessible for assistive technologies, like screenreaders
Let's make a simple example:
<button>
Click for action 1
<button>Click for action 2</button>
</button>
The accessible name for the first <button> would be "Click for action1 Click for action 2". And if you define an aria-label="Click for action 1", then the inner button element would not be read at all.
If you really want to make a whole element clickable, you can perfectly use javascript and still be accessible
<div class="outer">
<button type="button" class="card">
The card itself is the primary CTA.
</button>
<br/>
<br/>
some important content to read through.
some important content to read through.
some important content to read through.
<button class="cta">
Secondary CTA
</button>
</div>
<script>
$(".outer").on("click", function() {$(".card").click()});
</script>
<style>
.outer {cursor: pointer}
</style>
With this example, you will correctly have two buttons rendered to screenreaders, the first one "The card itselfis the primary CTA" and the second one "Secondary CTA", while a mouse click on the whole card would lead the same action as the first button.
It's hard to answer "why" questions, because there are many factors to be considered and ultimately the reason is that the specification specifies it, but I'll give it a try.
When this behavior was spec'ed, this design style was not very common. A link was normally either a single image or a small portion of text. Take a look at this link to an article from the year 2000:
]
Only the title and the image are interactive. The rest is simple text.
Even today, this is not so common. Take also look at the Microsoft 365 pricing page:
Note how the card itself is not interactive, only the things inside it. You can see the primary CTA "Buy now" in the form of a button and the secondary CTAs in the form of hyperlinks.
Now, about your example: Is that card really a button? It might be subjective, but for me that's not a button. A button normally appears with a color scheme contrasting with the surrounding page. I would make the card a <div> and the secondary CTA a <button>.
However it might be confusing to users, as the card doesn't seem much interactive to me. Consider adding cursor: pointer to the <div> (beyond all the things necessary for accessibility)`.
I noted you tagged accessibility. I think this is not a great idea for people using screen readers, and I think most screen readers would have problems interpreting a button inside a button (if the browser accepted that at all).
I would use the "Microsoft 365 pricing page approach" instead. It's simpler and works well with HTML.
One important problem is related to event-capturing; if you click on a interactive element nested inside another interactive element(e.g. a select inside a clickable button) there would be an interference here and two case might happen depends on the browser;
case 1 is that both element will raise that event (e.g. click) event
 
case 2 is that parent element will capture the event and the nested element won't raise that event
in fact both cases will result in non-deterministic behavior;
This is not limited to click events actually, but click event is more tangible; Also the screen reader will fail to parse the markup; keyboard-interaction won't work as expected; try it in the snippet below:
del.addEventListener('click', function(){
console.log('deleting ...')
})
save.addEventListener('click', function(){
console.log('saving ...')
})
sel.addEventListener('change', function(){
console.log('changing to', sel.value)
})
<div id='del'>
delete
<button id='save'> save
<select id='sel'>
<option>foo</option>
<option>bar</option>
<select>
<input name='a' type='radio' />
<input name='a' type='radio' />
<input name='a' type='radio' />
</button>
</div>

How to change texts colors in my case

I have bunch of links and I need to change the texts color to red after user clicks them
I have something like:
<li class="test" ng-repeat="item in items">
<a href="" ng-click="clickMe()" class="test-li">
{{item.name}}
</a>
</li>
Currently the style is like
.test-li {
color: black;
}
I want my texts to turn red after user clicks them.
So I do:
.test-li:visited {
color:red;
}
It works when I click the item, but the color changes back to black after I click another item. I feel like this can be archive simply in CSS without setting ng-class. Can anyone help me about it? Thanks a lot!
You don't have any destination url given in your links, so there really isn't a way for the browser to know which links have been visited. I think if you were to add a simple #test, #test1, #test2, etc to your href attribute in your links, you would find that your CSS does work as intended.
Since your link doesn't actually go anywhere, you'd be better off adding a 'visited' class to your <a> element when clicked, via JS.
jQuery exmample:
$('li a').click(function(){
$(this).addClass('visited');
// or you could use $(this).toggleClass('visited'); depending on what you want to achieve.
});

How to utilize CSS only button markup?

For my curiosity, given a CSS-only button markup like this one: http://www.cssbutton.me/ryanjohnson_me/4fea99463f2df0f605000043, one can create a button visually using:
<div class="button">Click</div>
But how can we actually make it functional? For example, make it link to some other page, so when user clicks on it, she gets redirected.
I've tried wrapping a <a href> inside the <div>, but the button text shows up as a link, which is undesirable. I also tried the opposite - wrapping the <div> inside a <a href>, which seems to work but I was told this is not valid html code.
Any other suggestion?
P.S. The targeted browsers would be IE8+, chrome 14+, Firefox 11+, Safari 5+ and Opera 11+, if this makes any difference.
Have you tried changing the
<div class="button">Click</div>
into <a class="button" href="#your_link">Click</a>?
It should work as a normal link, and have the css buttons stylings and expected behavior.
Use JavaScript to bind an action to the button.
function addEventHandler(elem,eventType,handler) {
if (elem.addEventListener)
elem.addEventListener (eventType,handler,false);
else if (elem.attachEvent)
elem.attachEvent ('on'+eventType,handler);
}
addEventHandler(document.getElementById('yourButton'), 'click', function(e) {
document.location.href = "newpage.html";
});
Add to the css:
a.button { text-decoration: none; }
To create button links:
<a class="button" href="/somewhere.html">Somewhere</a>
Using JavaScript, specifically jQuery, you can do
<div class="button" id="myButton">Click</div>
$("#myButton").click(function()
{
location.href = "mypage.htm";
});

please advice a better link button and return false solution

html has link element
as well as button element
<button></button>
in fact their responsibility are different but... sometimes design want them look the same.
I don't any clue to style them look exactly the same, beside reset display, margin, padding, border, background, font etc... they won't look the same at the end and sometimes they screw up each other default positioning attribute.
so my initial solution as below:
example of a link
designer want a link look like a button. I wrap a button in a link!
<button class="coolbutton">look cool</button>
I like this solution, especially i think a button are a lot easier to style.
then the a tag will response to the click and link
now, example of a form :
a button for submit the form and a links beside the button. they need to look the same.
and the link button shouldn't submit the form.
but it is inside the form...
<button class="coolbutton onclickreturnfalse">I just want to link it</button>
<button> Submit </button>
the class .onclickreturnfalse are bind to javascript click event to return false anyway. so it won't submit the form... but the problem is.. it return false to the link also.. so the link won't work...
sorry for my poor description and title. I need some opinion now. how a web designer solve these problems?
#
so i put my CSS here
#
button,a.bt1,a.bt2,a.bt3{
border: 1px solid rgba(152, 152, 152, 0.1);border-radius: 2px;color: #666666;cursor: pointer;
font-size: 8pt;font-weight: bold;min-width: 54px;padding: 4px 8px;text-align: center;
}
button,button.bt1,a.bt1 { background-color: #F5F5F5; }
button.bt2,a.bt2 { background-color: #F5F5F5; color:#BF0000; }
button.bt3,a.bt3 { background-color: #BF0000; color:#EFEFEF; }
button:hover,a.bt1:hover,a.bt2:hover,a.bt3:hover{
border: 1px solid rgba(208, 0, 0, 0.1); text-decoration:none;
}
seriously... they look a little bit different :(
You should either use a button or an anchor, but I don't see why would you use a button inside a link. You can style the anchor to look as a button or simply use a button and handle the click event.
For example, clicking on this link will not cause a postback (with JS enabled in the browser): <a href="#" class="coolbutton" onclick="alert('test'); return false;" />

Which is the _proper_ html element to use for calling action when clicking on an image?

I have a webapplication where (as in many other ones out there) you click on an image to do something, for instance, mark an entry, send a mail, flag something...
Short, clicking on the image is supposed to call an action (via javascript, but that's not the point).
I was wondering, what is the "right" way to do this?
<a>-tag? Hmm... actually it is not a link...
<button>? Because obviously a button is the semantic element for calling an action...
<div>?
Any hints?
Short Answer
Use an <img> - not a button or an anchor or an input - as the rest suggest that the element is interactive, even without JavaScript.
Long Answer
clicking on the image is supposed to call an action (via javascript, but that's not the point).
I disagree; that is the point :)
Because the clicking activates JS-only features, your image should only be available in a JS environment.
As such the proper way is to insert it with JavaScript; while an HTML document should be semantically correct, a DOM structure doesn't really need to be semantically correct, so which element you use becomes irrelevant.
The Wrong Way
<div>
Click on the image to do something:
</div>
<div>
Click on the image to do something: <input type="image" onclick="wtv()" src="..." />
</div>
<div>
Click on the image to do something: <img onclick="wtv()" src="..." />
</div>
<div>
Click on the image to do something: <button onclick="wtv()"><img onclick="wtv()" src="..." /></button>
</div>
These are all wrong because a user who doesn't have JavaScript sees these items and can't use them.
Of all of these, I'd say the <img> is the lesser evil, as it doesn't suggest an interactive element. The greatest evil is using the <a> as an anchor should be a hyperlink to another document, and you should never, ever use the javascript: protocol.
You'll still have the same problem when you add the JavaScript event handlers externally:
/* external .js file */
document.getElementById("myButton").onclick = wtv;
<!-- HTML document -->
<div id="myButtonParent">
Click on the image to do something: <a id="myButton" href="#" style="background-image:url(...)"> </a>
</div>
As, again, you still have the (non-functioning) hyperlink available to those users who don't have JavaScript.
Instead
Instead, insert the whole damn thing using DOM scripting! I'm going to use an <img> with an onclick event:
/* external .js file */
window.onload = function() {
var img = document.createElement("img");
img.src = "...";
img.onclick = wtv;
img.style.cursor = "pointer"; // so the mouse turns into a finger,
// like on a hyperlink
// Note: instead assign a class attribute and put this in an external CSS file...
document.getElementById("myButtonParent").appendChild(img);
}
You could add an onclick event for the image:
<img id='image1' onclick="javascript:DoSomething()"...
or add it via jquery:
$("#image1").click(
function() {
DoSomething();
});
I don't think you should use an anchor tag here. Anchoring is for navigating not doing things. Not to mention if you use the beforeunload events, they will get fired if you use an anchor.
While the div works it doesn't add anything semantically to the page. You are not defining a distinct chunk of the page you need to make an image clickable.
I don't use a button control enough to talk about that as an option.
Do not quite understand what you want to achieve. But have you tried image input?
<input type="image" src="image source">
It will do an operation similar to form submit.