Friday, February 6, 2015

Styling links with the rel attribute

One interface improvement I was planning to implement but have yet to do so is styling links with a favicon. This can be done via JavaScript, by getting the client browser to do the work, or simply with rel attribute styling.

HTML rel browser support - screencapIn HTML5, rel is supposed to take only a few values (w3-rel):

alternate
Links to an alternate version of the document (i.e. print page, translated or mirror).
Example: <link rel="alternate" type="application/atom+xml" title="W3Schools News" href="/blog/news/atom">

author
Links to the author of the document

help
Links to a help document.
Example: <link rel="help" href="/help/">

icon
Imports an icon to represent the document.
Example: <link rel="icon" href="/favicon.ico" type="image/x-icon">

license
Links to copyright information for the document

next
Indicates that the document is a part of a series, and that the next document in the series is the referenced document

prefetch
Specifies that the target resource should be cached

prev
Indicates that the document is a part of a series, and that the previous document in the series is the referenced document

search
Links to a search tool for the document

stylesheet
URL to a style sheet to import

However, that does not mean it cannot be used for other purposes.

AskTheCSSGuy (atc-cues) suggests the following code to be inserted in the head enclosed in style tags.

/* all A tags whose HREF attribute ends in .pdf */
a[href$='.pdf'] {
    padding-right: 18px;
    background: transparent url(icon_pdf.gif) no-repeat center right;
}

/* all A tags whose REL attribute equals pdf */
a[rel='pdf'] {
    padding-right: 18px;
    background: transparent url(icon_pdf.gif) no-repeat center right;
}

/*  all A tags whose REL attributes has the letters pdf somewhere mixed in*/
a[rel*='pdf'] {
    padding-right: 18px;
    background: transparent url(icon_pdf.gif) no-repeat center right;
}

/* all A tags whose REL attribute contains the value pdf, seperated from other values with a space */
a[rel~='pdf'] {
    padding-right: 18px;
    background: transparent url(icon_pdf.gif) no-repeat center right;
}

/* all A tags whose HREF attribute starts with mailto: */
a[href ^="mailto:"] {
    padding-right: 18px;
    background: transparent url(icon_mailto.gif) no-repeat center right;
}

/* all A tags whose CLASS attribute is popup */
a[class ="popup"] {
    padding-right: 18px;
    background: transparent url(icon_popup.gif) no-repeat center right;
}


a[href$='.doc'] {
    padding-right: 18px;
    background: transparent url(icon_doc.gif) no-repeat center right;
}

a[href$='.xls'] {
    padding-right: 18px;
    background: transparent url(icon_xls.gif) no-repeat center right;
}

a[rel ~='external'] {
    padding-right: 18px;
    background: transparent url(icon_external.gif) no-repeat center right;
}

Here’s the JavaScript code and the style (all in enclosed in head) that does pretty much the same thing. The code looks for links starting with “http” and then goes and gets the favicon for them. This is not a good method to identify external links as on Blogger / Blogspot, for instance, all links (even internal ones) have to start with http.

javascript looks for a ul tag with the class of "favilist". Then it goes through every link in that list and looks to see if the href starts with "http:", which would indicate that it's an external link. If so, it grabs the favicon off that domain name and inserts it before each link. If no favicon exists, it uses a locally stored image (external gif here) to indicate the link is external.

<script type="text/javascript">

function addLoadEvent(func) {

var oldonload = window.onload;

if (typeof window.onload != 'function') {

window.onload = func;

} else {

window.onload = function() {

oldonload();

func();

}

}

}

