简体   繁体   中英

Nested text links in HTML

In HTML nested links are not permitted. However, for my purpose (text notes which sometimes refer to whole sentences and sometimes to just one single word within already anotated sentences) I need them. So I have to find a way to solve this problem.

However, all I have now is a basic idea on how it should look and behave. The following mock up shows two links: one to target A, one to B. The "outer" a link is, the lower is the line under it. A is the outer link, thus, its line is lower than that of B. Clicking on the lines of a link should always lead to the target of that link - even if the text above that line is the text of an inner link.

I've tried to show that intended behaviour with hover colors: Blue for A, pink for B.

嵌套测试链接模型

Any ideas how I could realize this in HTML with the help of CSS (and maybe SVG?). I'd prefer solutions without scripting, but any suggestions are welcomed.

You can use <span> s inside links:

 a {color: #00f; border-bottom: 1px solid; text-decoration: none;} a span {color: #66f; text-decoration: underline;} 
 <a href="#">Hello, this is link. This is <span>inner link</span> here.</a> 

A small problem or extra work is, you need JavaScript to make them follow the links.

But as you asked, you can get the UI Effect without any scripting, but the following of link, definitely needs scripting!

Expanding on the answer from @connexo, you can wrap them all in a span and use a border-bottom on that.

 .split-link { border-bottom:1px solid blue; padding-bottom:1px; /* for visual reference only */ } .split-link a { text-decoration: none; } .split-link a.inner-link { text-decoration: underline; text-decoration: red; color:red; } 
 <span class="split-link"> <a href="#outer">Hello, this is a link. It has an </a> <a href="#inner" class="inner-link">inner link</a> <a href="#outer"> here.</a> </span> 

You will want to stay within valid HTML, so your only chance (aside of JS) is splitting the outer link into two links.

<a href="#outer">Hello, this is link. This is </a><a href="#inner" class="inner-link">inner link</a><a href="#inner"> here.</a>

.inner-link { color: #66f; text-decoration: underline; }

This will split the blue line in your example into two parts as well, which I assume you do not want. But it's not possible otherwise.

Use JavaScript for best results

I know:

I'd prefer solutions without scripting,

but…

any suggestions are welcomed .

You can add an inline onclick handler to a child span :

<a href="#A">AAAA <span onclick="event.preventDefault(); window.location.assign('#B'); return false;">BBBB</span> AAAA</a>

Or, to be DRY, pass in a reference to the handler instead:

<a href="#A">AAAA <span onclick="embedLink('#B');">BBBB</span> AAAA</a>

Definition of handler:

function embedLink(url) {
    event.preventDefault();
    window.location.assign(url);
    return false;
}

Working example:

 a { display: inline-block; text-decoration: none; color: blue; border-bottom: 1px solid blue; padding: 1px; } a .annotation { color: fuchsia; border-bottom: 1px double fuchsia; background-color: white; } a:hover { background-color: lightblue; } a .annotation:hover { background-color: lightpink; } 
 <a href="#A">AAAA <span data-href="#B" class="annotation" onclick="event.preventDefault(); window.location.assign(this.getAttribute('data-href')); return false;">BBBB</span> AAAA</a> 


With JS, you can handle other possibilities as well:

  • Open in new window . Use: window.open() instead of window.location.assign() .
  • Copy to clipboard . Add an event listener to the context and copy events on the parent link. In the handler, use document.execCommand('copy') to grab the url from the clicked child span instead; perhaps its URL is stored in a data-href attribute.
  • Display URL in status bar . Add a mouseover event listener. In the handler, set window.status = url .

Thank your all for your answers! They all have inspired me!

After some hard thinking and merging your answers together I came to the following solution whose greatest advantage is that the basic functions of all links work without JavaScript.

My main idea is to wrap all links inside a <span> element and, as connexo has suggested, to split up those links which contain links themself. Thus, the HTML skeleton of my above example looks like this:

<span>
 <a>AAA</a>
 <span><a>BBB</a></span>
 <a>AAA</a>
</span>

All JavaScript is associated just with the <span> . Onmouseover, it removes the hover-class from all ancestor <span> . Onclick, it takes the url of the first link child and redirects there.

The CSS is rather simple. It removes the underline from links and defines just how the span should look like (and behave in case of hover).

Another advantage of this design is that nested nested links are also supported, as you can see in the snippet below.

 function link_span_click(current_element,current_event) { current_event.preventDefault(); current_event.stopPropagation(); var target_href = current_element.getElementsByTagName('a')[0].href; window.location.assign(target_href); } function link_span_mouse_over(current_element) { while (current_element) { current_element.parentNode.classList.remove('link_span_hover'); current_element = current_element.parentNode; } var target_href = current_element.getElementsByTagName('a')[0].href; window.status = target_href; } function link_span_mouse_out(current_element) { while (current_element) { current_element.parentNode.classList.add('link_span_hover'); current_element = current_element.parentNode; } window.status = ''; } 
 a.nested_link { text-decoration: none; } span.link_span { cursor: pointer; display: inline-block; padding-bottom: 3px; background-color: white; border-bottom: 1px solid blue; } span.link_span_hover:hover { background-color: lightblue; } 
 <div> <span class="link_span link_span_hover" onclick="link_span_click(this, event)" onmouseout="link_span_mouse_out(this)" onmouseover="link_span_mouse_over(this)" > <a href="#a" class="nested_link">AAA</a> <span class="link_span link_span_hover" onclick="link_span_click(this, event)" onmouseout="link_span_mouse_out(this)" onmouseover="link_span_mouse_over(this)"> <a href="#b" class="nested_link">BBB</a> </span> <a href="#a" class="nested_link">AAA</a> </span> </div> <div> <span class="link_span link_span_hover" onclick="link_span_click(this,event)" onmouseout="link_span_mouse_out (this)" onmouseover="link_span_mouse_over (this)"> <a href="#a" class="nested_link">AAA AAA AAA AAA</a> <span class="link_span link_span_hover" onclick="link_span_click(this, event)" onmouseout="link_span_mouse_out(this)" onmouseover="link_span_mouse_over(this)"> <a href="#b" class="nested_link">BBB BBB</a> <span class="link_span link_span_hover" onclick="link_span_click(this, event)" onmouseout="link_span_mouse_out(this)" onmouseover="link_span_mouse_over(this)"> <a href="#c" class="nested_link">CCC</a> </span> <a href="#b" class="nested_link">BBB BBB</a> </span> <a href="#a" class="nested_link">AAA AAA AAA AAA</a> </span> </div> 

Still, there remains one problem: If a rather long textlink gets split up into to lines only the second (or last to be precise) line gets underlined.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM