Создаем динамические кнопочки-ссылки с помощью CSS

Чем привлекательны CSS – тем, что они часто, при создании тех или иных эффектов, позволяют заменить JavaScript. Вот и на этот раз каскадные таблицы стилей помогут нам сконструировать красивые динамические кнопочки.

Информацию, изложенную ниже, можно рассматривать как альтернативу способу создания универсальных графических кнопок и данный способ отчасти решает те же задачи.

Такие кнопки-ссылки:

  • Растягиваются горизонтально в зависимости от длины текста.
  • Могут иметь углы нужной формы, выполненной в рисунке.
  • Делают всю площадь кликабельной.
  • Остаются удобочитаемыми при отключении изображений.

Особенность кнопки заключается в ее динамике, т.е. меняется ее графическое представление в разных состояниях:

  1. по умолчанию;
  2. при наведении курсора;
  3. при нажатии на кнопку.

Динамическая кнопка с двойным эффектом

Создадим кнопку на CSS, которая имеет только 2 состояния: “по умолчанию” и “при наведении курсора“.

Наша кнопка основана на использовании тега a со вложенным в него тегом span, каждый из которых использует различные слои фонового изображения. Для получения возможности растяжки фона при увеличении размера кнопки по горизонтали задействуем так называемую технику “раздвижных дверей”. Вот так выглядит кнопка-ссылка в части HTML-кода:

<a href="#" class="button"><span>Динамическая кнопочка</span></a>

Как видите, код максимально прост. Далее нам нужно создать изображения кнопки в обоих состояниях. Для этого я воспользовался программой “Crystal Button“. Вот что у меня получилось:

ДефолтнаяПри наведении мыши
2 кнопки

Оба состояния кнопки мы поместим в одно изображение (для каждого из тегов a и span) и для смены с нормального состояния в “hover” будем смещать фоновое изображение по вертикали, CSS легко нам в этом поможет (о плюсах совмещения изображений в одно рассказано в статье “Оптимизация: используем одно изображение вместо двух”). Часть изображения, которая будет растягиваться в зависимости от текста, сделаем, к примеру, длиной в 350 пикселей (в зависимости от предполагаемой длины кнопок можно подобрать необходимую длину этой части). Высота нашей кнопки составляет 33 пикселя.

span
a

Для получения нужного эффекта раньше я прибегал к помощи JavaScript, CSS при этом вообще не использовался. HTML-код был следующим:

<a href="#" onmouseover="document.cat.src='button_hover.gif';" onmouseout="document.cat.src='button.gif';"><img src="button.gif" alt="Кнопочка"></a>

Соответственно, если у посетителя сайта отключен JavaScript, никакого эффекта наших красивых динамических кнопок он не увидит. Каскадные таблицы стилей помогут нам избавиться от этого недостатка.

Попробуем сделать точно такую же кнопку, используя CSS вместо JavaScript.

Код, которым оформим кнопочки “по умолчанию”:

a.button {
  display: block;
  float: left; /* чтобы кнопка не растягивалась на всю ширину родительского блока, а ограничивалась текстом */
  font: bold 12px arial, sans-serif;
  color: #555;
  text-decoration: none;
  background: url(button_r.gif) top right no-repeat;
  padding-right: 25px; /* отступ для "раздвижных дверей" */
  outline: none; /* убираем точечную обводку в FireFox, которая появляется при клике */
}
a.button span {
  display: block;
  line-height: 13px;
  background: url(button_l.gif) no-repeat;
  padding: 7px 0 13px 23px;
}

Необходимо учитывать, что высота строки и вертикальные отступы, заданные для span, в сумме должны с точностью равняться высоте изображения (в нашем примере – 33px). Если бы изображение не имело тени, то можно было бы просто указать высоту строки, равной 33px, тогда текст сразу поместился бы вертикально посередине.

Сейчас добавим эффект, который появляется при наведении курса мыши на кнопку:

a.button:hover {
  background-position: 100% -33px;
}
a.button:hover span {
  background-position: 0% -33px;
  color: #222;
}

Готово! Вот что у нас получилось.

Динамическая кнопочка

Динамическая кнопка с тройным эффектом

