Xiper

IMG: меняем рисунок при наведении

Автор: Александр Головко Дата публикации:

Одна из часто встречающихся задач при верстке — смена фона элемента при наведении мыши. Уверен, если речь идет о background, то проблем у тебя не возникнет. Хорошим решением будет подклеить картинки по методу спрайтов и по hover менять background-position. Тут нужно только не забыть, что IE6 не понимает hover для элементов не являющихся ссылками и ему нужно будет помочь.

А что если нужно менять не фоновый рисунок, а img? Например, какой-нибудь баннер при наведении как-то хитро подсвечивается? Трюк с background-position тут не пройдет. Нужно другое решение. Менять скриптом src? А может можно обойтись силами CSS?

Задача

Реализовать средствами CSS смену рисунка при наведении мыши. Рисунок расположен в img.

Решение

Склеиваем картинки, как в методе спрайтов:

склееные картинки верхний рисунок — обычный вид, нижний — при наведении

HTML код типичный для баннера — img внутри ссылки (естественно можно использовать не только ссылку, но и другой подходящий по смыслу элемент).

<a href="#" class="container">
	<img src="images/logo.png" width="120px" height="240px" alt=""/>
</a>

При наведении просто смещаем картинку вверх с помощью отрицательного margin-top.

.container{
	width:120px;
	height:120px; /* высота видимой части (одной картинки) */
	display:block; 
	overflow:hidden; /* чтобы нижнюю картинку не было видно */
}
.container:hover img{
	margin-top:-120px;
}

Ключевой момент: margin-top должен быть численно равен высоте видимой части картинки.

Ослиные костыли

К сожалению IE6 не поймет конструкцию ".container:hover img". Для него придется добавить expression (подробнее этот момент смотри в статье Псевдокласс hover в IE6).

* html .container{
behavior: expression(
          onmouseover = function() {this.className += ' hover'},
          onmouseout = function() {this.className = this.className.replace('hover', '')},
		  style.behavior = null
        );
}
* html .hover img{
	margin-top:-120px;
}

Как всегда, в боевых условиях вместо хаков используем условные комментарии.

Демо пример. Проверено в:

  • IE 6-8
  • Firefox 3.0-3.6
  • Opera 9.5-10.5
  • Safari 4
  • Chrome 5

Убираем expression (update by SelenIT)

Если контейнером является ссылка, то можно обойтись и без expression! У IE6 есть старый баг, что он иногда ленится перерисовывать содержимое ссылок под :hover-ом. Но если указать отдельно для .container:hover стиль, который явно даст понять IE, что ссылку надо перерисовать (подходит font-size:100%, background:#fff и подобные свойства), то и стиль для .container:hover тоже магическим образом начнет применяться.

То есть решение может выглядеть, например, так:

.container{
	width:120px;
	height:120px; 
	display:block; 
	overflow:hidden;
}
.container:hover{
	font-size:100%; /* специально для IE6 */
}
.container:hover img{
	margin-top:-120px;
}

Еще один метод — ни expression, ни дополнительного правила для IE6 (update by Татьяна Шкабко)

Другое решение задачи можно получить, если сдвигать картинку не с помощью margin, а с помощью text-indent. Саму картинку тогда нужно склеить немного иначе:

склееные картинки слева — обычный вид, справа — при наведении
.container{
	width:120px;
	height:120px;
	display:block;
	overflow:hidden;
}
.container:hover{
	text-indent:-120px;
}

Так как правило для hover упростилось, «пинать» IE6 нет необходимости. Конечно, если контейнер не ссылка, то, как и в предыдущем варианте, без expression не обойтись!

Демо пример. Проверено в:

  • IE 6-8
  • Firefox 3.0-3.6
  • Opera 9.5-10.5
  • Safari 4
  • Chrome 5

Материал

  • CSS Sprites w/out Using Background Images