вторник, 6 октября 2009 г.

CSS закругленные уголки/углы без абсолютного позиционирования (css round corners NO absolute position)

Доброго времени суток. Вот решил еще однин пост написать. Давайте сразу к делу.

В чем минусы position:absolute?

Я уже писал на своем блоге о методе верстки закругленных уголков. В тот раз они строились с помощью абсолютного позиционирования. Мы расставляли каждый уголок по уголкам о_0. Видите? Тавтология - уже минус. Также нам надо было фиксить проблему с ИЕ6 с помощью expressions (баг - bottom:0; not on the bottom). Зачем же эта ерунда если можно обойтись без этого?

Что будем верстать?

Я немного усложню общий вид и добавлю нашему блоку однопиксельный бордер. Выглядеть это будет так:

round green block

В основе данного метода верстки лежит спрайт. Он будет включать в себя 6 элементов нашего круглого блока: 4 угла + верхняя и нижняя части, захватывающие бордер.

Начнем нашу верстку

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

elements sprite

Мои элементы получились размером в 11 пикселей. Разместить их нужно именно вертикально один за другим (расскажу позже почему именно так).

Перейдем к представлению HTML кода:

<div class="roundblock">
<div class="head"><span><span></span></span></div>
<div class="body">
<div class="content">
Никакого абсолютного позиционирования
</div>
</div>
<div class="foot"><span><span></span></span></div>
</div>

Что у нас тут:

  • 3 части основного блока
  • вложенный span в елемент класса head и foot
  • еще один span в span'е
  • body для зеленого бордера
  • content в body для белого бордера

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

Давайте взглянем на CSS код:

.roundblock { width:200px; margin:200px auto; }
.roundblock .head {
background:url("corners-sprite.png") 0 -44px repeat-x;
height:11px;overflow:hidden;
}
.roundblock .head span {
background:url("corners-sprite.png") left 0 no-repeat;
height:11px; display:block;
}
.roundblock .head span span { background-position:right -11px; }

.roundblock .body {
border-width:0 1px; border-style:solid;
border-color:#6cb700;
}
.roundblock .body .content {
border-width:0 1px; border-style:solid;
border-color:white; background:#6cb700;
padding:10px; color:white;
}

.roundblock .foot {
background:url("corners-sprite.png") 0 -55px repeat-x;
height:11px; overflow:hidden;
}
.roundblock .foot span {
background:url("corners-sprite.png") left -33px no-repeat;
height:11px; display:block;
}
.roundblock .foot span span { background-position:right -22px; }

Давайте рассмотрим все по порядку:

  1. Первым делом мы опишем стили класса head. Обязательно следует указать ему высоту. В моем случае это 11 пикселей. Далее задаем фоновую картинку с урлом на наш ранее созданный спрайт. Устанавливаем позицию на элемент верхней части блока и тянем его по оси Х. Если ваши уголки меньше чем 20 пикселей, то следует поставить overflow:hidden, так как ИЕ6 не любит блочные элементы меньше 20-ти пикселей. Можете проверить что получилось открыв документ в браузере.
  2. Переходим к вложенному элементу span. Сразу же делаем его блочным (display:block) чтобы он тянулся по всей ширине контейнера. Устанавливаем картинку фона отказываясь от повторения (no-repeat). Так как это наш первый уголок и в картинке он у нас сверху, устанавливаем значение позиции Х равное left и значение Y равное 0. Проверяем в браузере и видим уголок слева.
  3. Переходим к span'у что поглубже. Он тоже должен быть блочным. Все так же только следует изменить позицию Х на right и сменить позицию спрайта по Y. Как и обещал, возвращаюсь к пояснению о вертикальной расстановке элементов в нашем спрайте. Как Вы могли заметить span у нас блочный и задавать ширину ему нельзя, так как вложенный в него span для другого уголка не будет в нужном месте. Если мы разместим элементы спрайта горизонтально, мы не сможем контролировать ширину, а в нашем случае она вычисляется окончанием рисунка.
  4. Далее сам контейнер с содержимым - body. Это промежуточный элемент, созданный для того, чтобы отобразить 2 бордера по бокам. Ставим ему зеленый бордер. А вот внутренний элемент с классом content послужит нам не только элементом с боковыми белыми линиями, но также создаст продолжение верхнего и нижнего фона.
  5. С foot'ом у нас все также как и с head. Меняем позицию спрайта соответствующих элементов и все готово.

