Drupal - How to create an EMPTY anchor-only link with l()?

PHP typecasting pop quiz time! (Full disclosure: I didn't win in our office).

As pointed out already, this is the code in l() that we're concerned with:

if (isset($options['fragment']) && $options['fragment'] !== '') {
  $options['fragment'] = '#' . $options['fragment'];

So here's the question: What value casts to an empty string but passes the following?

(isset($var) && $var !== '')

The answer is: FALSE!

So, we could try this:

l(t('My link'), NULL, array('fragment' => FALSE));

Which gives us:

<a href="/#">My link</a>

Thankfully we can strip that leading slash by passing along external => TRUE:

l(t('My link'), NULL, array('external' => TRUE, 'fragment' => FALSE));

Which gives us:

<a href="#">My link</a>

Boom. The things we do to avoid concatenating html strings manually, eh?


I'm not sure I'd actually recommend printing a link like this from php under normal circumstances. Without your javascript, all that link is going to do it jump your user to the top of the page (which, to my slight surprise, is specced behaviour). It should probably point somewhere that works without javascript.

If the link really only makes sense with javascript around (like the controls for a js-only slideshow or something), I think it's better to add the link to the page with javascript. Alternatively, if you really want to put it in your source, make sure it's display:none'd by default. Drupal has the .js class on the html for then showing it when javascript is around.

If you could not use clean "#" with fragment, I would suggest you to use <a href="javascript:">link</a>.
When adding "javascript:" or "javascript:void(0)" to href attribute, the <a> tag will do nothing. Then you can bind "onclick" to the link for your ajax purpose.
You can implement this using l() function as below:

     l('link', 'javascript:',  array('external' => TRUE));

Unfortunately the url() function (which l() calls internally) pretty much nukes any chance of an empty fragment with the following lines:

if (isset($options['fragment']) && $options['fragment'] !== '') {
  $options['fragment'] = '#' . $options['fragment'];

It checks to make sure the fragment isn't an empty string, which is what you'd need to pass to get the clean #. I think the easiest solution would be to pick the id of a suitable element somewhere in the page and use that for the fragment instead (or javascript:void as Sithu has mentioned).

However...the most accessible way (and subsequently, in many countries, legal way; think section 508 in the States, the DDA in the UK, etc.) would be to provide the content that's being loaded/adjusted by your link on a separate page, and use the URL for that page as the link's href instead. You would then use javascript to stop the event on the link from actually redirecting the page for those browsers which have it enabled.

That way you have fallback content for users without javascript, you stay legal, and you keep everyone and their dog happy :)