Why it exists, is there any reason why it still works?
Let’s go in pieces...
URI Schemes
The value javascript:código JavaScript
is a URI that uses the URI Scheme javascript
. Basically, there are several schemes different (for example, in a URL like http://www.abc.com
, the http
is the Scheme, but there are others that are not necessarily used for URL’s, such as mailto
, file
, maps
, among others - the list is immense).
In the link of the preceding paragraph, Scheme javascript
is listed as "Unofficial but common" (that is to say, it is not officially recognised by the IANA, whose official list is this), but still exists and is supported by browsers (see here the draft that defines this Scheme).
And where can I put one URI Scheme in an HTML document? Basically, in any attribute from this list of a kind URI
. See that the a[href]
is one of those whose type is URI
, but there are also others, such as img[src]
, body[background]
, form[action]
and many others (and beyond these, I can also put Javascript code in attributes related to events, as onclick
, onload
, etc - the difference is that these can only have code, while the other attributes already cited can have any valid URI).
This is not to say that it will always work with everyone, of course. For example, the 2 examples below do not work (I tested it in Chrome and Firefox):
<body background="javascript:alert('body background')">
<img src="javascript:alert('img src')">
That’s because the browser tries to load URL’s as image and fails.
But there are other cases where a URI Scheme of the kind javascript
works. For example, the example below shows the alert
when loading the iframe
:
<body>
<iframe src="javascript:alert('iframe')"></iframe>
</body>
And the example below shows the alert
when the form is submitted (it does not work on the snippet of the site, but testing directly on the browser itself, the alert
was shown):
<form action="javascript:alert('form action')">
<input type="submit" name="vai">
</form>
Why does it work?
This works because, in summary, the following happens:
- the element has an attribute whose value is any URI (using any URI Scheme existing): a
form
can have a URI in the attribute action
, one iframe
may have in the src
, one a
may have in the href
, etc....
- this URI is evaluated when a particular event occurs, which varies according to the element: in a
form
, is when it is submitted, in iframe
, is the moment he is born, in a a
, is when this is clicked.
- each URI has a way of being evaluated and a "consequence" (something that occurs next):
- if it is a URL like
http://www.etc...
: if you’re in a a
makes the browser go to the page, the form
submits the data to this URL, the iframe
loads the contents of the URL.
- if it’s
mailto:[email protected]
, can for example open the email client that is configured in the browser/OS (usually with the "To:" field already filled with the specified address).
- if it’s
javascript:código
, the code is executed (the algorithm to evaluate/execute a URI Scheme javascript
is described here).
- etc... (each URI Scheme has its own way of being evaluated and an action that the browser next take)
- depending on the element, the URI may not work (as is the case with
img src
cited above, for example)
But it makes sense?
Whether it makes sense to use it or not is another story (but it seems to me that the focus of the question is more on why it exists, and it doesn’t necessarily make sense to use it alert
in a link - although the other answers have focused only on this second aspect).
Maybe a a
with javascript
in the href
does not make much sense (as already explained in another answer), but with others URI schemes do. For example, mailto
or tel
on a link, in my view, makes perfect sense - including the MDN says the following on the attribute href
:
Links are not Restricted to HTTP-based Urls - they can use any URL Scheme supported by browsers.
Links are not restricted to the HTTP URL’s - they can use any Scheme supported by browsers.
And among the examples of schemes, he quotes tel
and mailto
, among others (another page with a similar example). But the same MDN also says:
Anchor Elements are often abused as fake Buttons by Setting their href
to #
or javascript:void(0)
to Prevent the page from Refreshing, then Listening for their click Events.
These Bogus href
values Unexpected behavior when copying/dragging links, Opening links in a new tab/window, bookmarking, or when Javascript is loading, errors, or is disabled. They also Convey incorrect Semantics to assistive Technologies, like screen Readers.
Use the <button>
Instead. In general, you should only use a hyperlink for navigation to a real URL.
Elements a
are often abused in the form of fake buttons, setting the href
for #
or javascript:void(0)
to prevent the page from reloading, and listening to click events.
These values of href
cause unexpected behavior when copying/dragging links, opening them in a new tab/window, adding to favorites or when Javascript is loading, error, or disabled. This also gives an incorrect semantics for assistive technologies such as screen readers.
Instead, use a <button>
. In general, you should only use a link to navigate to a real URL.
That is, technically nothing prevents you from using javascript:código
in a link, only not recommended.
If browsers banned everything that is not recommended, a lot would fail to work. But ramble...
A little bit of speculation...
Of course the browser might even allow only URL Schemes that "make sense" and disable the rest, but from what we can see, that’s not how they decided to do.
But let’s assume that the browsers decide that Javascript code will no longer be allowed on href
. That could solve the question of semantics and other problems mentioned in the other answers, but only partially, because it would still be possible to do this:
document.querySelector('a').addEventListener('click', function(e) {
e.preventDefault();
alert('vc clicou no link, mas ele não vai pra lugar nenhum');
});
<a href="https://www.google.com">Link</a>
That is, it is still possible to make a link that does not behave like a link: the URL of href
is completely ignored and I only show one alert
(and this works in the snippet of the site).
Of course still someone could argue that if you ban code on href
, would be "one less problem to worry about". But it may be that they decided that it was not worth creating an exception to close only one door, and all the others would remain open (and here I am speculating, I do not know if anyone has actually discussed this issue or if they simply implemented the support to URI Schemes in all attributes that can receive a valid and ready URI).
My guess is that "solving" it would bring too many complications that are probably not worth it, because how would I prevent the above case? Depending on the element and/or the event, I should ban the call to preventDefault
? Or shouldn’t you even let me add the click event? But what about other events like hover
, focus
, and so many others? But then the code would error ("popping" on the screen or console) or fail silently? And this is just for a[href]
, I would also have to review the behavior for all attributes already cited, which accept a URI Scheme javascript
. Which element/event combinations "make sense" and which should be "prohibited"?
So it seems to me that it is "better" to let you accept Javascript on href
, and who creates the pages who worry about not (ab)using.
In short, there is this: it exists because someone created it, and it still works because there doesn’t seem to be a "good enough" justification to stop working.
Why shouldn’t there be?
– Maniero
The attribute
href
(Hypertext Reference or hypertext reference) is used for the purpose of specifying a URL. It makes no sense to put scripts (codes that will be executed) in the attributehref
intended for addresses (at least from my perspective since it would break the meaning of the attributehref
).– felipe cardozo
I’ll try it again: Why shouldn’t there be? You have to give a reason, not speculate. The problem with the question is to speculate that it shouldn’t exist. Without knowing its motivation of the question, it makes no sense. Hence came an answer that is only a belief. Both in questions and answers, beliefs do not help much.
– Maniero
@Maniero, that’s why I ask Because and if there is any Motive for scripts to work in links. Regarding your question Why shouldn’t there be? is a reverse question since I ask "why does it exist", but in my view it is on account of semantics same!
– felipe cardozo
So I’m going to answer, because you already have an answer that doesn’t even answer and you have positives. Let’s see if you really want to know why or started from a wrong premise.
– Maniero
Actually reading your comment in a reply shows that you don’t want to know why, without explaining the real reason why you want to know that you can’t answer, the two answers given do not answer what you want to know or why it exists, Worse is one of them not to go near it and have two positives. I will just summarise here why this exists: there is no reason why it should not exist. If it exists elsewhere why should this place be special? What if you need to make creative use of it?
– Maniero
If the question is about why it works to put Javascript code in
href
(any code, not necessarily Alert), I suggest changing the example to any generic code without Alert. I say this because the answers below focused more on Alert than why (in fact none answered because it is possible, but perhaps it is because Alert ended up "diverting attention" and becoming the focus of the question, when in fact it is only part of any example) - by the way, your example works yes (tested in Chrome)– hkotsubo
@hkotsubo, yes it works (except here in stackoverflow, tested and did not work)
– felipe cardozo
Anyway, if you want to know why it is possible to run js on href, I suggest changing the question’s title. "Why there is?" is a thing, "makes sense?" is another (and the answers below focus on "makes sense" and do not mention anything about "why there is", hence the confusion)
– hkotsubo