В результате у Вас должно получиться это:

block ready

Помните, что если Вы не хотите блок с белым бордеров внутри, просто используйте background:#color; вместо backround:url('image'); у элементов head и foot. А в центре будет достаточно одного элемента с классом content.

Поэксперементируйте с данной версткой и Вы сможете легко создать что-то вроде этого:

round block with gradient

Спасибо. Буду рад любым комментариям и исправлениям.

понедельник, 5 октября 2009 г.

Двухколоночный макет тянущийся по вертикали (CSS only)

О чем это он? о_0

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

Вступление

Мы верстаем двухколоночные макет для маленького блога или даже микроблога, не побоюсь этого слова. Идеальный пример - Twitter.com. Зайдите на этот сервис и посмотрите на макет. Высота колонок одинаковая не зависимо от их содержимого.. они просто всегда равны. Еще и бордер в придачу между ними.. такие возможности дает нам табличная верстка. Просто один рядок и две ячейки. Таблица сделает все за Вас.

К сожалению я не любитель такой верстки - верстки таблицами... это конечно семантически корректно и очень просто, но все же я задался целью сделать это DIV'ами.

Проблема

Главная проблема заключается в том, что при разном содержимом наши колонки будут иметь разную высоту. Смотрите скриншот:

two column layout problem

Видите? Я поставил немного переносов строк и получилось вот ЭТО. Никуда не годится.. то же самое получается и с другой колонкой...

Цель

Как Вы уже поняли, цель заключается в том, чтобы сделать колонки тянущимися или легче будет сказать "всегда одинаковыми по высоте вне зависимости от содержимого".

Приступим

Для начала, как я всегда делаю, представлю Вам HTML код:


<div class="page">
<div class="leftcol">
LEFT COLUMN HERE
</div>

<div class="rightcol">
<div class="content">
RIGHT COLUMN HERE
</div>
</div>
</div>

Как Вы можете наблюдать, я создал общий контейнер для моих колоночек :). Они живут в страничке, у них статическая длинна и они разноцветные. Вот кстати нужный нам CSS код:


