Please help me to build a sprite

what is the correct way to use a sprite for an image link?
here is the situation:
i have 3 buttons with different hover states. so, 6 images on the sprite graphic.

how should I set up my html and css so that:

  1. it is just a pure image link, no text visible with css and images on
  2. it does not use an unordered list (is just a button on the page somewhere)
  3. search engines can still index the text link
  4. google doesn’t have issues with “hiding text”
  5. it is accessible to screen readers and the like
  6. works images off/css on, css off/images on, css and images off, css and images on

there is a huge to-do at my work right now about what is the “right” way; there are many tutorials online and I’ve looked at about a billion of them, and they don’t like any of them. someone pls help :confused:

Well you got me. I don’t have win 7 so I can’t comment. If it’s indeed the case, then prob need to give the body a z-index of 1 in order to set a correct stacking order.

Really. Which version? When you’ve found that none of my discussed demos break “willy-nilly” in any versions of IE you can come back and eat your words…

Forgot… that left:-999em gets ignored in 6 on 98/2k but not XP. Use text-indent and you’d be better off, though really that defeats the point of using image replacement since images off CSS on it’s /FAIL/ in those browsers.

There’s a reason I don’t just blindly trust IETester or MultipleIE, and instead have VM’s of 98, 2k and XP installed with the browser best suited to each as the primary. (5.5, 6 and 7 respectively)

… and here’s how I’d approach eric’s demo. (also swapped it to a 8 bit .png with the GAMA line stripped since that shaves 10k off the image)

http://www.cutcodedown.com/for_others/ericWatson/template.html

As with all my examples the directory:

http://www.cutcodedown.com/for_others/ericWatson

is unlocked for easy access.

Rather than sliding around the background position, which takes a LOT of code and has a LOT of redundancies since it’s not just a long declaration, you also have to restate BOTH dimensions, I just set the anchor itself to overflow:hidden, and then move the nested span around.

It’s nice to be able to replace:


/* Default State */
#nav #a{background-position:0 0;} 
#nav #b{background-position:-150px 0;}
#nav #c{background-position:-300px 0;}
#nav #d{background-position:-450px 0;}
#nav #e{background-position:-600px 0;}
/* Hover/Focus State */
#nav #a:hover,#nav #a:focus{background-position:0 -50px;}
#nav #b:hover,#nav #b:focus{background-position:-150px -50px;}
#nav #c:hover,#nav #c:focus{background-position:-300px -50px;}
#nav #d:hover,#nav #d:focus{background-position:-450px -50px;}
#nav #e:hover,#nav #e:focus{background-position:-600px -50px;}
/* Active State */
#nav #a:active{background-position:0 -100px;}
#nav #b:active{background-position:-150px -100px;}
#nav #c:active{background-position:-300px -100px;}
#nav #d:active{background-position:-450px -100px;}
#nav #e:active{background-position:-600px -100px;}
/* Current Page */
#home #nav #a{background-position:0 -150px;}
#about #nav #b{background-position:-150px -150px;}
#services #nav #c{background-position:-300px -150px;}
#map #nav #d{background-position:-450px -150px;}
#contact #nav #e{background-position:-600px -150px;}

with


#demoMenu a:active span {
	display:block; /* prevent IE render state sticking and not working IE 7 */
	top:-50px;
}

#demoMenu a:focus span,
#demoMenu a:hover span {
	display:block; /* prevent IE render state sticking and not working IE 7 */
	top:-100px;
}

#demoMenu .current span {
	top:-150px;
}

#demoMenu .home span {
	left:0;
}

#demoMenu .about span {
	left:-150px;
}

#demoMenu .services span {
	left:-300px;
}

#demoMenu .map span {
	left:-450px;
}

#demoMenu .contact span {
	left:-600px;
}

I also tossed in coloration for people browsing with images disabled but CSS enabled, which helps prevent IE 6 and 7 from ‘sticking’ in a on state (as Eric’s examples do occasionally) and then also have the display state change on a absolute for similar reasons. (7 won’t even render the pseudo-states without those!). The float on the LI also got axed since IE7 was stair-casing based on the line-height since the floats lacked height on them… I find it easier to just set the LI to display:inline and then pretend they don’t even exist.

I understand. Well sort of. I don’t really work as a web designer (as in don’t make much money doing it) I only pretend to be one. OK. Here is the whole tut of mine http://www.visibilityinherit.com/code/sprites.php. If I were you I would just use the first option to hide the text. That will show the text in three out of four scenarios and is the most SEO friendly of the bucnch. That should give your employer piece of mind.

Here is a button sprite. http://www.visibilityinherit.com/code/buttons.php

If you want text to be there in all those scenarios then use method two here http://www.visibilityinherit.com/code/image-replacement.php

How about IE8 win7 x64 for starters:

Where it appears and dissapears based on screen width. It always shows through here in Win2k IE6 but not on WinXP IE6…

Z-index to hide content span without effecting the parent does not work reliably. Damned shame too because it would be a very elegant solution to the problem. It just doesn’t work right all the time. The failure rate is likely below 10%, but that’s still a LOT in my book.

