11 августа 2011 г.

text-shadow для Internet Explorer

Привет, всем.

Лучшая из виденных мною реализаций свойства text-shadow в IE без использования JavaScript. Встречайте — CSS3 Text-Shadow – Can It Be Done in IE Without JavaScript? от Zoltan Hawryluk.
На сайте этого автора можно найти ещё интересные вещи.

Кроссбраузерные обработчики событий

addEvent() от Дина Эдвардса

Проверенное мной лаконичное решение. Использует DOM Level 0 Events и никакого feature detection'а. Когда мы вешаем обработчик с помощью addEvent() на элемент, в качестве свойства этого элемента добавляется объект events, внутри которого в массив добавляется функция-обработчик. Если этот массив уже существует, то к уже имеющимся обработчикам добавляются новые.

Из коробки при использовании функции removeEvent() необходимо указывать в качестве третьего аргумента ссылку на ранее установленный обработчик. Т.е. нет возможности удалять анонимные функции-обработчики. Но это легко исправляется слегка изменив функцию removeEvent():

function removeEvent(element, type, handler) { // delete the event handler from the hash table if (element.events && element.events[type]) { (!handler) ? delete element.events[type] : delete element.events[type][handler.$$guid]; } };

Теперь если мы не указали ссылку на функцию-обработчик в качестве третьего аргумента, то удаляются все обработчики заданного события.

Ссылки по теме

1 марта 2011 г.

Псевдо-класс :active и Internet Explorer

Заметил одну особенность использования псевдо-класса :active в Internet Explorer'е. Стили присвоенные с помощью псевдо-класса :active в этом браузере сработают только если вы кликаете непосредственно по элементу, которому был указан псевдо-класс, но не по его дочерним элементам.

Рассмотрим пример:

<p>Просто текст с <span>элементом</span> внутри.</p>

CSS:

p:active { text-decoration: underline; }

В IE текст внутри параграфа станет подчеркнутым только если вы кликните непосредственно по элементу <p>, а не по span'у внутри него. Это не касается остальных браузеров. В Safari, Google Chrome, Opera и Firefox текст внутри параграфа станет подчеркнутым не зависимо от того, нажали ли вы на дочерний элемент или на сам параграф.

Аналогично в IE не сработает следующий css-код:

p:active span { text-decoration: underline; }

Текст внутри элемента <span> не станет подчеркнутым если нажать на элемент <p>, в то время как в остальных браузерах текст будет подчеркнутым.

Не знаю что говорит на этот счет спецификация CSS (подозреваю что ничего), но мне кажется что Firefox и остальные браузеры более предсказуемо и правильно обрабатываю выше приведенные примеры нежели IE.

Описанный выше код касается всех существующих на данный момент версий Internet Explorer'а — 7, 8, 9 RC. Собственно IE7 вообще понимает псевдо-класс :active только для элемента <a>.

В качестве демонстрации можете потыкать по элементам внутри параграфов на этой страничке — http://quirksmode.org/css/hover.html.

12 января 2011 г.

Печать защищенных PDF файлов

Не совсем про веб-разработку, но всё же...

Скачал себе как-то 65 книг по покеру. Решил распечатать несколько страниц из одной книги. Но оказалось что PDF файл (впрочем как и остальные 64) были защищены от печати.

После не очень продолжительных поисков нашел замечательную программу для снятия защиты — A-PDF Restrictions Remover. Программа платная, но к счастью есть 15-ти дневный trial.

7 января 2011 г.

Кроссбраузерный DOMContentLoaded

Многие из вас наверняка знают про событие DOMContentLoaded. Вкратце — это событие позволяет запускать выполнение кода сразу после того, как будет готово DOM-дерево. Это отличная альтернатива событию onload, которое срабатывает только после того, как будет загружен весь документ, включая все внешние файлы и изображения. О преимуществах DOMContentLoaded более детально говорить, я думаю, не стоит. Но к сожалению свободно пользоваться DOMContentLoaded на данный момент нельзя, в виду того, что не все браузеры это событие поддерживают. А не поддерживают это событие вот какие браузеры:

  • Internet Explorer до 9-ой версии
  • Opera до 9-ой версии
  • Gecko-based браузеры с версией движка ниже 1.8
    • Firefox ниже версии 1.5
  • Webkit-based браузеры с версией движка ниже 525.13
    • Safari ниже версии 3.1

Данные о поддержке браузерами события DOMContentLoaded взяты из скрипта contentloaded.js достопочтенного Diego Perini.

Делее мы рассмотрим методы кроссбраузерного использования события DOMContentLoaded. Вернее методы эмуляции работы этого события.

Самые, пожалуй, популярные методы запуска кода по завершении построения DOM-дерева — это использование JavaScript-фреймворков. В jQuery это делается вот так:

$(document).ready(function(){ // Код который выполнится сразу по завершении построения DOM-дерева });

Или ещё короче:

$(function(){ // Код который выполнится сразу по завершении построения DOM-дерева })

В MooTools это выглядит так:

window.addEvent('domready', function() { alert('The DOM is ready!'); });

Но иногда подключать целую библиотеку только ради DOMContentLoaded — это через чур. Тогда я решил поискать готовые решения эмуляции этого события.

Вначале я наткнулся на уже упомянутый выше скрипт от Diego Perini ContentLoaded. Скрипт основывается на определении браузера и, в зависимости от того какой браузер использует клиент, мы используем тот или иной метод для скорейшего запуска обработчика после того, как готово DOM-дерево.

Для Safari версий ниже 3.1 скрипт проверяет свойство document.readyState. Если значение этого свойства равно complete или loaded, то запускается обработчик события, в противном случае проверка выполняется повторно через 10 милисекунд.

В IE для проверки загруженности DOM-дерева используется проприетарная функция doScroll(), которая выкинет ошибку, если попытаться запустить её до того, как будет построено DOM-дерево. doScroll()вызывается до тех пор, пока не перестанет выдавать ошибку и тогда запускается необходимый код.

Для браузеров, которые не поддерживают DOMContentLoaded и не являются Internet Explorer'ом, обработчик вешается на событие onload.

Помимо решения от Diego Perini, я наткрнулся на статью «Кроссбраузерное событие onDOMContentLoaded».

Короче, решение от Diego Perini, на мой взгляд, не самое лучшее. Есть более толковый способ и он подробно расписан в статье «Кроссбраузерное событие onDOMContentLoaded».

Diego Perini использует определение браузера (browser detection) и в зависимости от того, какой браузер у пользователя, используется тот или иной подход. В статье на javascript.ru используется немного другой подход. Он выглядит приблизительно так: для браузеров кроме IE обработчик вешается одновременно и на событие DOMContentLoaded и на onload и срабатывает только один раз. Если сработало DOMContentLoaded, то по событию onload этот обработчик уже не вызывается. Если же браузер не поддерживает DOMContentLoaded, то обработчик сработает по событию onload. Хоть в IE до 9-ой версии и нет события DOMContentLoaded, есть возможность запустить обработчик раньше события onload. Для это в IE используется проприетарная функция doScroll(), которая выкинет ошибку, если попытаться запустить её до того, как будет построено DOM-дерево. Таким образом в IE мы вызываем обработчик, когда doScroll() перестанет выдавать ошибку.

Вот собственно и всё.

25 января 2010 г.

Прилипающий к низу футер

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

Имеем следующий html-код:
<div id="wrapper">
  <div id="header">Header</div>
  <div id="content">Content</div>
  <div id="footer">Footer</div>
</div>

Вот что записываем в css:
  1. Элементам html и body задаём height: 100%;.
  2. Элементу wrapper задаём min-height: 100%; position: relative;.
  3. Элементу footer задаём position: absolute;. Из-за абсолютного позиционирования ширина блока автоматически изменилась на auto. Исправляем это с помощью width: 100%;. Позиционируем блок внизу родительского элемента — bottom: 0;. Задаём блоку фиксированную высоту.
  4. Чтобы footer не налазил на содержимое блока content, добавляем блоку content нижний padding равный высоте блока footer.

Но сегодня я подсмотрел, на первый взгляд, более изящное решение. Вот готовый пример.

HTML-код:
<div id="wrapper">
  <div id="header">Header</div>
  <div id="content">Content</div>
</div>
<div id="footer">Footer</div>

Вот что записываем в css:
  1. Как и в первом случае, элементам html и body задаём height: 100%;.
  2. Элементу wrapper задаём min-height: 100%;, но на этот раз никак не позиционируем его.
  3. Элементу footer задаём фиксированную высоту, а затем задаем ему отрицательный верхний margin равный высоте этого элемента.
  4. Как и в предыдущем примере чтобы footer не налазил на содержимое блока content, добавляем блоку content нижний padding равный высоте блока footer.

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

22 января 2010 г.

Clearfix

Я был в восторге от нового метода очистки потока от float'ов, с которым познакомился. Узнал я о нём из статьи «Clearing floats: clearfix vs overflow. Недостатки и достоинства обоих подходов».

До этого я знал два основных способа очистить поток:
  • С помощью задания overflow: hidden элементу, внутри которого мы хотим очистить поток. overflow: hidden создаёт отдельный контекст форматирования. Недостатком этого метода является то, что если нам понадобится вынести какой-то блок за границы контейнера с overflow: hidden, то этот блок не будет виден.
  • С помощью <div class="clear"></div>. У класса .clear в стилях задаём clear: both. В этом методе мне не нравилась необходимость использования лишнего пустого div'а, что бьёт по семантике.
А вот в чем заключается новый метод. Элементу, внутри которого мы хотим очистить поток, в стилях мы прописываем:
.clearfix { zoom: 1 }   /* создаем новый контекст форматирования для IE6 и 7 */
.clearfix:after {
  content: "";
  clear: both;
  display: block;
  width: 0; height: 0;
  overflow: hidden;
  font-size: 0;
}
Т.е., как мы видим, в данном методе мы используем псевдо-класс :after. В комментарие к топику можно найти ещё более упрощенную версию конструкции, которая, как мне кажется, вполне удачно справится с задачей в большинстве случаев:
.clear:after {
  content: "";
  display: block;
  clear: both;
}
/* И не забываем про hasLayout для IE */
Этот метод обладает одним очевидным приимуществом перед overflow: hidden, т.к. позволяет выносить дочерние элементы за границы родительского. В общем, при выборе какой же из методов использовать — overflow: hidden или .clear:after { }, я бы вам рекомендовал прислушаться к совету Вадима Макеева и «пользоваться связкой overflow:hidden + zoom:1, а в случаях, когда что-то нужно вытащить из контейнера, использовать dot-clearing» (dot-clearing — это тот самый новый способ, о котором и идёт речь в статье).

Не забываем о том, что IE7 и ниже не поддерживает псевдоклассы :after и :before. Для очищения потока в этих версиях браузера нужному блоку мы присваиваем hasLayuot, что создаёт новый контекст форматирования. Таким образом для IE7 и 6 мы выравниваем поток с помощью hasLayout, для остальных браузеров мы выравниваем поток с потощью clear: both — и это не одно и тоже! Рекомендую разобрать вот этот пример, в котором метод очистки потока с помощью псевдокласса :after приводит к разному результату в IE7 и ниже и в остальных браузерах.

Больше информации вы найдёте в статье «How To Clear Floats Without Structural Markup» на Position Is Everything.

1 ноября 2009 г.

Спрайты и их недостатки

Перевод статьи «To Sprite Or Not To Sprite». Автор — Vladimir Vukicevic.

CSS спрайты давно прижились среди разработчиков благодаря возможности с их помощью значительно ускорить загрузку сайта. Стив Содерс как раз представил SpriteMe! на конференции Velocity '09 (к теме о том, зачем использовать генераторы CSS спрайтов или прочие серверные инструменты, если можно использовать <canvas> и toDataURL и генерировать спрайты на лету). Впрочем, есть несколько заблуждений о CSS спрайтах, и главное из них то, что спрайты не имеют недостатков.

Основная идея CSS спрайтов в том, чтоб соединить несколько изображений, используемых на вашем сайте, в одно, тем самым уменьшив количество HTTP запросов к вашему сайту. Изображение отображается при помощи CSS свойств background и background-position (что, кстати, означает, что ваша разметка станет более сложной; изображения задаются при помощи CSS, а не с помощью тега <img>*).