Чай со спецэффектами

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

Для этого вам понадобятся следующие вещи: простой текстовый редактор и свежий браузер, вроде Firefox, Opera, Safari или Chrome. Чем свежее, тем лучше — хорошо бы даже ночную сборку или какую-нибудь альфу.

Готовим основу

Для начала подготовим основу для нашего чаепития. На мой взгляд, прогрессивный HTML5-шаблон с простым доктайпом <!DOCTYPE HTML> подойдёт лучше всего:

<!DOCTYPE HTML>
<html lang="en-US">
<head>
    <title>Чай со спецэффектами</title>
    <meta charset="UTF-8">
</head>
<body>

</body>
</html>

Обратите внимание на атрибут lang элемента <html> — мы собираемся заваривать английский чай с американским акцентом, и его значение как раз соответствует нашему замыслу: en-US. Дальше нам это ещё пригодится.

Теперь давайте отыщем подходящую чашку. Точнее, даже не отыщем, а тут же соберём из знакомых частей. Из чего мы можем составить обычную чашку чая? Как минимум, из самой чашки cup и блюдца saucer. Чашка состоит из сосуда vessel с ручкой handle, в который последовательно налиты чай tea, брошены два кусочка сахара sugar, по вкусу, а замыкается это всё донышком bottom. Так у нас и получилось:

<div class="cup">
    <div class="vessel">
        <div class="tea">
            <div class="sugar"></div>
            <div class="sugar"></div>
            <div class="bottom"></div>
        </div>
    </div>
    <div class="handle"></div>
</div>
<div class="saucer"></div>

Итак, основа для нашего чаепития готова, начинаем его рисовать.

Раскрашиваем набросок

Теперь отбросим все браузерные условности простым ластиком. Чай у нас незамысловатый, поэтому здесь подойдёт и * { … }. Для более сложных проектов всё же рекомендуется использовать reset.css

* {
    padding:0;
    margin:0;
    }

Наступает очередь воплотить все составные части нашего чая: позиционируем их по центру, правильно расставляем z-index, задаём размеры и цвет фона для каждого элемента. Вот как выглядит чашка:

.cup {
    position:absolute;
    top:50%;
    left:50%;
    z-index:2;
    margin:-150px 0 0 -150px;
    width:300px;
    height:300px;
    }

…и получаем пример №1, он же на картинке.

Если вы остались довольны получившимся кубизмом — хорошо, значит вас устроит чаепитие даже в компании Internet Explorer. Те, кому этого мало, приглашаются дальше.

Спиливаем лишнее

И всё-таки, чашка должна быть круглой. Хотя бы для того, чтобы во время размешивания там не застревала чайная ложка. Давайте всё скруглим. После недавнего выхода альфа-версии Opera 10.50 с широкой поддержкой модуля CSS Backgrounds and Borders Level 3 для этих целей мы вполне можем рассчитывать на свойство border-radius.

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

.saucer {
    position:absolute;
    top:50%;
    left:50%;
    z-index:1;
    margin:-250px 0 0 -250px;
    width:500px;
    height:500px;
    -webkit-border-radius:250px;
    -moz-border-radius:250px;
    border-radius:250px;
    background:#FFF;
    }

В данном случае компактное правило border-radius:250px задаёт радиус скругления всех четырёх углов, точно так же, как margin:0 обнуляет поля со всех четырёх сторон элемента.

Обратите внимание на префиксы -webkit и -moz — они нужны браузерам на основе Webkit (Safari, Chrome) и Gecko (Firefox) для того, чтобы применить скругление. Последняя альфа браузера Opera обрабатывает свойство без префикса. Подобным же образом мы скругляем сосуд, чай и донышко. Ручку и подтаявшие кусочки сахара мы подтачиваем до скруглённых брусков.

И получаем пример №2, он же на картинке.

И хорошо бы: всё скруглилось, встало на свои места. Так ведь и просилась бы чашка в руки, если бы не пугала своей плоской двухмерностью. Самое время добавить немного объёма.

Надуваем чашку

Будем честны, мы здесь не пытаемся заигрывать с Canvas, поэтому объём у нас будет псевдо-трёхмерным. А много ли надо нам, жертвам квадратного и плоского веба? Берём в руки свойство box-shadow и вперёд:

.vessel {
    -webkit-box-shadow:20px 20px 100px rgba(0,0,0,.8);
    -moz-box-shadow:20px 20px 100px rgba(0,0,0,.8);
    box-shadow:20px 20px 100px rgba(0,0,0,.8);
    }