It’s why I’d use the gilder-levin empty element technique instead, and combine it with the overflow trick… gimme a couple minutes I’ll toss together a demo of that approach using your images. It’s nice because you have to state the background-positions a hell of a lot less.

Paul O’B invented Gilder-levin image replacement? I think not. He may be the one who taught it to you, but I’m pretty damned sure he’s NOT the one who came up with it. You might want to research who Tom Gilder and Levin Alexander are. (though they put the empty tag before the content, without top/left declared which now breaks randomly in FF 3.6 - like damned near everything else broken in 3.6)

The latter technique with the z-index breaks willy-nilly in certain versions of IE BTW, so much like using text-indent I wouldn’t advise using that method.

@pasNon, if you’ll show us the images you are trying to work with, we could give you a real-world demo case. In the meantime, have a look at this rewrite I did for someone not too long ago:

http://www.cutcodedown.com/for_others/MrMoolah/

it uses one image to do all four of the menu buttons and their states.

http://www.cutcodedown.com/for_others/MrMoolah/images/mainMenu.png

It does so using gilder-levin image replacement so user agents who don’t see our images get text.

One of the advantages of gilder-levin you can leverage when making sprites is to declare the dimensions of each anchor (at least on the y axis) with it set to display:block or float, and set overflow hidden. Then instead of having to restate all your background-positions on each and every one, you can just slide the nested empty tag (I use span usually) around instead. Basically I use background-position to set the horizontal offset, but on hover I just slide it up with a negative value on TOP.


#mainMenu a {
	position:relative;
	float:left;
	display:inline; /* fix IE float oddities */
	overflow:hidden;
	height:55px;
	text-align:center;
	text-decoration:none;
	color:#FFF;
	background:#F80;
}

#mainMenu a:active,
#mainMenu a:focus,
#mainMenu a:hover {
	background:#18F;
}

#mainMenu .home a {
	width:198px;
}

#mainMenu .services a {
	width:231px;
}

#mainMenu .links a {
	width:176px;
}

#mainMenu .contact a {
	width:239px;
	margin-right:-8px; /* prevent IE from incorrectly wrapping these */
}

#mainMenu a span {
	position:absolute;
	top:0;
	left:0;
	width:256px;
	height:165px;
	background:url(images/mainMenu.png) 0 0 no-repeat;
}

#mainMenu a:active span,
#mainMenu a:focus span,
#mainMenu a:hover span {
	top:-55px;
	display:inline; /* IE7 won't render state change without display status change */
}

#mainMenu a.current span {
	top:-110px !important;
}

#mainMenu .services a span {
	background-position:-198px 0;
}

#mainMenu .links a span {
	background-position:-429px 0;
}

#mainMenu .contact a span {
	background-position:-605px 0;
}

Pretty simple.

I wasnt saying i was wrong - just the opposite. However… there is no js involved. Not even a little. If it’s not wrapped in script tags it’s not js. It’s only a trick to keep from jumping to top of page when clicked. There are other (non JavaScript words) that does the same.

what screen readers are you talking about? I use it all the time and most of my websites don’t have any negative inpact of it

Eric I didn’t say you’re wrong, I only said that I wouldn’t use the first solution since(no mather how small) there was JS involved. But like I said I wouldn’t :slight_smile:

i’m not trying to devalue your solution - i think it’s great. i’m at odd ends with them because i just started working here, they never used sprites before and are battling me every step of the way on many “new” coding techniques. i’m just trying to find validation to actually be able to use them :confused:

Well… you don’t want to place it off screen and you don’t want to hide it behind images so how does your employer propose to do it? Hiding it behind an image does not penalize you.

Your only other option is to do as I did here and hide it with no height only padding but it won’t show text in all scenarios. http://www.visibilityinherit.com/code/sprites-demo.php

thank you.
also a problem i might have mentioned-- my employer is suddenly adamantly against hiding text with images because they believe google penalizes you if you use it because it was a popular spam technique. do you know this to be true or false?

hi eric, thank you for replying. i am new to css and sprites/image replacement particularly so i can’t understand exactly how i would apply your solution to a sprite button with hover. would you mind laying it out a bit for me? i really appreciate it. :slight_smile:

I posted the only solution there is.

Here it is in a sprite. http://www.visibilityinherit.com/code/spriteric-image-replacement-demo.php

I have a rule of thumb with the way I post. I really don’t enjoy being wrong so “I” usually only post answers to questions that I know 100%. My solution does NOT use JS it is only in the href to prevent launching to top. Reading usually prevents this mistake. Simply add a url to the href which is what OP needs anyway. negative text indent is fine however does not fulfill OPs requirements which is why I did not include it.

sorry, you are right, i did also mean to add “does not use javascript” to that list of demands :wink:

negative text indent though, should never be used. there are screen readers that actually do read css and they will not read something that is text indented.

do you have a solution that does not involve a text indent though? i’m interested to see it.