2 сентября 2008 в 14:46

CSS Sprites 2: время Javascript перевод

Ощущение динамики часто являлось тем, что отличало насыщенные Flash-ем сайты от сайтов, основанных на стандартах html. До недавнего времени флэш-интерфейсы всегда казались более живыми, они взаимодействовали с пользователем динамично, и это тот функционал, который остальные сайты не могли просто взять и скопировать.

Конечно, позже состояние дел изменилось — появились эффекты для динамических интерфейсов, поддерживаемые такими JS-библиотеками, как Prototype, Scriptaculous, Moo, YUI, MochiKit (и этот список можно продолжить). Сейчас самое время (через 4 года) вспомнить технику CSS Sprites и посмотреть, сможем ли мы добавить в неё «немного динамики».

Знакомство с jQuery


Тут мы сталкиваемся с первым условием: нам нужно использовать jQuery, чтобы все получилось. jQuery – это хорошо продуманная JS-библиотека, которая предоставляет нам тот же нужный функционал, что и другие библиотеки, но обладает, помимо этого, дополнительным преимуществом, которое позволяет упростить расширение CSS Sprites: для выбора элементов страницы мы можем применять те же конструкции, что используются в CSS.

Нужно отметить, что эта библиотека требует загрузки несколько дополнительных килобайт скриптов. Конечно, внешние JS-библиотеки кэшируются и загружаются только один раз – когда посетитель сайта открывает страницу в первый раз. Самая компактная версия jQuery весит 15 кб. Это неизбежное увеличение размера страницы, и оно может стать проблемой. Если вы уже используете jQuery для других целей, тогда все нормально. Но если вы заинтересованы в добавлении только этой техники, то посчитайте размер загружаемой страницы и решите для себя, стоит ли эффект этого. (С тех пор, как jQuery хостится у Google, вы можете сделать ссылку на версию используемой библиотеки, как и мы в приведенных примерах, и надеятся, что браузеры большинства посетителей вашего сайта уже закэшировали URL библиотеки) (Пер.: На мой взгляд, автор тут немного преувеличивает проблему: jQuery одна из самых маленьких JS-библиотек и 15 лишних килобайт за динамику при первой загрузке — это нестрашно)

Как насчет других JS-библиотек? Вам абсолютно ничего не мешает использовать их. Рассматривайте эту статью как открытое приглашение портировать эту технику к той библиотеке, которой вы пользуетесь.

HTML и CSS


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

У нас уже есть основанный только на CSS метод для rollover-эффекта (т.е. эффекта при наведении), поэтому начнем создавать нашу навигацию на сайте с использованием CSS Sprites. И, поскольку мы ленивы, в дальнейшем мы не будем создавать все во второй раз, а просто возьмем эти наработки, всего лишь добавив jQuery поверх.


Картинка для CSS Sprites

Если есть какие-то вопросы по технике CSS Sprites, вы можете взглянуть на оригинальную статью, но есть несколько моментов, которые стоит разъяснить ниже. Начнем с HTML. Уделите особое внимание этой структуре, мы будем часто на неё ссылаться в дальнейшем:

<ul class='nav current-about'>
  <li class='home'><a href='#'>Home</a></li>
  <li class='about'><a href='#'>About</a></li>
  <li class='services'><a href='#'>Services</a></li>
  <li class='contact'><a href='#'>Contact</a></li>
</ul>

Каждый класс служит определенной цели: класс nav тэга ul позволяет указывать на этот элемент с помощью CSS (и позже Javascript), в то время, как второй класс current-about используется для выделения просматриваемой страницы или раздела сайта. Каждый li-элемент имеет свой уникальный класс, который также используется для указания на этот тэг в CSS или JS.

Итак, наша разметка для навигации – это простой и доступный HTML список, и у нас достаточно классов чтобы заработала техника Sprites:

.nav {
width: 401px;
height: 48px;
background: url(../i/blue-nav.gif) no-repeat;
position: absolute;
top: 100px;
left: 100px;
}


Мы установили свойство position равным absolute, чтобы изменить точку отсчета для позиционных сдвигов тэгов li. Мы могли бы также использовать значение relative, чтобы достичь того же эффекта и, в то же время, оставляя элемент .nav в нормальном потоке. Есть некоторые причины использовать значение relative, но в этой статье мы будем применять значение absolute. Больше информации по этому вопросу вы можете получить в статье Дугласа Боумана.

Основа самой техники Sprites в нашем случае – это использование background-изображений для каждого элемента навигации и их абсолютное позиционирование внутри родительского тэга ul:

.nav li a:link, .nav li a:visited {
position: absolute;
top: 0;
height: 48px;
text-indent: -9000px;
overflow: hidden;
}

.nav .home a:link, .nav .home a:visited {
left: 23px;
width: 76px;
}

.nav .home a:hover, .nav .home a:focus {
background: url(../i/blue-nav.gif) no-repeat -23px -49px;
}

.nav .home a:active {
background: url(../i/blue-nav.gif) no-repeat -23px -98px;
}


Мы собираемся продвинуться немножко дальше, чем в оригинальной статье, и определим состояния focus и active. Первое состояние – это небольшое добавление к переключателю изображений, когда ссылка является субъектом состояния hover или focus, состояние active добавляет новое свойство – при клике на элемент. Они необязательны, но это хорошая идея — определить стили для обоих состояний. Правило “overflow: hidden” также новое в наших стилях, оно служит для того, чтобы предотвратить появление визуального бага в некоторых браузерах.

Пример 1: Настройка CSS Sprites для меню.

Итак, мы подошли к стартовой точке – у нас теперь есть работающее навигационное меню, основанное на технике CSS Sprites, с возможностью выбора активного элемента. Разовьем нашу идею дальше.

Начальная настройка jQuery


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

$(document).ready(function(){
  // весь код здесь
});


Поскольку спрайтовое меню – это наше «меню по умолчанию» для отключенного Javascript (если мы все сделали правильно), то нам лучше избавиться от всех определенных в стилях фоновых изображений для элементов при наведении, поэтому мы создадим новые фоновые изображения с помощью скрипта:

$(".nav").children("li").each(function() {
  $(this).children("a").css({backgroundImage:"none"});
});


В первой строчке запрашиваются элемент(-ы) класса nav и после применяется функция к каждому дочернему элементу li, который они содержат. Эта функция показана во второй строчке кода, она опрашивает объект this (под this подразумеваются найденные тэги li) на наличие дочерних тэгов a внутри него. Если такие существуют, то для свойства CSS background-image этих элементов устанавливается значение none.

Пример 2: Отключение стилей при наведении с помощью jQuery.

Это работает… но мы также потеряли выделение выбранного пункта меню в процессе. Поэтому нам нужно проверять название нашего current-(выбранный пункт меню) класса для родительского тэга ul, чтобы сохранить фоновое изображение для выбранного элемента. Предыдущий код необходимо немного расширить:

$(".nav").children("li").each(function() {
  var current = "nav current-" + ($(this).attr("class"));
  var parentClass = $(".nav").attr("class");
  if (parentClass != current) {
    $(this).children("a").css({backgroundImage:"none"});
  }
});


(Пер.: В следующем абзаце подробно объясняется, что делает вышеприведенный код. Я посчитал это излишним – это очевидно даже тем, кто не знаком с jQuery. :))

Привязка событий


Теперь нам нужно привязать функцию к каждому из элементов li для каждого события-взаимодействия, к которому применяются стили. Давайте создадим функцию для этого и назовем её attachNavEvents:

function attachNavEvents(parent, myClass) {
  $(parent + " ." + myClass).mouseover(function() {
    // какой-то код
  }).mouseout(function() {
    // какой-то код
  }).mousedown(function() {
    // какой-то код
  }).mouseup(function() {
    // какой-то код
  });
}


Эта функция принимает 2 аргумента. Первый аргумент – строка, содержащая название класса родительского элемента. Второй аргумент – строка, содержащая название название класса тэга li, к которому привязываются события. Мы скомбинировали оба аргумента в следующей строке функции, чтобы создать селектор, аналогичным применяемому в CSS, например такой .nav .home.

Поскольку jQuery позволяет привязывать сразу несколько функций к одному объекту, мы смогли создать все функции для обработки событий сразу (в одной цепочке). Цепочка функций – это уникальная концепция jQuery. Не стоит заморачиваться насчет неё – не так важно, как она работает. Поэтому если вы находитесь в небольшом замешательстве, просто примите на веру то, что мы сейчас делаем.

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

attachNavEvents(".nav", "home");
attachNavEvents(".nav", "about");
attachNavEvents(".nav", "services");
attachNavEvents(".nav", "contact");