Свойство box-shadow конструируется просто: горизонтальное смещение тени, вертикальное, размер и цвет, который мы задаём в виде rgba(), чтобы последним значением указать полупрозрачность заливки. В случае с элементом tea, также используется ключевое слово inset, чтобы повернуть тень внутрь элемента.

И вот пример №3, он же на картинке.

Ну, что — чай уже почти как настоящий. За исключением некоторых проблем: тени в браузерах на движке Webkit рассчитываются весьма загадочно (см. заметку Firefox против Photoshop), поэтому, в нашем случае, выглядят более жёстко. Также текущая версия Webkit в браузере Safari 4.0.4 пока не умеет применять ключевое слово inset, однако Chrome уже справляется.

Осталось только добавить в это чаепитие немного жизни.

Художественный беспорядок

Самая очевидная проблема нашей чашки — это отвалившаяся ручка и вставшие пирамидой кусочки сахара. Давайте разбросаем всё это по своим местам и попробуем размешать сахар. Поможет нам в этом свойство transform и методы rotate() и translate(), занимающиеся, соответственно, поворотом и перемещением элементов.

Обратите внимание, что для краткости в этой части примеры кода будут приводится без дублирования свойств с префиксами -webkit, -moz и -o. Полный код вы можете найти в примерах.

Для начала, вернём ручку ровно в центр чашки, изменив значение отрицательного поля, а потом применим transform: повернём на –145 градусов и сместим на 170 пикселей.

.handle {
    margin:-20px 0 0 -45px;
    transform:rotate(-145deg) translate(170px,0);
    }

Принимаемся за кубики: их у нас ровно два. Не знаю, как для вас, но для меня это оптимальное количество сахара. И нам нужно обратиться к каждому из кубиков, чтобы применить нужное смещение. Самым удачным способом будет посчитать их по порядку появления в чае, при помощи селектора :nth-child():

.sugar:nth-child(1) {
    transform:rotate(70deg) translate(-20px,20px);
    }
.sugar:nth-child(2) {
    transform:rotate(30deg) translate(35px,0);
    }

Теперь всё на месте, и вроде бы можно пить чай, но сахар упорно не желает размешиваться. Значит, самое время встряхнуть его при помощи сочетания свойств transform и transition. Для начала мы задаём каждому кубику новое смещение, которое произойдёт при наведении на чашку: поворот на 1200 градусов и новые координаты.

.cup:hover
.sugar:nth-child(1) {
    transform:rotate(1200deg) translate(-20px,20px);
    }

А затем описываем сам процесс перемещения:

.sugar {
    transition:transform 10s ease-out;
    }

Синтаксис свойства transition простой: сначала идёт то свойство, которое мы собираемся изменять, потом время и тип ускорения, в нашем случае ease-out, что значит с замедлением. При наведении курсора на чашку .cup:hover сахар будет размешиваться по часовой стрелке, при отведении — в обратную сторону.

И вот пример №4, он же на картинке.

Практически всё готово. Самые нетерпеливые могут браться за чай, остальные же приглашаются дальше — добавить разнообразия.

Немного разнообразия

Сколько людей, столько и вкусов. Поэтому давайте добавим нашему чаепитию возможность выбрать в какой традиции пить чай: в английской, русской или японской. Предлагаю сделать это наиболее адекватно, используя упомянутый выше атрибут lang элемента <html>. Для этого добавим возможность выбора:

<ul class="switcher">
    <li lang="en-US" title="Английски"></li>
    <li lang="ru-RU" title="Русский"></li>
    <li lang="ja-JP" title="Японский"></li>
</ul>

Каждый из пунктов нашего меню будет переключать атрибут lang на нужный язык при помощи нехитрого скрипта, навешивающего обработчики:

function init() {
    var html = document.documentElement;
    var items = document.querySelectorAll('ul.switcher li');
    for(var i=0; i<items.length; i++){
        items[i].onclick = function() {
            html.lang = this.lang;
        }
    }
}
window.onload = init;

В этом скрипте используется удобнейший метод querySelectorAll, который позволяет выбрать нужные элементы при помощи CSS-селекторов наподобие jQuery.

Осталось только добавить специфические стили для каждого из языков (тематическую скатерть и цвет чая) и поменять состояние текущего пункта меню. Вся магия происходит благодаря псевдо-классу :lang(), который появляется у каждого элемента после того, как мы обновили атрибут lang элемента <html>:

BODY:lang(en-US) {
    background:#519AB8 url(i/en.png);
    }
.switcher:lang(en-US) LI[lang=en-US],
.switcher:lang(ru-RU) LI[lang=ru-RU],
.switcher:lang(ja-JP) LI[lang=ja-JP] {
    border-color:#FFF;
    cursor:default;
    }

И, наконец, последний пример №5, он же на картинке. Чай готов, сахар по вкусу — можно пить :)

Комментарии

45

Браво!
Моё чувство прекрасного, основанное на чистом HTML и максимальном избежании JS, просто в восторге.

Вадим, вы извращенец в хорошем смысле этого слова, но это скоро нас всех накроет похоже. Продажи фотошопа могут резко пойти вниз. Мне нравится Overall performance score 100 и Grade A on Make fewer HTTP requests в YSlow. Спасибо!

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

Первый раз за года два вижу атрибут lang в действии, хоть и не серьезном (: Спасибо за хорошую статью!

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

Надо было переключение языка сделать через :target :) Чтобы никакого JS :) Но всё равно классно. Отличная идея!

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

Круто! И не подумал бы, что такое можно сделать без картинок. А ведь всего год-два назад такое трудно было представить.
Хотя мне вариант в Опере 10.10, тоже нравится))

Потрясающе, а такие моменты особенно жаль что до сих пор есть ИЕ ((

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

asp_id, рисовать «на чистом HTML» это немного дико с точки зрения логики документа. Прогрессивные ребята сейчас рисуют на упомянутом Canvas (отрисовка точек через JS) и SVG (XML-подобный векторный язык).

BOLK, я сначала сделал через :target, но там возникли проблемы с изначальным состоянием и во время обновления. Ну, и хотелось завязать всё на lang.

dreikanter, Chrome for Mac 4.0.249.43 показывает всё совсем по-другому: с жёсткой тенью и без артефактов. Странно…

Чистяков Денис, скругление для всех четырёх углов просто пишется короче, чем для двух — а если не видно разницы, то зачем платить больше? ;)

Наверное, круто было бы еще сделать, чтобы сахар постепенно таял :)

sparrow, была такая идея — просто не дошли руки. Может выпущу через некоторое время «Чаепитие 2» ;)

Здорово. HTML/CSS стал уже пригоден для писания демок, как амига и спектрум во время оно.

Скорей бы IE научился border-radius-у !
А почему Opera взалась за default селекторы? А не стала делать -opera-border-radius и т.п.? Неужто Firefox и WebToolkit до такого не додумались?

мда.. в ИЕ8 зрелище плачевное(
и судя по некоторым материалам от разрабов микрософта — в ИЕ9 будет не намного лучше...
вообще, шикарно)
я все никак ХТМЛ5 не начну осваивать (останавливает то, что пока это скорее фетиш, чем реально полезный навык...)

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

invite, боюсь, что особенно никак — разве что ставить минимальную высоту для body, чтобы появлялась прокрутка.

все же смею напомнить о суровой действительности в этом мире:

90% - держатели мышки двумя руками
максимум на что можно рассчитывать - это ие 8
пока мелкие не пошевеляться: все что вы делаете - в жопу

так что не дурите мозги со своими новыми технологиями
лет через 5 открою гугл и почитаю на оф сайтах что и как делать

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

metaluga, сам ты фотосрачень, чем GIMP не устраивает? Уже больше года рисую дизайны для сайтов в нем (более полусотни заказчиков). И не один не пожаловался. А если руки кривые - ни один фотошоп не поможет

Неплохой пример, вот только на будущее

если бы всех массово пересадить с ИЕ, то можно было бы активно внедрять. А так даже современные браузеры не все в полной мере осилили пример: Chrome 6.0.472.63 beta

А вращение чая в чашке выглядит в каждом браузере иначе (:

Я в восторге!
transform:rotate(-145deg) translate(170px,0);
В справочнике CSS3 эти свойства не нашел. Откуда их брали?

jumancy, давайте так: я вам скажу откуда я взял эти свойства, а вы мне — откуда вы взяли такой сомнительный CSS3-справочник.

Если говорить про справочник, то купите и прочитайте живую или электронную версию книги «CSS3 for Designers»; посмотрите на список CSS-свойств, разделённый по версиям; или почитайте какие свойства поддерживает Opera, Firefox и IE10.

Супер. Спасибо за урок! Добавить звуки и меняющийся бэкграунд - выйдет отличная утренняя открытка