.page { background:#ffff66; width:500px; overflow:hidden; }
.leftcol {
float:left; background:#ccff66;
width:350px; border-right:1px solid #ff9900;
}
.rightcol { padding-left:350px; background:#ccff66; }
.rightcol .content {
background:#ffff66; border-left:1px solid #ff9900;
}

Все и без меня ясно, но я вставлю свои пять копеек. Главному контейнеру (page) мы ставим фон желтого цвета, это на тот случай если наша правая колонка будет короче левой.
Левая колонка принимает свойства float со значением left и фон, свой собственный фон - зеленый, длинна - 350 пикселей.
Правой колонке установим значение padding-left равным длинне левой колонке - 350 пикселей и ЗЕЛЕНЫЙ фон. ВАЖНО установить именно padding, а не margin, так как наша колонка не будет страховать левую в том случае если та будет короткой.
Внутри контейнера с правой колонкой я создал еще один блок, который и будет иметь свой правильный ЖЕЛТЫЙ фон.
Не забудьте про overflow:hidden у элемента .page. Это исправляет неправильное вычисление браузером высоты этого блока. В противном случае все будет как на предыдущем скриншоте.

two column layout good

Вот и он!!! Попробуйте подобавлять немного содержимого куда-либо.. все будет отлично! Кстати, я совсем не упомянул о бордере.. На левую колонку ставим border-right, на вложенный блок правой - border-left. Верстка кроссбраузерная (ИЕ6 тоже)!!! Никаких таблиц и javascript'a.

Хух... долго здесь ничего не писал... надеюсь кому-то это будет интересно и может даже пригодится... исправляйте, если есть ошибки... Спасибо...

пятница, 27 марта 2009 г.

Использование CSS Sprites (Спрайты)

Сейчас поговорим о CSS спрайтах. Допустим, Вы используете несколько картинок для построения той же графической кнопки или блока с закругленными уголками. Чтобы не использовать несколько картинок можно объеденить их в одно расположив их в нужном порядке.

Главное преимущество спрайтов - это уменьшение количества HTTP запросов к серверу для получения картинок. Это конечно незначительно уменьшает скорость загрузки страницы, но представте, что у вас 100 маленьких картинок(допустим, иконок). Объеденив их, например в 4 картинки включающие по 25 иконок, Вы уменьшаете количество запросов в 25 раз, а это уже что-то.

Ну давайте наконец перейдем к делу.
Предлагаю небольшой пример с использованием 8-ми картинок объедененных в одну.



Давайте отобразим 4 верхних смайлика и установим ховер (hover) на каждый из них. Псевдокласс будет менять каждый смайлик на нижестоящий.

Вот HTML конструкция:
<ul>
<li><a class="happy" href="#"></a></li>
<li><a class="green" href="#"></a></li>
<li><a class="punk" href="#"></a></li>
<li><a class="sad" href="#"></a></li>
</ul>
А вот фрагмент CSS кода:
ul li { list-style:none; float:left; }
ul a { display:block; display:block; height:96px; width:96px;
background:url("smileys.png") no-repeat; float:left;
}
Как Вы заметили, я задал всем элементам "а" фон с картинкой smileys.png которая показана выше. Должно получится следующее:


Теперь немного пояснения. Размеры наших элементов "а" - 96х96 пикселей. Свойство background-position по умолчанию имеет значение 0. Это значит, что фон для элемента будет начинаться с верхнего левого угла нашей картинки. Вот почему все 4 смайлика будут одинаковыми.

Теперь попробуем изменить 3 последних смайлика используя ту же картинку.

ul a.happy { } /* с первым у нас и так все нормально */
ul a.green { background-position:-96px 0; }
ul a.punk { background-position:-192px 0; }
ul a.sad { background-position:-288px 0;}
Заметьте, что я установил именно отрицательное значение по оси Х. Это потому, что мы двигаем не элементы по фону, а сам фон под элементом. Допустим, для зеленого смайлика нам необходимо сдвинуть фон влево ровно на 96px. Должно отображаться следующее:



Ну а теперь добавим псевдокласс hover для каждого элемента "а":
ul a.happy:hover { background-position:0 -96px; }
ul a.green:hover { background-position:-96px -96px; }
ul a.punk:hover { background-position:-192px -96px; }
ul a.sad:hover { background-position:-288px -96px; }
Теперь я сдвинул background вниз на 96 пикселей для каждого из классов, а значение Х оставил прежним. В конечном результате у вас должно получиться следующее:

Рабочий пример








Вот так можно удобно пользоваться спрайтами. Главное правильно расположить картинки чтобы в дальнейшем их возможно было использовать. Например, для кнопки состоящей из 3-х картинок (предыдущая статья) можно использовать такой спрайт:



Сверху расположены правая и левая часть кнопки, снизу - середина.

Надеюсь, что моя статья была вам интересна и вы что-то из нее почерпнули. Если нет, то смайлики определенно должны были вас порадовать :).

вторник, 17 марта 2009 г.

CSS кнопка (кроссбраузерная)

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

Я нарисовал свою собственную кнопку которая напоминает стиль Windows Vista Button:


Для того чтобы сверстать такую кнопку я использую следующую конструкцию:

<a class="button" href="#">
<img class="head" src="blank.png" /><input type="submit" value="Button"/><img class="tail" src="blank.png" />
</a>

Я не зря обрамил три элемента именно в тег <A>. IE6 понимает псевдокласс hover только для этого элемента, поэтому если в дальнейшем мы захотим чтобы кнопка изменяла свой вид при наведении на нее мышкой - это будет какраз кстати. Также учтите, что все элементы являются инлайновыми(inline) и любой пробел или перенос строки между ними приведет к возникновению пустого пространства, а нам этого не надо. Поэтому сохраните форматирование именно так (все 3 внутренних элемента в одной строке).

И так, как Вы уже заметили, кнопка состоит их трех основных элементов: элемент img который выполняет роль левой части, элемент img - правая часть и input, который будет растягиваться посредине. Для верстки нам понадобятся 3 составные картинки этой кнопки. Вырежьте их в каком-то графическом редакторе типа Photoshop или GIMP. У Вас должно получиться следующее:

     

ВАЖНО! Дополнительно вырежьте картинку размером 1x1 пикселя полностью прозрачного фона. Об этом чуть дальше.

Настало время для самой верстки:

.button { text-decoration:none; }
.button * {
border:0;
height:37px;
cursor:pointer;
vertical-align:middle;
}

.button img.head {
background:url("button-left.png") no-repeat;
width:7px;
}

.button img.tail {
background:url("button-right.png") no-repeat;
width:7px;
}

.button input {
background:url("button-bg.png") repeat-x;
color:#eee;
width:100px;
padding-bottom:2px;
font-size:15px;
}
Подробно рассмотрим каждый селектор:

.button * задает каждому элементу высоту в 37 пикселей, убирает бордер и устанавливает курсор в виде руки(это по желанию).

Далее опишем два класса head и tail. Установите на бекграунд заведомо вырезанные рисунки. Я устанавливаю их с помощью CSS опять же для hover'a. Теперь, как и обещал, вернемся к нашей прозрачной однопиксельной картинке. В этом примере я назвал ее blank.png и поставил ее на оба тега img. Это нужно сделать так как картинка без указанного атрибута src вовсе не будет отрисовываться.

Наконец устанавливаем CSS свойства для нашей кнопки. Ставим фоновый рисунок и растягиваем его по горизонтали. Задаем cерый цвет шрифта, верхний паддинг чтобы центрировать текст по вертикали и размер фонта 15 пикселей.

Ну вот и все. Кроссбраузерная CSS кнопка готова.

Если захотите установить hover, достаточно добавить всего 3 коротких селектора:
.button:hover .head { background:url("button-left-hover.png") no-repeat;}
.button:hover input { background:url("button-bg-hover.png") repeat-x; }
.button:hover .tail { background:url("button-right-hover.png") no-repeat;}

четверг, 5 марта 2009 г.

Метод getElementById() в IE или "при чем тут name?"

Здравствуйте! Если Вы читаете эту статью, возможно, вы столкнулись с той же проблемой что и я и находитесь в небольшом замешательстве. Я сам когда-то столкнулся с ситуацией когда javascript'овый метод getElementById() возвращал мне ссылку не на тот объект который я запрашивал. Пришлось потратить немного времени чтобы выяснить в чем же всетаки дело.

На сайте http://www.w3schools.com в разделе Javascript черным по белому написано определение метода getElementById(). Выглядит оно так:

The getElementById() method returns a reference to the first object with the specified ID.
Из данных слов понятно, что этот метод возвращает ссылку на обьект с указанным идентификатором. Так оно и есть конечно, не думайте что я пытаюсь это оспорить :). А вот ребята из Microsoft со своим Internet Explorer'ом оспорили.