Пока мы почти ничего не сделали, но у нас все впереди.

Пример 3: Начальная настройка скрипта для событий.

Теория


Я собираюсь объяснить, что мы будем делать дальше. Это важно понять, потому что вам нужно будет создать стили для элементов, с которыми мы будем работать.

Для каждой из ссылок мы создадим новый тэг div внутри тэга li. Этот новый тэг мы и будем использовать для эффектов jQuery. Фоновое изображение для тэга div будет то же самое, что мы использовали ранее для тэга a (и оно зависит также от родительского тэга li). Мы абсолютно позиционируем тэг div (он будет позиционироваться относительно элемента .nav). Таким образом, мы почти полностью скопировали существующий тэг a из нашей начальной конструкции CSS Sprites. Путем проб и ошибок я выяснил, что создание нового тэга div позволяет с меньшими трудностями создать динамические эффекты на jQuery, чем если мы будем обходиться только существующими тэгами, так что это необходимый шаг.

Стили для тэга div должны быть заранее прописаны в CSS. Мы создадим новый уникальный класс для div (например, .nav-home), зависящий от названия родительского класса li, и добавим к нему стили:

.nav-home {
position: absolute;
top: 0;
left: 23px;
width: 76px;
height: 48px;
background: url(../i/blue-nav.gif) no-repeat -23px -49px;
}


Практика


Настало время добавления эффектов. Когда срабатывает событие mouseover, мы создаем элемент div c соответствующим названием класса. Нам нужно, чтобы этот тэг был невидимым перед тем, как он появится, поэтому используем jQuery-функцию css для задания ему свойства display: none. Наконец, мы используем jQuery-функцию fadeIn для плавного появления div и передаем ей в качестве аргумента значение 200, чтобы определить длительность анимации в миллисекундах:

function attachNavEvents(parent, myClass) {
  $(parent + " ." + myClass).mouseover(function() {
    $(this).before('<div class="nav-' + myClass + '"></div>');
    $("div.nav-" + myClass).css({display:"none"}).fadeIn(200);
  });
}


Затем мы делаем то же самое, только наоборот, для события mouseout – наш div должен плавно исчезнуть. После того, как он исчезнет, мы удаляем div из DOM. Вот как наша функция attachNavEvents должна работать:

function attachNavEvents(parent, myClass) {
  $(parent + " ." + myClass).mouseover(function() {
    $(this).before('<div class="nav-' + myClass + '"></div>');
    $("div.nav-" + myClass).css({display:"none"}).fadeIn(200);
  }).mouseout(function() {
    // псевдо-ссылка плавно исчезает и уничтожается
    $("div.nav-" + myClass).fadeOut(200, function() {
      $(this).remove();
    });
  });
}


И этого достаточно для эффектов при наведении.

Пример 4: Добавление эффектов при наведении.

Нам следует подумать об обработке событий mousedown и mouseup, поскольку у нас в стилях было прописано состояние active для ссылок. Создадим другой класс, чтобы мы могли ссылаться только на него в CSS и менять название класса при возникновении события mousedown. При возникновении события mouseup, будет возвращаться прежнее название класса для тэга div. Вот как будет выглядеть функция attachNavEvents после этих изменений:

function attachNavEvents(parent, myClass) {
  $(parent + " ." + myClass).mouseover(function() {
    $(this).before('<div class="nav-' + myClass + '"></div>');
    $("div.nav-" + myClass).css({display:"none"}).fadeIn(200);
  }).mouseout(function() {
    $("div.nav-" + myClass).fadeOut(200, function() {
      $(this).remove();
    });
  }).mousedown(function() {
    $("div.nav-" + myClass).attr("class", "nav-" + myClass + "-click");
  }).mouseup(function() {
    $("div.nav-" + myClass + "-click").attr("class", "nav-" + myClass);
  });
}


Мы можем повторно использовать стили при наведении на тэг div, всего лишь немного изменив положение фонового спрайтового изображения для создания стилей при клике:

.nav-home, .nav-home-click {
position: absolute;
top: 0;
left: 23px;
width: 76px;
height: 48px;
background: url(../i/blue-nav.gif) no-repeat -23px -49px;
}

.nav-home-click {
background: url(../i/blue-nav.gif) no-repeat -23px -98px;
}


Теперь у нас есть эффекты при наведении, мы видим выбранный элемент навигации, и эффекты при клике также работают.

