Xiper

Резиновая кнопка

Автор: Евгений Рыжков Дата публикации:

Задача

Для формы сделать резиновую (тянущуюся) кнопку по ширине с особым оформлением (с обычным оформлением уверен у тебя проблем не возникает).

Схема резиновой кнопки

Требования:

  • ширина кнопки зависит от текста в ней
  • использование тега <input> (чтобы сохранить логичность кода. Как сделать с <button>, пока не нашел решения)
  • кликабильность всей поверхности кнопки
  • отсутствие javascript (еще одна причина использовать <input>)
  • ну и конечно же кроссбраузерность и следование стандартам

На кой это нужно?

На сайте может быть много форм, а на крупных сайтах — очень много. Каждая форма как правило имеет кнопку. И бывает так, что в разных формах текст в кнопке должен быть разным: ok, сохранить, задать вопрос менеджеру и т.п. Чтобы не плодить для каждой формы отдельный фон для кнопки, лучше сделать одну универсальную кнопку. Это не только съекономит трафик за счет сокращения картинок, но и сделает верстку более гибкой (не нужно будет каждой новой кнопке с отличающимся текстом рисовать новый фон и добавлять классы).

Решение

Воспользуемся следующим приемом:

Схема приема реализации резиновой кнопки
<div class="button">
	<input type="submit" value="" />текст кнопки
	<span></span>
</div>
.button {
color: #fff; /* цвет текста кнопки */
height: 23px; /* высота кнопки */
padding: 5px 6px 0 6px; /* внутренние отступы кнопки */
background: url(path-to/button.png) no-repeat; /* длинная картинка - левая часть фона кнопки */
font-size: 11px; /* размер шрифта кнопки */
float: left; /* чтобы ширина блока зависела от содержимого */
position: relative;
overflow: hidden;
}
.button span {
background: url(path-to/button-r.png); /* фон правой части кнопки */
height: 27px;
width: 6px;
display: block;
position: absolute;
z-index: 1; /* обязательно указываем z-слой, чтобы input был выше */
top: 0;
right: 0;
overflow: hidden;
}
.button input {
position: absolute; /* абсолютно размещаем input поверх остальных элементов */
top: 0;
left: 0;
width: 200%; /* input должен занимать всю область по высоте и ширине, чтобы вся кнопка была кликабильной (200% для ие6, чотбынавреняка растянулся на всю ширину, ибо при 100% растягивался не полностью) */
height: 100%;
opacity: 0; /* делаем кнопку полностью прозрачной, чтобы она не искажала задуманный дизайн, но была функционирующей */
filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);  /* прозрачность для ие6-7 */
cursor: pointer;
border: none;
z-index: 2; /* z-слой должен быть больше, чем у других частей кнопки */
}
* html .button {
height: 27px; /* учитываем блочную модель ие6 */
}
.button span {
right: -1px; /* тут правильней было б использовать expression для лечения смещений в 1px в ие6 */
}

Посмотреть результат.

Заметки

  • В боевых условиях вместо хаков для IE6 следует использовать условные комментарии
  • для уменьшения количества отдельных картинок, можно воспользоваться техникой спрайтов — склеить картинки в одну:
    Спрайты для резиновой кнопки

Недостаток

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

Решение 2

update by nadiam84 Некоторые манипуляции в HTML + CSS дают возможность сделать кнопку с прозрачными углами, за счет того, что углы не будут накладываться на фон:

<div class="button">
	<div>
		<input type="submit" value="текст кнопки" />
		<span></span>
	</div>
</div>
.button {
	float: left; /* чтобы ширина кнопки зависела от контента. по идее должен подойти и display: inline-block */
	margin: 50px;
}
.button div {
	position: relative;
	color: #fff;
	height: 27px;
	background: url(path-to/button.png) no-repeat; /* левые углы фона с прозрачными участками */
	font-size: 11px;
}
* html .button div { /* хак для ие6 чтобы с шириной кнопки проблем не было */
	width: 10px;
}
.button span { /* правое скругление кнопки выносим за пределы кнопки */
	background: url(path-to/button-r.png);
	height: 27px;
	width: 6px;
	display: block;
	position: absolute;
	z-index: 1;
	top: 0;
	right: -6px;
	overflow: hidden;
}
.button input {
	height: 100%;
	cursor: pointer;
	margin: 0 -6px 0 0; /* чтобы кликабильным была правая часть кнопки, вынесенная за ее пределы */
	padding: 2px 6px 5px 6px;
	overflow: visible; /* убираем необнуляемые внутренние отступы для ie6-7 */
	border: none;
	position: relative;
	z-index: 2;
	background: none;
}

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

  • IE 6-7
  • Firefox 3.6
  • Opera 10.5
  • Chrome 7

Преимущества:

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

Недостатки:

  • для реализации одной кнопки требуется 4 элемента! Можно span заменить псевдоэлементом (before), но это не намного улучшит ситуацию;
  • раздутый CSS код.

Решение 3 — CSS3

update by Евгений Рыжков Пришло время CSS3 и незачем больше заниматься фигней с этими костылями из кучи HTML и CSS! Юзаем border-radius в сочетании с каким-нибудь PIE для IE и будет всем счастье.

<input type="submit" value="текст кнопки" />
input {
	height: 27px;
	cursor: pointer;
	padding: 2px 6px 5px 6px;
	overflow: visible;
	border: none;
	background: url(img/button-repeat.png) repeat-x;
	-moz-border-radius: 5px;
	-webkit-border-radius: 5px;
	border-radius: 5px;    
}

Для IE:

input {
	behavior: url(path-to/PIE.htc);
}

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

  • IE 6-8
  • Firefox 3.6
  • Opera 10.5
  • Chrome 7

Преимущества тут даже не стоит перечислять: достаточно сравнить HTML и CSS коды этого варианта с предыдущими. Да пребудет с нами HTML5 и CSS3!

Используемые приемы в этой статье: