Consider the following HTML:
<ul>
<li>
<h2>Item 1</h2>
<p class="subline">Meta information bla bla</p>
<div class="description">
<p>Paragraph one</p>
<p>Paragraph two</p>
</div>
</li>
<!-- More ... -->
</ul>
I'd like to link each of the li
s to a link. As proof of concept, I give you this invalid code:
<ul>
<li>
<a href="http://www.google.com/search?q=test+1">
<h2>Item 1</h2>
<p class="subline">Meta information bla bla</p>
<div class="description">
<p>Paragraph one</p>
<p>Paragraph two</p>
</div>
</a>
</li>
<!-- More ... -->
</ul>
Obviously, this won't validate because I can't have block-level elements inside inline elements.
ED开发者_开发问答IT: As it turns out, the code above is valid in HTML5. Problem solved.
I need to find another solution:
Insert an a
tag into each block level element
I considered adding identical h2 > a
, p.subline > a
, and div > p > a
tags, but I'd like to have a hover state using :hover
that affects the whole area of the link, so that won't work.
Using an onclick event
I have used Javascript to solve this problem before (li.onclick = function() { window.location.href = ...
), but then I can't use the middle mouse key to open in a new window. This affects usability, depends on Javascript, and is, frankly, super annoying.
Making the block-level elements inline:
<ul>
<li>
<a href="http://www.google.com/search?q=test+1">
<span class="title">Item 1</span>
<span class="subline">Meta information bla bla</span>
<span class="description">
<span>Paragraph one</span>
<span>Paragraph two</span>
</span>
</a>
</li>
<!-- More ... -->
</ul>
Most likely, display: block
would need to be applied to some of or all of those spans to make them behave.
This is valid HTML, but it's really kind of awful.
Does anyone know the best way to tackle this problem?
Use HTML5:
http://davidwalsh.name/html5-elements-links
HTML5 presents a simpler line of thought with HTML than XHTML. And quite honestly, it's a much needed simplification. One of those simplifications is the ability to wrap block-level elements like DIVs, H-tags, and P's with basic A elements. You read that correctly: wrap block-level elements with A tags.
Personally, I've never worried about this. Yea, it's technically invalid, but I'm a fan of pragmatic validation.
I totally sympathize with your frustration. I think you've summed up the problem and the common approaches to address it well. I've gone both routes you've suggested in various situations.
First, another, even more problematic(!) option. I don't condone the following as a best practice! ...But you could add it to the list that may fit in limited circumstances.
http://jsfiddle.net/peteorpeter/J4sT9/
Basically, if you can stomach using hefty portions of absolute positioning and fixed heights, you can make the title a link and cover the other elements. It's quite fragile and rigid, really. You also can't have a background on the link or it will obscure the other elements.
Ok, once you get the puke taste out of your mouth after looking at that mess, I think you should:
- Embrace the nice semantic markup you started with
- Add a link in it somewhere that looks pretty and clickable
- In JS, hide the link above and route clicks from the
<li>
to the hidden link - In JS (or CSS 2+), enhance the hover effect on the
<li>
Slightly altered markup:
<ul>
<li>
<h2>Item 1</h2>
<p class="subline">Meta information bla bla</p>
<div class="description">
<p>Paragraph one</p>
<p>Paragraph two</p>
</div>
<a class="link-for-no-JS" href="buystuff">Item 1</a>
</li>
<!-- More ... -->
</ul>
Nothing too groundbreaking there, just basic progressive enhancement. Folks with less capable browsers have to hunt for a link and might not get any hover effects (but it could still be a handsome, usable interface); folks with more advanced browsers get an even more intuitive and responsive experience.
In the past I have solved this exact issue by putting the link in the heading then propagating it to the li using Javascript. That way most people get the desired effect and if JS is off it works anyway. When you propagate the link set a class as well. It's a little extra complexity but it is valid HTML. Depends on your priorities.
// psuedocode
on document ready {
els = getElementsByClassName("mylinks")
for el in els {
li = el.parentNode.parentNode;
li.onclick = function() {window.location = el.href}
li.className = "liHover";
}
}
There is another hack which depending on situation can work. Pull the a
element out of the natural rendering flow using position: absolute
and make it's height and width large enough to cover the area in question. A high z-index
value can also come handy. It's a hack though.
精彩评论