Пример 5: Собираем все вместе.

Другие размышления


Мы не ограничены только эффектом «fade». jQuery имеет встроенные функции «slideUp/slideDown», которые тоже можно использовать (второй пример в статье). Или мы даже можем проявить фантазию и задействовать собственные анимационные эффекты, основанные на стилях и использующие jQuery-функцию animate (третий пример). Сразу предупреждаем насчет функции animate — анимация может получиться не очень плавной, как вы могли заметить в нашем примере.

Кроссбраузерная совместимость – это как своеобразный небольшой подарок для вас, jQuery прекрасно работает во всех современных браузерах, и все, что вы видите здесь, работает в ИЕ6, ИЕ7, ФФ2, ФФ3, Сафари, Опере и т.д. Мы даже предусмотрели множество грациозных способов обхода ограничения функционала. Так, если у посетителя сайта отключен Javascript, он увидит динамику, реализованную с помощью CSS Sprites. (Пер.: Это не работает в ИЕ6) Если же отключены CSS и JS, посетитель увидит простой ul-список. Мы получаем и другие преимущества CSS Sprites помимо этого, так как можем использовать одну картинку для различных навигационных состояний и эффектов.

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

Еще одна небольшая проблема, с которой вы можете столкнуться – это когда текст на сайте начинает «моргать» во время анимации. Это сложное явление связано с рендерингом суб-пикселей, присущим современным операционным системам. Лучшее решение этой проблемы – задать почти непрозрачное значение opacity, чтобы рендеринг текста проводился особым образом. Если вы добавите эту строчку в свои стили, то «моргание текста» должно прекратиться, только текст будет сглаживаться обычным образом, а не с помощью суб-пикселей:

p {
  opacity 0.9999;
}


Пакет функций для Sprites2


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

$(document).ready(function(){
  generateSprites(".nav", "current-", true, 150, "slide");
});


Функция generateSprites принимает 5 аргументов:
1. Название класса родительского ul, включая точку.
2. Префикс, используемый для выбранных элементов (например, для выбранного класса selected-about, используйте "selected-" в качестве значения префикса).
3. Переключатель, показывающий, используются ли стили для состояния active. Если вы определяете состояние :active и его эквиваленты в jQuery в вашей таблице стилей, установите значение true. В противном случае нужно установить false.
4. Скорость анимации, в миллисекундах (300 = 0.3 секунды).
5. Тип анимации, строковая переменная. Установите «slide» или «fade», последнее стоит по умолчанию.

Пример 6: Всего одна простая строчка кода для изменения благодаря нашей функции.

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

Заметки


