My previous solution to this was built on Phark’s “Accessible Image Replacement” technique. It works by pushing the text really far to the left (9,999 pixels) which makes sure it’s there for screen readers but hidden from users (unless someone has a display that’s able to show nearly 10,000 pixels to the left of the container in question). The problem seems to be that some browsers, like the one on the iPad, render a 9,999px box even though it’s not visible. This affects performance, especially for animations.
Well, there’s a better way. It works similarly, but instead of pushing the textual content so far left that we’re sure it’s outside the visible area, we push it just outside the box to the right. The advantage is that even without knowing how long the text is, we know exactly how far to push it to make sure it’s completely out of the box. So if you’re asking “How do I make a background image clickable?” This is the new answer. It’s easy, just follow these steps and I’ll show you how to make a clickable background image like this:
Start with just a link exactly as you would make it for any other purpose, and make sure to give the link an id so that we can use that to apply our styles:
<a href="http://ran.ge/" title="Professional WordPress Development" id="range-logo">Range Web Development</a>
That’s all the (X)HTML you’ll need to make your background image clickable. Your link should look something like this: Range Web Development
So, how can we make a background image a clickable link? It turns out it can be done with a clever CSS trick. Let’s get started by adding the background image and make the link the same size as the image (so you can see the whole image). Since an anchor tag isn’t a block level element, we need to force it to display as “block” so that we can specify the size:
#range-logo { background-image:url(http://ran.ge/content/uploads/2009/11/logo-trimmed.png); display:block; height:100px; width:460px; }
At this point it should look something like this: Range Web Development
Now all we need to do is hide the text. This can be done using “text-indent” to indent the text just outside the containing box, using “white-space” set to nowrap to keep the text from wrapping back into the box, and using “overflow” to hide content outside the box like this:
#range-logo { background-image:url(http://ran.ge/content/uploads/2009/11/logo-trimmed.png); display:block; height:100px; overflow:hidden; text-indent:100%; white-space:nowrap; width:460px; }
And the finished product looks like this:
And there you have it – a quick CSS trick with clean markup that turns your background images into clickable links. The best thing is, these don’t adversely affect your SEO and can even be easily used inside of header tags if needed!
Update:
I was asked how to add a border. Here it is with a CSS border:
#range-logo { background-image:url(http://ran.ge/content/uploads/2009/11/logo-trimmed.png); border:1px solid #CCC; display:block; height:100px; overflow:hidden; text-indent:100%; white-space:nowrap; width:460px; }
That obviously works, but the border is too close for my liking and adding padding causes our image to be out of place. Here’s the solution:
#range-logo { background-image:url(http://ran.ge/content/uploads/2009/11/logo-trimmed.png); background-position:5px 5px; background-repeat:no-repeat; border:1px solid #CCC; display:block; height:100px; overflow:hidden; padding:5px; text-indent:100%; white-space:nowrap; width:460px; }
Basically we’re adding 5 pixels of padding all around, re-positioning the background image to 5px in from the top and left, then setting the background image to not repeat. Now our border looks nice:
As a quick note, if you’re using “box-sizing: border-box;” you’ll need to adjust the width and height in the CSS to be the width/height of the image plus the padding, so in this case 470px × 110px.
I have been trying to make the image have a css border as well, although the border always ends up around the text off to the side.
I just added an example to the end with a border.
I have a issue on how to make the top image clickable …. any thoughts? Also maybe you can help with a solution to an additional issue. I have the bottom image set to no-repeat, yet it still repeats on x… and thoughts?
.footerzig{background: url(“http://www.iselaespanadesignstudio.com/wp-content/themes/twentytenchild/images/zigzagf.png'”), repeat-x scroll 0 0 transparent;
clear: both;
height: 154px;
}
.footerzigover{background: url(“http://www.iselaespanadesignstudio.com/wp-content/themes/twentytenchild/images/idea.png'”), no-repeat scroll 0 0 transparent;
clear: both;
height: 154px;
}
I have a issue on how to make the top image clickable …. any thoughts? Also maybe you can help with a solution to an additional issue. I have the bottom image set to no-repeat, yet it still repeats on x… and thoughts?
.footerzig{background: url(“http://www.iselaespanadesignstudio.com/wp-content/themes/twentytenchild/images/zigzagf.png’”), repeat-x scroll 0 0 transparent;
clear: both;
height: 154px;
}
.footerzigover{background: url(“http://www.iselaespanadesignstudio.com/wp-content/themes/twentytenchild/images/idea.png’”), no-repeat scroll 0 0 transparent;
clear: both;
height: 154px;
}
Life saver! Thank you so much! Works great!
You are a legend, thank you! 🙂
Thank you for the great css trick! The only thing that makes the text appear again, is searching for it (ctrl+f). But i think no one would do that…
Great trick Aaron! It did the job fine on my drupal site in Firefox.
In all the other browsers the link kept showing at the right end of the backgroundpicture.
Nevertheless, thanks so much for sharing!
Weird. I’m guessing you have some other CSS that’s interfering because I’ve tested this in firefox, Chrome, Safari, and Internet Explorer (all the way back to IE6)
Hey Aaron,
Thanks for the code.
I got a small problem here.
My idea is to have this:
BODY
IMAGE (Clickable)
WRAPPER (margin: 0 auto)
Page Contents…
But my background image link is not working.
I guess its because of the #wrapper code with “margin: 0 auto” which comes immediately below it.
z-index changes aint working either.
Any ideas? This thing is getting on my nerves.
Thanks in advance… 🙂
With the wrapper BELOW it you should be fine. Can you link to where you’re having the problem?
Great solution, thank you!
If you want to get this to work also in IE6 and IE7, the background image style should not (only) be applied to the a tag, but (also) to a surrounding div container.
I don’t usually target IE6 or IE7, but I to have Virtual Machines with them for testing when needed. I just spun them up and tested and it works just as is in both of them.
This is very nice. I have a question: is it possible to add a _blank “target” in the CSS so that the new page opens in a new window? 🙂
There are CSS properties in the proposed CSS3 spec that are supposed to do this:
However, as far as I know this isn’t supported by any browsers yet.
You can add target=”_blank” to the HTML or add some JavaScript to handle it.
Great trick. I’m trying to use this to have 5 icons in a row but I can’t seem to control their placement. I want to be able to center them in a div, but can’t figure out how.
Sincerely,
A css-learner
Maybe link to the code you’re working with (or use http://jsfiddle.net/ to set up an example). Centering multiple items can be a little tricky some times.
Hey Aaron, thanks. I figured out a way to make it work by using your trick combined with an unordered list, in a div that I gave an id, then controlled it’s left indent to make it visibly center. Thanks again!
For positioning the image within the padding box, why not:
background-position: center center;
That would work too and is probably a better option.
I’ve tried this, but my image stays on the left side. This image link is located in div (fluid grid layout):
#Arrow { clear: both; float: left; margin-left: 0; width: 100%; display: block; text-align: center; margin-top: 10%; }
It looks like it’ll always be on the left because you have float:left defined in your CSS.
I prise the Lord for You and Google – thank you Aaron. After a whole day to figure out the problem, you safe me. I have only to use a class instead of an ID in my case and it works wonderful in IE FF and Chrome.
Best regards
Marcus
Hi Aaron
Sorry if this is low level stuff but Ive just created an Image and used Css to display it. No HTML yet.
}
#body .header ul{
background: url(“images/get in touch.jpg”) no-repeat 790px 0px;
}
the href in the html is
href=”contact.html”>
All id like to do is make the image clickable to this ref.
Any easy way of adding to the css ?
Any feedback appreciated
Bryan
First, those CSS rules wouldn’t work without HTML. Specifically you need a ul inside an element with the class header inside an element with the ID body.
Second, semantically it makes sense to use a link to link something.
Lastly, you can’t do that with just CSS. You’ll need HTML or JavaScript to link the element that has the images as the background.
Thanks for response got around by doing
this:
Was wondering if you knew what was missing from this search code. I desperately want a basic site search field on my site but have had no luck so far. Any feedback would be really appreciated. And once again sorry if its low level stuff but Im literally a nube and teaching myself but this codes got me stumped.
}
Go
}
Thanks a lot! Saved me a lot of time fixing a design issue in one of my websites.
Instead of using the “text-indent” and “overflow” CSS to hide my text I just did not include any text in my link:
The image is still clickable and no extraneous text!
Only tested on IE 8. Maybe I missed the point of the text in the first place? But figured I would share anyways.
Forgot to say Thank You! for posting this in the first place. It helped me out a lot.
Also, I guess I can’t post html in the comment box. I will try again:
[/lang]
Simply showing the lack of text within the link.
The reason for the text is so that screen readers (and search engines) have text to process so they know what the link is about. Imagine being blind, having the site read to you, and having no text at all for the link in question.
Strangely enough, at least for me, this only works on FF. Has no effect on Chrome, IE (8) or Opera.
This definitely works in all modern browsers including Chrome, IE8, and Opera. Maybe something else in your CSS is causing a conflict of some kind?
Perhaps it has something to do with the absolute positioning I was using on the respective elements!?
Hi, Brett
Yes, it’s the absolute positioning — it throws off the use of % in test-indent. If you duplicate your width info here, it works again. E.g.:
width: 364px; text-indent: 364px;
HTH, Rupert
Thanks for your help with this – it worked brilliantly.
Hi Aaron, I much appreciated effort of putting up info on a web.
Any possible thoughts for 4 level dropdown menu based on graphic buttons? Your tip haven’t resolved issue.
Many thanks in advance for any possibility thoughts.
Michal.
I think I found a possible solution: Sometimes just needs to talk to yourself and the solutions appears as the answer of UNIVERSE 🙂 Thank you for inspiration.
I am having trouble getting this done, Will this work on a Blogger template
This will work anywhere you can do HTML and CSS
I so wish I’d have found your site earlier, love the way you build the code incrementally and add the highlights, so easy to follow. Thanks for posting.
Thank you! This was SOOO helpful!
great tutorial, thanks for share and help
Great post. I’m facing many of these issues as well..
Thanks for the tutorial! It worked like a charm.
Made one adjustment, as I’m working within several layers of wrappers. In order to correct my positioning, I added the following before the background-image line.
margin-top:-10px;
margin-left:10px;
Thank you so much! I was almost losing hope that there is a solution for this problem but yours is working perfectly! Plus a good explanation!
Wouldn’t it be simpler to use the div style=”visibility:hidden” tag for the text instead of shoving it around the screen? Or am I missing something?
The problem is that screen readers don’t read that text.
Then perhaps set the font to 1px and change the color to something that won’t be so easily noticed.
People can set a minimum font size in their browsers. Someone with poor eyesight could set that to 18px or even higher, which would override your 1px size. Also, since this technique is for using a background image, you can’t just match the foreground color to the background color.
i have my backgroundimage of orbit and its planets,how can i made those planet to act as a link…though it is in circular way
Often you can use rounded borders to do circular objects.
Thanks very much for this. Works like a charm.
This is offering some great ideas for a related issue I have, but I have a suggestion regarding hiding the link text.
Instead of moving the text way off to the side, or at all, why not just set the font size to 0px? I tested it with firebug on this very page, on the step where you show the text still visible over the image. It disappears just fine, and the link still works.
People can set a minimum font size in their browser which will override your 0px setting. In FireFox, go to preferences -> Content -> Advanced and you’ll see that you can change the “Minimum font size”.
I need to apply this to my particular code in WP. The categories show in a widget with the category name above the thumb image for the featured article of that category, followed by an excerpt below that. I don’t need to vanish the text, but do need to have a different bg image for each category listed, as there are three of these categories across the page from left to right. Idk now to specify the css to do that. The code looks like this for each category box:
Category 21 Name
and changes only for the data-catid and actual name.
How do I target just this link for this category so it will have a unique bg image? I know it has to be for the container of the link, which appears to be just the h3. Below this span4 is a ul listing more articles in that category, and nothing else. Any ideas?
Sorry, idk how to mark the code so it own digest like that. Lets try leaving off the first
h3 class=”category-title color-none”>
a class=”tab_title active” data-catid=”21″ href=”http://www.domainNameHere.com/category/earthstar-traveler/”>EarthStar Traveler
/h3>
Almost. Here’s the html minus the opening angle brackets:
div class=”span4″>
h3 class=”category-title color-none”>
a class=”tab_title active” data-catid=”21″ href=”http://www.domainNameHere.com/category/category-21-name/”>Category 12 Name
/h3>
Dude, I’ve been trying to make this happen all day and your code finally worked! Thank you!
This is a great article. Perfect for what I needed!
This might be a long shot but I’m hoping you can help me! I’m trying to implement your technique with a full screen background image… but no luck. Can you peek at my code and tell me if/how it can be done?
HTML:
CSS:
html, body {
overflow: hidden;
height: 100%;
width: 100%;
padding: 0;
margin: 0;
}
#full-screen-background-image {
z-index: -999;
min-height: 100%;
min-width: 1024px;
width: 100%;
height: auto;
position: fixed;
top: 0;
left: 0;
}
Thanks in advance if you can offer any solutions! I’ve been working on this for 2 days now, trying various things I’m finding online, but nothing has worked yet.
Sherry
Hey Sherry, this isn’t really the right technique for a full-page background image. Most of those use javascript to listen for clicks on the body that originated outsize the content area, and CSS only for adding the background image to the body or html tag.
hi Aaron
So i am trying to get the clickable background image to have 4 separate links.
HdrUserControl.acsx provides the id’s
And then the Master.css is as follows
div div#headerContainer
{
position: relative;
padding: 10px 0 15px;
}
#headerContainer img
{
display: block;
width: 320px;
margin-bottom: 28px;
}
.headerLinks
{
position: absolute;
right: 0;
bottom: 15px;
}
.headerLinks ul { float: right; }
.headerLinks li
{
float: left;
margin: 0;
padding: 38px 15px 0;
font-size: 12px;
background: url(../Images/master02.jpg) no-repeat -689px 0;
}
.headerLinks li.headerLinksPrint { background: url(../Images/master02.jpg) no-repeat -800px 0; }
.headerLinks li.headerLinksEnquiry { background: url(../Images/master02.jpg) no-repeat -927px 0; }
.headerLinks li.headerLinksContact { background: url(../Images/master02.jpg) no-repeat -1030px 0; }
Am not sure how to add the ids to the image sections that are already defined?
thanks
Mark
Unfortunately, what you need is going to be pretty different from what this tutorial does. Look at breaking the image up or possible putting it on a container and then layering the links over the top (still using the text-indent to hide the text from the links)
I am a serious CSS noob, so I can’t get this working at all.
Please help
Can you be more specific about what exactly isn’t working? Just copying and pasting the last bit of code should work, just put in your own image.
i cant get the link to be on top the image like the first picture.
just to be clear, i’m putting the first code in the html file, and everything else in css stylesheet?
Yes, the HTML would go in the HTML file and the CSS could go in a style tag or in an separate CSS file. Just make sure that the ID on your link matches the ID being used in your CSS.
I’ve found another solution to this problem. replace ] with >
This will hide the text, from users but still leave it for screen readers, while replacing the block with an image. I used an animated gif sprite. It flashes on hover. Pretty nifty if I say so myself.
The image is 2 blocks high and has 2 frames. In the first frame of the animation I have 2 buttons, one on top of another both exactly the same. In the second frame, I have the same thing but the bottom button is slightly brighter. When you hover over the button it appears to flash. When the button is in its normal state, it’s still animated but doesn’t appear to be since the top half of both frames are the same. In essence I have 3 buttons exactly the same (top-left, bottom-left, top-right) while the last one (bottom-right) is different.
Here’s the code.
HTML:
[a class=”button” id=”listen” title=”Listen” href=”javascript:void()” target=”_self” style=”text-decoration: none”][span id=”center” title=”Listen”]Listen[/span][/a]
CSS:
#center { text-align: center; margin: auto; }
/*– Hide the link text –*/
.button span
{ display: none; }
.button
{
text-align: center;
display: block;
width: 117px;
height: 30px;
background-position: 0 0;
background-repeat:no-repeat;
}
/*– Button Hover –*/
.button#listen:hover { background-position: 0 -30; }
/*– Button Image –*/
.button#listen { background-image:url(‘../images/buttons/Grunge_css_listen.gif’); }
The problem with display:none on the text is that screen readers and search engines ignore it.
Thanks for a great article. I used your method when I found it too difficult to set the size of a link with a foreground image that would work consistently across all browsers at all resolutions.
I made part of the background image transparent and set a background color, and the background color shows through the transparent parts – this means you can set a different background color to show when the link takes focus. This is easier than setting up different background images. You can see this on the menu button on my site jamesrmeyer.com (note that the menu button is designed only to show on small devices, so if using a desktop browser, you will need to reduce the window size to see it.)
When I used this method, I found that text-indent set 100% did not work in the Android browser on my Samsung phone and the text was visible. Absolute positioning was not involved (see Brett’s comment). When I changed it to the defined width value, it worked okay. So unless there is some reason for setting percentage, such as an element where the width can change, it would seem better to use the same width value for the text-indent value.
Nice tutorial. It works !