getElementById возвращает ссылку на объект с указанным name?

Рассмотрим небольшой пример. Создадим несколько элементов у которых бы совпадали атрибуты id и name:
<textarea name="chooseMe"></textarea>
<div id="chooseMe" />

А теперь попробуем вывести на экран сообщение с именем нужной нам ноды (nodeName):

alert(document.getElementById('chooseMe').nodeName);

Выполнение данного скрипта судя по названию метода должно вывести на экран сообщение с текстом DIV во всех браузерах. Жаль что используя IE6 или IE7 мы увидим ничто иное как окошко с текстом TEXTAREA. А какая разница между именем или айди? IE думает, что никакой.

Будьте внимательны используя элементы с совпадающими именами и идентификаторами когда используете браузеры компании Microsoft. Ну а если Вам это так необходимо, просто добавьте приставку значению имени или айди определенного элемента или же учитывайте порядок поиска "сверху вниз".

вторник, 24 февраля 2009 г.

Новые возможности CSS3

Конец эры интенсивного использования CSS2.1 не за горами. Вскоре CSS дизайнеры позабудут о проблемах верстки в IE6, перестанут вырезать картинки чтобы создать блоки с закругленными уголками, задавать float:left блочным элементам дабы те выстроились в нужное количество колонок и ложить два background'а на разные элементы когда так хочется установить их на один. Совсем чуть-чуть и мы наконец сможем задействовать всю мощь CSS3 так как нам этого захочется.

Сейчас современные браузеры такие как Opera 9.63, Mozilla 3.06 и Internet Explorer 6 :) активно внедряют CSS3. Конечно понимают они не все нововведенные свойста. Вот например случай с закругленными углами:

border-radius:10px;  /*одно свойство и кругые углы в 10 пикселей готовы*/

...к сожаление такое нигде не работает. Mozilla использует свой прием. Добавляет приставку -moz- почти ко всем свойствам CSS3 и все начинает работать. Safari добавляет приставку -webkit-.

Уверен, что в новых браузерах таких как Opera 10, Mozilla 3.1 и IE8 все будет хорошо

Немного подкрепления от CSS3