Во время написания этой статьи в интернете распространилась схожая техника, хотя и без дополнительной поддержки CSS Sprites. Мы также обнаружили совсем другое анимированное jQuery меню, которое вы можете найти полезным.
Автор оригинала: Dave Shea
Neophyte @Neophyte
карма
27,9
рейтинг 0,0
Самое читаемое Разработка

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

  • –7
    Есть более удачная альтернатива CSS spites- кроссбраузерный data: url
    habrahabr.ru/blogs/client_side_optimization/28177/
    • 0
      CSS Sprites 2 примерно так же относится к CSS Sprites, как Pixel Perfect — к Firebug…
      • –3
        для чего вы используете CSS Sprites?
        • –2
          Если вы про эту статью, то использую не я, а Dave Shea. И, к тому же, в этой статье достаточно подробно написано, для чего именно используется CSS Sprites. Надеюсь вы её прочитали…

          Что касается меня, использовал эту технику на одном сайте для кастомизации тем.
          • –12
            я слышал что они используются для сокращения количества запросов серверу, в статье к сожалению я не нашёл упоминания зачем они используются в данном случае (прочитал бегло), не могли бы вы процитировать?
            • –2
              В данном случае CSS Sprites применяется для обеспечения работы меню при отключенном Javascript.
              • –16
                почему оно не будет работать если это будет не спрайт а разные рисунки?
                • –2
                  Я конечно понимаю, что у вас нет времени, чтобы нормально прочитать всю статью, походить по ссылкам, которых там предостаточно. Но у меня сейчас тоже не очень много времени, я 7 часов потратил на перевод. Так что, гугл вам в помощь… или возвращайтесь позже, перечитайте внимательнее.
                  • –2
                    то есть вы признаёте что css sprites здесь вообще не нужен, потому что могу спокойно вместо этого:
                    .nav .home a: hover, .nav .home a: focus {
                    background: url(../i/blue-nav.gif) no-repeat -23px -49px;
                    }

                    .nav .home a: active {
                    background: url(../i/blue-nav.gif) no-repeat -23px -98px;
                    }

                    написать это:
                    .nav .home a: hover, .nav .home a: focus {
                    background: url(../i/blue-focus.gif) no-repeat 50% 50%;
                    }

                    .nav .home a: active {
                    background: url(../i/blue-active.gif) no-repeat 50% 50%;
                    }

                    и что css sprites это прошлый век, камень в огород верстальщика, и надо использовать data: url?
                    • –1
                      Да, безусловно вы во всем правы, и где вы только раньше были…

                      З.Ы. Обязательно пошлите Dave Shea (Дейву Ши) письмо о своих наблюдениях!
                      • –12
                        раз вы со мной слогласны вы могли бы ему и написать, или даже перевести!
                        • –3
                          Обязательно переведу… как-нибудь в следующем веке. Напомните только, ок?
                    • –1
                      я так понимаю дело в том, что картинка ../i/blue-nav.gif будет уже загружена, а картинка ../i/blue-active.gif загрузится только при наведении на объект курсора.
                      И еще делать два запроса к серверу или один — есть разница
                      • –9
                        совершенно верно, но чем спрайты лучше data: url?
                        • –9
                          возразить не можете- минусуете?
                        • 0
                          Уважаемый arestov, это не самостоятельная статья, это перевод статьи с сайта alistapart.com. Автор той статьи решил использовать технику CSS Sprites. Он забыл спросить у меня, не спросил он и у вас.

                          data: url конечно лучше, с этим никто не спорит, но спрайт — слаще… Так что выбирайте сами, что использовать.

                          Да, и гугл находится по адресу google.com
                          • –9
                            к сожалению ничем не слаще
                        • –1
                          в вашем примере приведено две картинки, соответственно 2 запроса к серверу вместо одного, что для высоконагруженных серверов является роскошью
                          • –1
                            Не думаю, что из-за одной лишней картинки, которую сервер обязательно закэширует, могут возникнуть какие-либо проблемы с нагрузкой. :)
                            • 0
                              Разработчики Яндекса так не думают. И я с ними солидарен
                          • –9
                            в моём примере 1 css файл. всего 1.
                            поддержка позиционирования как хочешь (background-position) и соответсвенно никаких рисков с заползанием куда не надо
                            а у вас?
                            • –4
                              Ну в этом примере все замечательно, но поддерживать css с url data сложнее, и добавляет лишнего кода в css, если в нескольких разных элементах нужна одна и та же картинка. Во всем нужен разумный компромисс.

                              Во всяком случае, когда в дизайне сайта встречается сотня разнообразных графических элементов, то это повод задуматься, а уж использовать sprite или все вставлять в один css с url data это на вкус разработчика.
                              • 0
                                gzip успешно сжимает пофторяющиеся куски.об этом было написано
                        • –4
                          Проще, быстрее, надежнее. И для высоконагруженных серваков надо считать не «1 картинка, 2 картинки» и прирост количества запросов процентов на 30, если элементов много.
                          • –9
                            м.. тут ктонибудь вообще в курсе того о чём говорит?
                            • 0
                              Да просто понять хотим: ну какого хрена вы НАВЯЗЫВАЕТЕ свое? Ваш пример хорош. Но что-то в нем настораживает.
                              • –12
                                до сих пор я так и не получил ответа чем спрайты лучше. его я и добиваюсь

                                а собралась тут стадо баранов которые плюют во все инновационное как в новый логотип яндекса и даже не могут объяснить почему старый лучше
                                • –1
                                  Это инновационное имеет столько «но», что…
                                • –4
                                  Пока explorer не будет этого поддерживать я не буду этого применять. Невыгодно. Плюс, увеличивая размер CSS вы увеличиваете вероятность того, что он не загрузится и клиент увидит нестилизированную страницу.
                                  Пока что спрайты более отказоустойчивая техника.
      • 0
        видимо, мысль оказалась недостаточно понятна: сейчас data: URL является реальной альтернативой для CSS Sprites. Со своими плюсами и минусами (уже статьи 3-4 на эту тему на Хабре было). arestov попытался сделать акцент именно на это. Т.е. автор заметки, скорее всего, не имеет представления об использовании последней техники (либо усиленно замалчивает свое знание).

        Хотя, имхо, будущее именно за ней. Ибо технологически реализовывать ее несколько проще, а бонусов чуток больше (минус 1 запрос к серверу). Что и указано в приведенной статье
        • 0
          Уважаемый sunnybear, я уже упоминал здесь, что моя статья всего лишь перевод. Причем перевод статьи не о том, как оптимизировать что-то, и называется она в оригинале «CSS Sprites2 — It's Javascript Time», а не, например, «CSS Sprites2 — It's Optimization Time». Большая её часть посвящена реализации техники с помощью jQuery, и автор статьи не настаивает на использовании именно этой JS-библиотеки. А CSS Sprites идет как backend, ему посвящены всего несколько абзацев. Ничто не мешает использовать вместо него data: url в данном случае.

          Согласитесь, было бы нехорошо, если бы, например, обсуждения статей о реализации чего-либо на PHP, начинались с коммента «Есть более удачная альтернатива PHP — Python» или «В Ruby on Rails это реализуется парой строк». Начало обсуждения статьи было, на мой взгляд, из той же серии. arestov начал обсуждение именно с какого-то утверждения, приведя в доказательство ссылку на вашу статью. Но он, во-первых, по сути не прочитал мой топик (!!) (если бы он прочитал, то не задал бы некоторых своих вопросов), во-вторых, не понял, что это перевод (и я не автор), и, в-третьих, стал ждать того, что я ему буду что-то объяснять по статье, хотя в ней очень подробно все расписано. Говорить о том, что чувствуешь, только что потратив солидное время на перевод, общаясь с человеком, нормально не прочитавшим статью и задающим вопросы имеющие довольно отдаленное отношение к её сути, думаю не стоит. Но мы с ним уже закрыли этот вопрос в личной переписке.

          Оптимизация — это огромная тема (в которой вы очень хорошо разбираетесь, судя по профайлу). Я не занимаюсь вопросами оптимизации, но в той фирме, где я работаю, естественно затрагиваются эти вопросы. У нас, почему-то, бОльшую прибавку в скорости дают оптимизации на сервере, запросов к базе данных и программного кода (Ruby). Разница в скорости по сравнению с неоптимизированным кодом получаются чуть ли не на порядок, и этого вполне хватает. До вопросов оптимизации картинок, Javascript и СSS мы почти никогда не добирались, может из-за того, что не было крупных проектов.
  • +3
    Отличная статья, но странно видеть типографские кавычки («, ») в коде. =)
    • 0
      Спасибо, постараюсь исправить кавычки. У меня были небольшие проблемы с форматированием кода, особенно с расставлением отступов.
      • 0
        Исправил
        • –4
          Спасибо!
  • 0
    Много минусов. Пора плюсовать.
    • –4
      Да тут плюсуй не плюсуй, все никак не выходит вытянуть в «+»… :-(
  • +2
    Итоговая функция конечно врядли кому пригодиться, но общие подходы расписаны неплохо.
    Отдельное спасибо за решение бага с мерцанием (opacity 0.9999)
  • –4
    Размер шрифта не масштабируестя(одна из причин не использовать sprites)… А это большой пропуск в юзабилити — так делать не надо! В общем… работа новичка-непрофесионалла :)
    • +1
      Чтобы все отлично масштабировалось, нужно вообще отказаться от графического текста на сайте.

      А то, что на alistapart.com печатают новичков-непрофессионалов — это фраза дня… :)
      • 0
        nobody's perfect… alistapart.com too :)
    • +1
      не масштабируется-ли? ) опера, ff — никаких проблем. Сафари и IE — не работает. Так или иначе но в IE это тоже будет. Потом +)
      • 0
        правда никаких проблем… у 50% процентов пользователей интернета IE… никаких проблем!
  • 0
    Я несколько лет назад сделал клон Battle City на JS+CSS… Где он сейчас — не знаю, надо будет поискать.
  • 0
    Все понравилось, статья хорошая. Только в пятом примере, если быстро нажать на кнопку и убрать курсор, то кнопка остается со стилем, как при наведении.

    Использовал FireFox 3.0, IE 6.0, Opera 9.23, Google Chrome =))

  • 0
    Отличная статейка. Очень понравилось. Можно было б наверное даже jQuery-плагин оформить, вдруг пригодится ;-)

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