Мы пойдем еще дальше и добавим для нашей кнопки-ссылки еще один эффект, который проявляется при нажатии на кнопку. Соответственно для наших изображений мы добавляем еще одно состояние.

spana
изображение для тега span  изображение для тега a

Осталось дописать чуток CSS для третьего состояния кнопки-ссылки:

a.button:active,
a.button:focus {
  background-position: 100% -66px;
}
a.button:active span,
a.button:focus span {
  background-position: 0% -66px;
  color: #222;
  padding: 8px 0 12px 23px; /* опускаем текст на 1px */
}

Готово! Можно кликать!

СохранитьОтмена

Получается вполне симпатично, не правда ли? :)

По желанию, для всех трех состояний кнопки можно установить фоновый цвет, на случай, если в браузере пользователя отключен показ изображений. В таком случае достаточно классам a.button, a.button:hover и a.button:active добавить свойство background-color.

Исправляем баг

В браузерах Opera и Internet Explorer наблюдается следующий баг – в них всякий раз, когда кнопка “отпущена”, она не возвращается в состояние по умолчанию. Кстати, в ранних версиях Оперы такого бага не наблюдалось. Чтобы устранить эту неприятность, для тега а приходится использовать небольшой код JavaScript. Таким образом html-код кнопки будет выглядеть следующим образом:

<a href="#" class="button" onclick="this.blur();"><span>Динамическая кнопочка</span></a>