Наверное уже многие знакомы с возможностями CSS3, но все же скажу пару слов от себя.

  • Очень понравилась возможность устанавливать несколько фоновых рисунков на элемент, это очень упрощает жизнь хотябы с теми же закругленными краями. Хотя сразу вспоминаешь, что это уже не проблема.
    background: url(body-bottom.gif) bottom left no-repeat,
    url(body-middle.gif) left repeat-y;
  • Возможность установить рисунок на border (Safari, Firefox 3.1 alpha)
    border-top-image:url("image.png");
    .
  • Очень классная вещь с добавлением падающей тени от текста(Opera 9.5+):
    text-shadow:10px 5px yellow;
  • Мультиколоночный лейаут с помощью всего нескольких свойств:
    -moz-column-count: 3;
    -moz-column-gap: 1em;
    -moz-column-rule: 1px solid black;
  • Закругленные углы (round corners) теперь под силу всем:
    -moz-border-radius:0 15px 0 15px;

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

четверг, 19 февраля 2009 г.

Кроссбраузерный XmlHttpRequest (xhr)

Сегодня немного отдалимся от CSS и HTML и перейдем к Javascript. Речь пойдет о XmlHttpRequest.

XmlHttpRequest - это апи для пересылки различных данных между браузером и веб-сервером по Http-протоколу. Вообщем вы можете слать запрос на удаленный сервер не перегружая страницу. Очень удобная вещь.

Работая над одним проектом, я столкнулся с проблемой кроссбраузерности при использовании XHR.. как Вы думаете о чем это я? Конечно же о полюбившимся мною IE6 :). С ним всегда все наперекосяк. Вот я и решил написать свою реализацию XmlHttpRequest, точнее описать что-то вроде класса который бы все делал сам, был бы легок в эксплуатации.

И так представляю вашему вниманию функцию создающую кроссбраузерный XmlHttpRequest:

function Xhr(options) {
this.method = 'post';
this.onSuccess = function() {
};
this.onFailure = function() {
};

if (options) {
for (var o in options)
this[o] = options[o];
}
if (window.XMLHttpRequest) this.request = new XMLHttpRequest();
else if (window.ActiveXObject) this.request = new ActiveXObject("Microsoft.XMLHTTP");

this.onreadystatechange = function() {
if (this.request.readyState == 4)
if (this.request.status == 200) {
this.onSuccess(this.request.responseXML, this.request.responseText);
}
else this.onFailure();
};

var xhr = this;
this.request.onreadystatechange = function() {
xhr.onreadystatechange();
};

this.send = function(url, data) {
this.request.open(this.method, url, true);
if (this.method == 'post') {
this.request.setRequestHeader('Content-type','application/x-www-form-urlencoded');
this.request.setRequestHeader('Content-length', data.length);
}
this.request.send(data);
};
}

Теперь мне стоит немного рассказать об этом коде. И так Вы видите функцию, которой на вход передаются параметры (опции), относительно которых и будет строиться наш XHR. Пойдем по порядку

  • method - метод передачи данных, может быть POST или GET.
  • onSuccess - это функция которая будет выполняться при удачном выполнении запроса.
  • onFailure - функция которая будет выполняться при возникновении ошибки(можно выводить какое-то сообщение).
Ну вот все нужные параметры переданы, а дальше идет проверка на ActiveX. Если таковые компоненты присутствуют значит это никто иной как Internet Explorer 6.

Теперь небольшой примерчик использования.

Допустим у Вас есть текстовое поле(textarea) в котором люди пишут свои комментарии.

<textarea rows='5' cols='100' name='comment' id='comment'></textarea>
<input type='button' name='send' value='Отослать' onclick='send();'/>

Наша задача принять значение текстового поля и передать их на сервер не перегружая страницу. Создадим функцию которую сможем поместить в виде события(event) на нашу кнопку отправки.

function send() {
var xhr = new Xhr({
method:'post',
onSuccess:function() { alert('Спасибо за комментарий'); },
onFailure:function() { alert('Произошла ошибка!!!'); }
});
var commentValue = document.getElementById('comment').value;
xhr.send('/commented', 'commentText=' + commentValue);
}

Метод send у XHR шлет запрос на сервер по урлу '/commented' и передает параметр 'commentText' - это текст комментария. А на сервере мы просто получаем параметры и используем их в своих целях.

Хух! Вот и все. Напомню, что этот XmlHttpRequest работает во всех браузерах. Удачного использования.