function faviconizeFavilist() {

if (!document.getElementsByTagName) return false;

if (!document.createElement) return false;

var ul = document.getElementsByTagName("ul");

for (var i=0; i<ul.length; i++) {

if (ul[i].className == "favilist") {

var links = ul[i].getElementsByTagName("a");

for (var j=0; j<links.length; j++) {

var hoststring = /^http:/;

var hrefvalue = links[j].getAttribute("href",2);

if (hrefvalue.search(hoststring) != -1) {

var domain = hrefvalue.match(/(\w+):\/\/([^/:]+)(:\d*)?([^# ]*)/);

domain = RegExp.$2;

var cue = document.createElement("img");

cue.className = "faviconimg";

var cuesrc = "http://"+domain+"/favicon.ico";

cue.setAttribute("src",cuesrc);

cue.onerror = function () {

this.src = "external.gif";

}

links[j].parentNode.insertBefore(cue,links[j]);

}

}

}

}

}

addLoadEvent(faviconizeFavilist);

</script>

<style type="text/css">

p, li {font:normal 12px/18px arial;}

h1 {font:bold 22px/28px arial;}

h2 {font:bold 16px/20px arial;}

.wrap {width:500px;}

img.faviconimg {

border:0;

width:11px;

height:11px;

padding:0 4px;

}

ul.favilist {list-style:none;}

</style>

A second version..

javascript looks for every link on the page to see if the href starts with "http:", which would indicate that it's an external link. If so, it grabs the favicon off that domain name and inserts it after each link. If no favicon exists, it uses a locally stored image (external gif here) to indicate the link is external.

<script type="text/javascript">

function addLoadEvent(func) {

var oldonload = window.onload;

if (typeof window.onload != 'function') {

window.onload = func;

} else {

window.onload = function() {

oldonload();

func();

}

}

}

function insertAfter(newElement,targetElement) {

var parent = targetElement.parentNode;

if (parent.lastChild == targetElement) {

parent.appendChild(newElement);

} else {

parent.insertBefore(newElement,targetElement.nextSibling);

}

}

function faviconize() {

if (!document.getElementsByTagName) return false;

if (!document.createElement) return false;

var links = document.getElementsByTagName("a");

for (var j=0; j<links.length; j++) {

var hoststring = /^http:/;

var hrefvalue = links[j].getAttribute("href",2);

if (hrefvalue.search(hoststring) != -1) {

var domain = hrefvalue.match(/(\w+):\/\/([^/:]+)(:\d*)?([^# ]*)/);

domain = RegExp.$2;

var cue = document.createElement("img");

cue.className = "faviconimg";

var cuesrc = "http://"+domain+"/favicon.ico";

cue.setAttribute("src",cuesrc);

cue.onerror = function () {

this.src = "external.gif";

}

insertAfter(cue,links[j]);

}

}

}

addLoadEvent(faviconize);

</script>

<style type="text/css">

p, li {font:normal 12px/18px arial;}

h1 {font:bold 22px/28px arial;}

h2 {font:bold 16px/20px arial;}

.wrap {width:500px;}

img.faviconimg {

border:0;

width:11px;

height:11px;

padding:0 4px;

}

ul.favilist {list-style:none;}

</style>

..and, in the final example..

the javascript looks for a div tag with the class of "blogentry". Then it goes through every link in that div to see if the href starts with "http:", which would indicate that it's an external link. If so, it grabs the favicon off that domain name and inserts it after each link. If no favicon exists, it uses a locally stored image (external gif here) to indicate the link is external. If you wanted to change the class name to suit your needs, make sure you find 'blogentry' in the javascript and change it to whatever class name you want.

<script type="text/javascript">

function addLoadEvent(func) {

var oldonload = window.onload;

if (typeof window.onload != 'function') {

window.onload = func;

} else {

window.onload = function() {

oldonload();

func();

}

}

}

function insertAfter(newElement,targetElement) {

var parent = targetElement.parentNode;

if (parent.lastChild == targetElement) {

parent.appendChild(newElement);

} else {

parent.insertBefore(newElement,targetElement.nextSibling);

}

}

function faviconizeDivClass() {

if (!document.getElementsByTagName) return false;

if (!document.createElement) return false;

var div = document.getElementsByTagName("div");

for (var i=0; i<div.length; i++) {

if (div[i].className == "blogentry") {

var links = div[i].getElementsByTagName("a");

for (var j=0; j<links.length; j++) {

var hoststring = /^http:/;

var hrefvalue = links[j].getAttribute("href",2);

if (hrefvalue.search(hoststring) != -1) {

var domain = hrefvalue.match(/(\w+):\/\/([^/:]+)(:\d*)?([^# ]*)/);

domain = RegExp.$2;

var cue = document.createElement("img");

cue.className = "faviconimg";

var cuesrc = "http://"+domain+"/favicon.ico";

cue.setAttribute("src",cuesrc);

cue.onerror = function () {

this.src = "external.gif";

}

insertAfter(cue,links[j]);

}

}

}

}

}

addLoadEvent(faviconizeDivClass);

</script>

<style type="text/css">

p, li {font:normal 12px/18px arial;}

h1 {font:bold 22px/28px arial;}

h2 {font:bold 16px/20px arial;}

.wrap {width:500px;}

img.faviconimg {

border:0;

width:11px;

height:11px;

padding:0 4px;

}

</style>

*(*This article is unfinished – it was scheduled to appear in the hope that it will be finished before, but since this message is here and until it is removed, the article is to be considered work in progress*)*.

Sources / More info: w3-rel, atc-cues, atc-zip, dblg-cues,

1 comment:

Thank you for commenting and rest assured that any and all comments are welcome, whether positive or negative, constructive or distructive. Unfortunately, if you comment in this view I might not know about - please use the regular (Desktop) view.
I am using Disqus for commenting, but Blogger is not showing it so your comments may end up not being displayed - tell Google about it!