Комментарии (153)

  1. Жмур
    19 августа 2010 г. в 16:11

    Большое спасибо за статью! Очень помогла! Столкнулся с css – оказалось ничего сложного!))) Все элементарно!

  2. vanno
    7 сентября 2010 г. в 16:05

    Спасибо за статью, очень полезна, как и остальные ваши статьи типа 3колончатого шаблона)

    Но вот проблема возникла, что то не получается своими силами исправить
    Хочу сделать вертикальное меню с помощью кнопок, но получаются какие то огромные отступы или вообще по 2 кнопки в строчку залазят
    Есть ли способы борьбы с этим?

    Вот пример
    И еще

    CSS:

    a.butt {
    margin: 12px 2px 15px 2px;
    display: block;
    float: left; /* чтобы кнопка не растягивалась на всю ширину родительского блока, а ограничивалась текстом */
    font: bold 12px arial, sans-serif;
    color: #ccc;
    text-decoration: none;
    background: url(http://mssi.wallst.ru/textures/butt/button_r.gif) top right no-repeat;
    padding-right: 16px; /* отступ для "раздвижных дверей" */
    outline: none; /* убираем точечную обводку в FireFox, которая появляется при клике */
    }

    a.butt span {
    display: block;
    line-height: 13px;
    background: url(http://mssi.wallst.ru/textures/butt/button_l.gif) no-repeat;
    padding: 9px 0 11px 33px;
    }

    a.butt:hover {
    background-position: 100% -33px;
    }

    a.butt:hover span {
    background-position: 0% -33px;
    color: #fff;
    }

    a.butt:active {
    background-position: 100% -66px;
    }

    a.butt:active span {
    background-position: 0% -66px;
    color: #fff;
    padding: 10px 0 10px 33px; /* опускаем текст на 1px */
    }

    html:

    <center>
    <p><a href="#" class="butt" onclick="this.blur(); return false;"><span>right</span></a></p>
    <p><a href="#" class="butt" onclick="this.blur(); return false;"><span>right</span></a></p>
    <p><a href="#" class="butt" onclick="this.blur(); return false;"><span>right</span></a></p>
    <p><a href="#" class="butt" onclick="this.blur(); return false;"><span>right</span></a></p>
    </center>

    1. 8 сентября 2010 г. в 08:21 / ответ на коммент vanno

      Добавьте в стили:

      p {overflow: hidden}
      1. vanno
        8 сентября 2010 г. в 11:13 / ответ на коммент Dimox

        Спасибо, теперь каждая на своей строке, но отступы остались
        И заметил еще более важную проблему, ссылки не работают с кнопок этих

        Главная страница
        Страницы существуют, но при нажатии на кнопку ничего не происходит

        1. 8 сентября 2010 г. в 13:00 / ответ на коммент vanno

          Спасибо, теперь каждая на своей строке, но отступы остались

          Отступы у вас указаны здесь:

          a.butt {
            margin: 12px 2px 15px 2px;
            ...
          }
          

          Страницы существуют, но при нажатии на кнопку ничего не происходит

          Из параметров ссылок удалите return false;.

          1. vanno
            8 сентября 2010 г. в 13:56 / ответ на коммент Dimox

            Сам себе удивляюсь…вот что значит не внимательность! margin даже не заметил :) делал ведь сначала горизонтальное меню..
            Благодарю, теперь все работает

  3. saplant
    13 сентября 2010 г. в 13:53

    Статья очень помогла!
    Но в IE 8 кнопки не работают. При наведении курсора на текст кнопки, нажатия не происходит. Опишите, пожалуйста, подробней как заставить кнопки работать в IE 8.

    1. vanno
      13 сентября 2010 г. в 19:07 / ответ на коммент saplant

      А проблема случайно не та же что и у меня с return false; ?

      1. saplant
        13 сентября 2010 г. в 20:13 / ответ на коммент vanno

        К сожалению, я не знаю return false; это или ещё что-то, но независимо от наличия или отсутствия этой записи ссылки не работают также как и у Вас на Главной странице . И также как у Вас у меня прописан DOCTYPE Если убрать DOCTYPE, то всё работает нормально, но я не могу его убрать иначе у меня шаблон “плывёт”.

  4. Юрий
    5 октября 2010 г. в 10:56

    Хотел сделать кнопки на сайт, не заморачиваясь со скриптами, искал – как – и наткнулся на ваш сайт. Всё очень интересно и познавательно, но…Есть одно но, -для новичка немного сложновато( я написал свой сайт полностью в блокноте).Меня это заинтересовало – оказывается есть программа Css меню генератор называется , которая за , буквально, пару минут позволяет без заморочек сгенерировать нужные коды на любое количество кнопок для меню и не только, чтобы не быть голословным – посмотрите сами , что получилось-
    m-printservice.ru-

  5. Митяй
    6 октября 2010 г. в 04:24

    Объясните мне пожалуйста, неучу безграмотному… Нарисовал кнопки, как показано у Вас в учебнике, методом проб и ошибок, сделал ту кнопку которая мне нужна – фон появляется только при наведении в противном случае его нет. Проблема в размещении на странице. Это безобразие прилипает к левому краю, а мне нужно чётко посередь ! Никак не могу отодрать ( Помогите пожалуйста!

    a.button {
    display: block;
    float: left; /* чтобы кнопка не растягивалась на всю ширину родительского блока, а ограничивалась текстом */
    font: 12px arial, sans-serif;
    color: #555;
    text-decoration: none;
    padding-right: 15px; /* отступ для "раздвижных дверей" */
    outline: none; /* убираем точечную обводку в FireFox, которая появляется при клике */
    border-top-style: none;

    }
    a.button span {
    display: block;
    line-height: 13px;
    padding-top: 7px;
    padding-right: 0;
    padding-bottom: 13px;
    padding-left: 15px;
    width: auto;
    }

    a.button:hover {
    background-image: url(img/nav-butt-r.png);
    background-repeat: no-repeat;
    background-position: right;

    }
    a.button:hover span {
    background-image: url(img/nav-butt-l.png);
    background-repeat: no-repeat;

    color: #0094c7;
    }
    .button {
    padding-top: 5px;
    position: relative;
    width: auto;
    }

    1. 6 октября 2010 г. в 08:58 / ответ на коммент Митяй

      У Вас в a.button { } фон не прописан, поэтому его нет по умолчанию.

      1. Митяй
        6 октября 2010 г. в 18:17 / ответ на коммент Dimox

        Да он мне и не нужен был. Я уже разобрался. пришлось пожертвовать “резиновостью”, но кнопки по центру я расположил. Спасибо за пример.. поучительно )

        1. Nadyushka
          8 октября 2010 г. в 14:34 / ответ на коммент Митяй

          Вот здесь хорошая статья как раз для такого случая:
          http://w3pro.ru/article/vyravnivanie-blokov-po-tsentru

          т.е. надо вокруг ссылки добавить 2 дополнительных элемента

          <div id="center-1"><div id="center-2"><a href="#" name="cat"><img src="button.gif" alt="Кнопочка" border="0"></a></div></div>

          и в стили добавить:

          #center-2 {
          position: relative;
          float: left;
          left: 50%;
          list-style: none;
          margin: 0;
          padding: 0;
          }

          #center-2 a {
          position: relative;
          float: left;
          right: 50%;
          padding: 10px;
          }

          #center-1 {
          overflow: hidden;
          }

  6. ie6
    20 октября 2010 г. в 19:12

    Тупо потраченное время. Предупреждать надо, что в IE6 полная жопа. А вставить вставку “Обновите браузер” проще всего.

    1. Nadyushka
      5 ноября 2010 г. в 06:00 / ответ на коммент ie6

      Что значит “в IE6 полная жопа”? Я свою кнопку тестировала и под ie6, жопы не наблюдала. Может, подробней опишете свою проблему, выложите код – протестируем и чем сможем – поможем!

  7. Unknown Designer
    8 февраля 2011 г. в 00:57

    Всё это прекрасно, но как сделать так, чтобы переходить на какую-нибудь страницу, нажимая по этой динамической кнопке?

    1. 8 февраля 2011 г. в 11:00 / ответ на коммент Unknown Designer

      Прописать ссылку вместо знака #.

  8. 20 марта 2011 г. в 11:28

    Спасибо вам огромное! Весь интернет излазил, кнопочку хотел сделать))
    теперь, надеюсь, проблем не будет)

  9. 23 марта 2011 г. в 17:48

    Скажите, пожалуйста, а как сделать, чтоб кнопка менялась при нажатии на кнопку мыши а не при наведении???

    1. 24 марта 2011 г. в 10:47 / ответ на коммент tohin

      Поменяйте :hover на :active.

  10. 24 марта 2011 г. в 22:04

    Dimox
    у меня тут вопрос возник. Занялся кроссбраузерностью, по корявости отображения ИЕ впереди планеты всей, что с этим сделать можно?
    Да и опера не вполне нормально отображает нажатие на кнопку

    1. 25 марта 2011 г. в 11:03 / ответ на коммент VaNnOrus

      по корявости отображения ИЕ впереди планеты всей, что с этим сделать можно?

      Забить на него или почитать эту статью, может пригодится.

      Да и опера не вполне нормально отображает нажатие на кнопку

      Странно, конечно. На момент написания статьи все работало.

  11. 6 апреля 2011 г. в 11:42

    Dimox, если скрестить динамически кнопки с табами jQuery, т.е.

    <li class="current"><a href="#" class="button"><span>1-я вкладка</span></a></li>
    <li><a href="#" class="button"><span>2-я вкладка</span></a></li>

    Насколько это рабочий вариант и будет ли правильным такое решение? Я попробую сделать, но хотелось бы услышать ваше мнение. Преследуется цель сделать табы из графических кнопок под разную длину текста.

    1. Вполне нормально. Только тег a можно убрать, а вместо него стили применить к тегу li.

      1. LEV7n
        10 августа 2011 г. в 12:50 / ответ на коммент Dimox

        и что? тогда кнопка будет нелинкабельна и никуда не будет вести, зачем джсом крутить? это вполне кроссбраузерный вариант

  12. 7 апреля 2011 г. в 21:26

    Если без

    a

    , то придется использовать скрипт для ИЕ6?

    1. Если нужен эффект при наведении, то да.

      1. Скрестить кнопки и табы получилось! Работает отлично, обошелся без a. Пока скрипт для ИЕ6 задействовать не стал, решил оставить эффект наведения для нормальных браузеров.
        Спасибо за помощь, Dimox!

  13. Slaad
    14 мая 2011 г. в 21:49

    спасибо огромное за блог, очень много информации для начинающего)) очень обстоятельно и детально, спасибо!

    заметил баг в firefox с такими кнопками – если навести мышь на кнопку, нажать, а потом удерживая нажатой увести с кнопки, то кнопка останется нажатой.
    ну и конечно в ie8 кнопка не нажимается :active не работает похоже((

    1. LEV7n
      10 августа 2011 г. в 12:52 / ответ на коммент Slaad

      актив не псевдокласс, в цсс прописывается как обычный дополнительный

  14. slaad
    16 мая 2011 г. в 09:01

    простите за спам, но мб. поможет решить проблему – проверил кнопку в опере – проблема та же, что и в IE 8 не работает эфет нажатия, если нажимаешь на левую створку двери, а вот если нажимать на правую – то все нажимается. Т.е. a.button:active работает, а вот a.button:active span уже нет.

    буду очень признателен, если подскажете что можно сделать с этим

    1. Nadyushka
      16 мая 2011 г. в 14:44 / ответ на коммент slaad

      Код html и css в студию!

      1. slaad
        17 мая 2011 г. в 09:04 / ответ на коммент Nadyushka

        Nadyushka, спасибо, что отвечаете!
        Можно ориетнироваться на код Dimox’a, я делал по аналогии перепроверил, не работает не только у меня, но и у Dimox’a (в 11 Опере и ИЕ8).
        Попробуйте в 11 Опере (благо она бесплатная) нажимать на правую и левую стороны кнопки и увидите, что при клике слева кнопка не нажимается, а справа все ок.
        т.е. скорее всего это именно проблема совместимости метода с этими броузерами.

        Есть и еще один глюк – при нажатии на правую сторону кнопки не происходит перехода по ссылке ни в одном из броузеров, переход происходит только при клике на левую сторону (но это возможно я что-то с кодом накосячил). Можно посмотреть тут – только я правую сторону делал шириной в 5 px, поэтому нужно приноровиться, чтобы попасть по ней.

        1. Nadyushka
          19 мая 2011 г. в 06:57 / ответ на коммент slaad

          Протестировала в последних версиях браузеров (включая Оперу 11), глюка с левой створкой не нашла – при клике даже на самый край кнопки виден визуальный эффект. А вот с правой створкой действительно эффекта не наблюдается.

          Жаль, нельзя картинку вставить, нагляднее бы вышло.
          Проблема Ваша в том, что картинка правой створки выставлена бэкграундом к ячейке таблицы, то есть она не находится внутри ссылки, и, следовательно, никакого эффекта при нажатии нет, и перехода по ссылке соответственно, тоже.

          Ранее в комментах я выкладывала свой вариант кнопки, попробуйте его (страница 4, коммент 105). Этот вариант протестирован и используется в одном из проектов.

          1. slaad
            20 мая 2011 г. в 09:50 / ответ на коммент Nadyushka

            Nadyushkа,
            странно, может не очень поняли друг-друга…

            у меня и Dimoxa на кнопке висят эффекты:
            1) наведение мышки –

            :hover

            2) нажатие мышки (утапливание) –

            :active

            3) переход по ссылке на которую ведет кнопка –

            .active

            У меня в опере не срабатывает 2) эффект если нажимать на левую створку – кнопка не утапливается.
            А у Вас?

            А переход по ссылке починил, теперь работает корректно, спасибо за подсказку! Но вот 2-й эффект не удалось заставвить работать.

            1. Nadyushka
              20 мая 2011 г. в 12:12 / ответ на коммент slaad

              Нда, когда проект сдавался Оперы 11 еще не было. Так что мой вариант тоже не работает. Слегка потестила – судя по всему внутренний span полностью перекрывает ссылку и при этом перестает работать :active. Буду думать.

              1. Андрей
                29 мая 2011 г. в 18:42 / ответ на коммент Nadyushka

                Никто не придумал как пофиксить нажатие в IE8?

                1. Присоединяюсь к вопросу

  15. Денис
    5 августа 2011 г. в 06:54

    нашел решение для ie8 и opera > v11. Добавить в пустой div с таким стилем:
    position:absolute;top:0px;width:100%; height:33px;
    где height:33px как понимаете высота вашей кнопки. После этого везде нажимается.

    1. 5 августа 2011 г. в 11:58 / ответ на коммент Денис

      Не помогло. Опера 11.50

      1. Денис
        25 августа 2011 г. в 09:55 / ответ на коммент Санёк

        в 11.50 тоже проверял – работает. Пустой див в конце, тюею перед

        1. Денис
          25 августа 2011 г. в 10:04 / ответ на коммент Денис

          примерно так выглядит

          <a href="void(0)" rel="nofollow">КНОПКА</a>

          ну а стили как у ТС с добавлением для дива как я написал выше

          1. Денис
            25 августа 2011 г. в 10:08 / ответ на коммент Денис

            В общем пустой див прямо перед закрывающимся тегом а (анкором). если правильно сделать, то работает на всех браузерах со времен ie6 до сегодняшних(у меня спец.набор их всех). Проверял на двух компах – нетбук с xp и перс. с win7, хотя операционка и железо совершенно не при чем )

            1. 25 августа 2011 г. в 13:42 / ответ на коммент Денис

              Не работает.

              <a href="#" class="button"><span>Button</span><div style="position:absolute;top:0px;width:100%; height:60px;"></div></a>
              
            2. Николай
              29 августа 2011 г. в 23:17 / ответ на коммент Денис

              У меня тоже не получилось заставить работать с вложенным дивом.
              Вот живой пример: tamzam.ru
              Подскажите, какие настройки нужны, чтобы заработало?

              1. Николай
                24 сентября 2011 г. в 23:54 / ответ на коммент Николай

                Нашел решение для оперы, нужно правила с :active продублировать с :focus

                Но в explorer так и не удалось заставить по :active работать обе части “раздвижных дверей”. При нажатии на правую створку срабатывает, а на левую – нет.
                Вот эта конструкция не воспринимается: a.button:active span. В принципе, если у вас для графики правая створка не критична, можно для explore дополнительное правило написать a.button span:active, тогда створки работают в нем раздельно, но зато нажимаются))

                1. Николай
                  25 сентября 2011 г. в 00:38 / ответ на коммент Николай

                  немного потестил, кнопка в примере при добавлении :focus срабатывает, а вот у меня нет((

  16. Николай
    25 сентября 2011 г. в 19:01

    все разобрался, если продублировать :focus к тем же событиям, что описаны по :active то срабатывает во всех броузерах включая explorer и opera! В том числе срабатывает и кнопка из примера при нажатии на любую створку.

    можно удалить 2 моих предудущих поста, простите за спам

    1. 26 сентября 2011 г. в 11:24 / ответ на коммент Николай

      Попробовал сделать, как вы написали. Кнопка нажимается, но не разжимается. У вас также?

  17. Николай
    26 сентября 2011 г. в 18:11

    странно…
    у меня отжимается вроде вот файл из примера на котором тренировался: (http://ifolder.ru/25958855) проверял в опере 11.51 и explorer 8.0 (в хроме и файрфоксе работало и раньше). А вы в каком броузере смотрите?

    Еще выше ссылку давал, там тоже можно посмотреть.

    1. 26 сентября 2011 г. в 18:35 / ответ на коммент Николай

      Понял, в чем причина. В статье у кнопки я добавил параметр onclick="this.blur(); return false;", который как раз за отжим и отвечает. А при тестировании на новой странице я забыл его вставить.

      Спасибо что помогли разобраться. Надо будет обновить статью.

  18. 14 марта 2012 г. в 19:16

    Спасибо, как раз то что искал. Только немного доработал под свои нужды, чтобы span накладывался на ссылку, т.е. перекрывал текст.

  19. Александр
    5 апреля 2012 г. в 16:06

    добрый день,
    существует следующая проблема:
    надо на ссылку поставить кнопку-картинку для перехода(на ссылку перехода на англоязычную страницу сайта поставить кнопку-картинку влага Великобритании)

    <a href="uk/index_uk.html" title="Enter" rel="nofollow"></a>

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

    1. Вот так сделайте:

      <a href="uk/index_uk.html" title="Enter" rel="nofollow"><img src="ссылка_на_изображение" alt="" /></a>
      1. Александр
        6 апреля 2012 г. в 13:14 / ответ на коммент Dimox

        спасибо, Dimox, выручил.

  20. 7 апреля 2012 г. в 21:54

    Спасибо Dimox! Я как раз делаю сейчас онлайн кинотеатр, и мне эта кнопка ооочень пригодилась!!!

Ваш комментарий

Жирный текст

Ссылка

Цитата

Внутристрочный код

CSS-код

HTML-код

JavaScript-код

PHP-код