html
«Крестики-нолики» на HTML и CSS
Давно хотел попробовать сделать

Играет на уровне мастера, то есть пытается либо выиграть, либо свести к ничьей. Вычисления позиций проводил через реализацию
Кстати, несмотря на всю винтажность, от браузера требуется поддержка CSS3, включая трансформации.
Я сильно не тестировал, спать уже надо ложиться. Если будут ошибки, пишите, постараюсь поправить, если только они не относятся к недостаткам алгоритма Остермиллера.
В IE10 не будет попадать под conditional comments
«Микрософт» решила, что conditional comments не должны обнаруживать IE10. То есть, по идее, условия «[if IE]», «[if IE 10]», «[if IE gt 5]» работать не должны, а «[if IE lte 9]»
Поведение изменено
Because some features in earlier versions of IE aren’t compatible with HTML5 parsing, we’ve removed them from IE10 mode. Sites that rely on these legacy features will still work when running in legacy modes. This way, sites that work today will continue to work with IE10 even if the developers of the site don’t have the time to update them.
Причём «Микрософт» тут же признаётся, что парсер ни при чём:
This means conditional comments can still be used, but will only target older versions of IE.
Если часть условия conditional comments
Скорее «Микрософт» этим шагом заявляет, что «мы так всё идеально поддерживаем, что нет нужды отделять IE от других браузеров». Может быть это и так. Но я был бы рад, если бы conditional comments появились в других браузерах, а не исчезли был из IE.
Помимо этого из IE10 исчезнут Element Behaviors и XML Data Islands.
Добавлено позднее: мы тут поговорили с Вадимом Макеевым, кажется, я ошибаюсь. В режимах эмуляции старых браузеров (вероятно в этот момент работает отдельный движок), conditional comments работают, в режиме IE10 — нет.
Увеличение числа параллельных соединений браузера к одному домену из HTML
Большинство разработчиков сайтов уже знают, что число соединений к серверу у браузеров лимитированно. Старые версии браузеров используют только два соединения на сервер, более свежие побольше (например, «Опера» 11.10 — аж 16).
В общем случае алгоритм использования этих соединений достаточно сложен и отличается от браузера к браузеру (имеется ввиду будут ли параллельно загружаются стилевые таблицы, скрипты и прочее), но общее правило неизменно — больше своего лимита браузер соединений к серверу не плодит.
Между тем, это не всегда хорошо, ведь если все соединения заняты, то браузер ждёт данных по ним, не инициируя новые, даже если канал до сервера позволяет загрузить
Если сайт и канал вполне выдержат и большее количество соединений от одного пользователя (с учётом посещаемости), то есть хитрость, которую часто используют — загружать статику (картинки, файлы стилей и прочее) с других доменов. Их не обязательно располагать на других серверах, достаточно дать одному серверу несколько имён и использовать их для загрузки.
Выглядеть это может так: static1.example.org, static2.example.org и так далее. «Яндекс», к примеру, грузит свои данные с домена yandex.st. Как видите, подходит другой домен любого уровня.
Хорошо, когда есть возможность завести любое количество доменов
Ничего страшного, чаще всего у пользователя такого хостинга аж четыре домена, просто мало кто об этом подозревает. Первые два достаточно очевидны — хостер часто, кроме
Ещё два не так очевидны— это домены «example.org.» и «www.example.org.». Обратите внимание на точку в конце домена.
Мои эксперименты (проверял на сервисе BrowserShots, операционные системы Linux, Windows XP, Mac OS X) говорят о том, что браузеры умеют с ними работать, то есть картинки с URL, где имя домена кончалось на точку, грузились нормально.
Для того, чтобы проверить считают ли браузеры домены с точкой в конце и без различными, я создал небольшой скрипт, который отдаёт картинку без кеширования с секундной задержкой.
В эксперименте я выставил максимальное количество соединений к серверу в единицу («Опера» и «FireFox» позволяют это сделать, где это делается в браузерах на WebKit я не знаю, подскажите, если знаете) и создал две

На скриншоте хорошо заметен результат и видно где какой эксперимент (по колонке «Домен»). По скриншоту видно, что я использовал хорошо всем знакомый FireBug, но на Dragonfly из «Оперы» картина такая же.
HTTP-заголовок Default-Style
Если бы я сейчас на ночь глядя не решил почитать по диагонали спецификацию тега LINK, то так, наверное, никогда в жизни бы и не узнал о существовании
Если у вас подключены несколько таблиц стилей к одному документу, вы можете дать им имя, прописав его в атрибуте «title», и выбрать его через
<head>
<style type="text/css" title="right">
body {
background: blue;
}
</style>
<style type="text/css" title="wrong">
body {
background: red;
}
</style>
<meta http-equiv="Default-Style" content="right" />
</head>Работать должен только стиль с именем «right» (можно дать и русские имена). Слово должен я выделил, потому что это стандарт. Жизнь, как всегда, богаче.
Я проверил на браузерах, которые у меня есть, в «Опере» 11 RC3 и Internet Explorer 9 beta это не работает, работает в Firefox 3.6.12, Safari 5 и Chrome 9.0.597.19, можете проверить свой браузер, фон должен быть синим.
Можно из этого сделать своеобразный
Добавлено: во встроенном браузере на моём «Нексусе» работает («Андроид» 2.2.1), в Firefox 2.0 и Chrome 5.0.375.125 — тоже.
Добавлено ещё позже: в комментарях меня поправляет Денис Попов: по стандарту если заданы несколько тегов LINK, задающих стили с title, то выбирается первый («Опера» и «IE» нарушают стандарт уже в этом месте, я проверил), если не задан специальный
Прочитайте комментарий, там есть немаловажные подробности.
Воздушный бой на чистом HTML

Все в последнее время настолько в восторге от новых возможностей браузеров, что пишут игру за игрой на HTML5/CSS/JavaScript. Это всё скучно. Вчера перед сном я размышлял об игре на чистом HTML (даже без CSS), а сегодня, пока собирался в Самару, на 404fest, потихоньку её написал.
Встречайте — Pure HTML Air Fight. Написано на чистом HTML, без использования JavaScript, CSS и серверной логики. На сервере отрабатывает только скрипт, контролирующий введённый URL и запускающий игру, если URL ошибочен.
Задача классическая — попасть в пролетающий самолёт, внизу есть кнопка, запускающая ракету. Скорость самолёта и задержка меняется (на самом деле они жёстко зависят от момента пуска ракеты, у меня же чистый HTML, никакого рандома).
Кстати, в игре есть фоновый звук при попадании в самолёт.
Добавлено позднее: сайт под «хабрэффектом», так что может открываться крайне медленно, игра может вообще не работать.
Добавлено ещё позднее: некоторые ребята (в том числе в комментариях на «Хабре»)
rel="noreferrer"
Как известно, около года назад в WebKit появилась поддержка атрибута «rel» у ссылки со значением «noreferrer». Если указать это значение, то браузер не будет передавать заголовок «referer», в котором указано с какого адреса браузер осуществил переход.
Это прекрасная вещь, которая позволяет защищать, к примеру, информацию из интранета. У нас (в «Яндексе») стоят специальные скрипты для скрытия заголовка «referer» специальными ухищрениями, чтобы предотвратить утечку (так как некоторые сервисы у нас с ЧПУ) данных. Этот атрибут, если он был бы реализован везде, решил бы эту задачу более изящно.
К сожалению, с его распространением, думаю, будет расти его параноидальное использование, что сильно повлияет на статистику. Сейчас можно быть
Ну и ещё один показатель бардака —
P.S. Возможно поддержка «noreferrer» и ещё
IE, непрямоугольные блоки и тени

Что я хочу сказать по поводу статьи «Хитрая тень» в блоге Олега Мохова?
<html>
<head>
<xml:namespace ns="urn:schemas-microsoft-com:vml" prefix="v"/>
<style type="text/css">
.vml {
behavior: url(#default#VML);
-ms-behavior: url(#default#VML);
font: 12px Tahoma, sans-serif;
}
#bar1 {
width: 400px;
height: 60px;
color: white;
padding: 12px;
display: block;
}
#bar2 {
width: 20px;
height: 22px;
padding: 12px;
color: white;
position:absolute;
}
</style>
</head>
<body>
<v:roundrect class="vml" id="bar1" fillcolor="navy" strokecolor="navy" strokeweight="1px" arcsize="0.1">
Привет, ребята из W3C! Отсталый Internet Explorer уже много-много лет умеет смешивать векторный язык и
HTML, а в 2010 году не все продвинутые браузеры так умеют.
<v:shadow class="vml" on="true" opacity="0.3" color="navy" offset="7px,5px" />
</v:roundrect>
<v:shape class="vml" id="bar2"
fillcolor="red" strokecolor="red"
coordorigin="0 0" coordsize="200 200"
path="m 1,1 l 800,1, 800,400, 1800,400, 1800,1500, 1,1500, x e">
<v:shadow class="vml" on="true" opacity="0.3" color="red" offset="7px,5px" />
<p>Привет<br />ещё раз!</p>
<p>Вы знаете, уже Internet Explorer 5.0 умеет делать непрямоугольные блоки.</p>
<p>Причём, делает это непринуждённо.</p>
</v:shape>
</body>
</html>Что IE умеет круче ещё с пятой версии.
Добавлено позднее: в комментариях мне подсказывают, что в IE8/9 надо либо включать режим эмуляции, либо использовать
Четыре малоизвестных факта о conditional comments (условных комментариях) в Internet Explorer
<!--[if VML]> Код VML <![endif]-->Можно, например, проверить запущен ли браузер на Windows 7. «Семёрка» и Vista вообще сильно отличаются по возможностям по XP, так что это иногда может быть полезно. Например, в Vista/7 поддерживается TLS SNI или аппаратное
<!--[if WindowsEdition]> Это Windows 7 или старше <![endif] --><!--[if gte MyPlugn 1.2]> Мой плагин версии 1.2 и выше <![endif] -->Этот же способ позволяет изменить версию IE для проверки в conditional comments на любую — достаточно исправить значение «IE» в указанной ветки реестра и перезапустить браузер.
<!--[if (IE 7) | (WindowsEdition)]> Это IE7 или любой IE на Windows 7 и выше <![endif] -->
<!--[if (gte IE 6) & (lt IE 9)]> Это IE6-8 <![endif] -->Регулятор громкости в плеере для IE
Я недавно делал плеер для Internet Explorer по функциональности похожий на VideoJS. Как я уже упоминал, там ни одной картинки — всё VML. Регулятор громкости и кнопочки —
Попробую описать как сделан регулятор громкости, но писать буду под стандартные браузеры, так что код будет несколько отличаться.

На рисунке мы видим прямоугольник со скруглёнными углами, это сумеет сделать даже моя бабуля (в IE для этой цели я использовал VML):
#video_volume {
width: 34px;
height: 20px;
font: 14px Arial;
color: white;
background: gray;
-webkit-border-radius: 0.5em;
-moz-border-radius: 0.5em;
-khtml-border-radius: 0.5em;
border-radius: 0.5em;
}У нас получается пустой скруглённый прямоугольник. Теперь надо нарисовать уменьшающиеся прямоугольники. Как? Первая идея, которой я и воспользовался — вложить теги внутрь друг друга и сделать
<span>❚<span>❚<span>❚<span>❚<span>❚</span></span></span></span></span>В стиле прописываем абсолютную позицию
#video_volume span {
position: absolute;
margin-top: 1px;
}Получилась этакая рекурсия стилей. Уже близко к тому, что хочется получить.

Теперь надо снизу обрезать лишнее. В IE я просто ограничил размеры и выставил
#video_volume div {
clip: rect(auto, auto, 14px, auto);
position: absolute; /* crop работает только у абсолютно позиционированных элементов */
/* кстати, ребята из W3C, почему вы забыли про crop? почему только прямоугольник, зачем position? */
}Почти то что нужно, но повёрнуто в другую сторону:

Что делать? Всё просто, это текст, значит, его можно просто развернуть в другую сторону, указав ему direction, правда при указании direction элементы регулятора прилипают к правому краю, для того, что это исправить, укажем отступ справа.
Теперь осталось обрамить это ещё одним родительским контейнером, так как указав абсолютную позицию всех элементов мы вывели их из потока. Родительский контейнер позволит регулятору занять своё место в потоке.

Получился такой код:
<head>
<style type="text/css">
#video_volume, #video_volume div {
width: 34px;
height: 20px;
font: 14px Arial;
color: white;
background: gray;
padding-right: 5px;
-webkit-border-radius: 0.5em;
-moz-border-radius: 0.5em;
-khtml-border-radius: 0.5em;
border-radius: 0.5em;
}
#video_volume div {
clip: rect(auto, auto, 14px, auto);
position: absolute;
direction: rtl;
}
#video_volume span {
position: absolute;
margin-top: 1px;
}
</style>
</head>
<body>
<div id="video_volume">
<div>
<span>❚<span>❚<span>❚<span>❚<span>❚</span></span></span></span></span>
</div>
</div>
</body>Кстати, «Опере» rtl правильно не работает (по крайней мере в моей 10.60 alpha), нужно расставлять margin, но я этого делать не буду.
Тег video и IE
Интересно, когда консорциум W3 отвернулся от тега OBJECT? Помнится, даже IFRAME старательно пытались заменить на OBJECT, а сейчас
Тем не менее, API ActiveX Windows Media Player хорошо документирован и работать с ним очень просто. Я в последнее время мало программирую на JavaScript и вчера вечером, чтобы освежить знания, попробовал сделал плеер, похожий на VideoJS, но только для IE — с тегом OBJECT и применением VML.

Сегодня утром решил не останавливатся на достигнутом и за завтраком начал делать другую
P.S. Некоторые вещи там сделаны неоптимально, так что я бы очень рекомендовал несколько подчистить код, если
P.P.S. Кнопочки и progress bar нарисованы через VML.
Input multiple-2
По мотивам предыдущего поста. Чтобы Opera 9+ (а так же 3.5—6.05), Firefox 3.6+, Chrome 3.0.191.0+ и Safari 4.0.1+ позволили выбрать несколько файлов в диалоге загрузки файлов, нужно написать вот такой код:
<form enctype="multipart/form-data" method="post">
<input type="file" min="1" max="9999" name="file[]" multiple="true" />
<input type="submit" name="submit" />
</form>Я указал «file[]» для того, чтобы PHP сразу разложил полученные файлы по массиву $_FILES. К сожалению, запрос от «Оперы» PHP понимает неверно, так как «Опера» шлёт такой запрос в формате multipart/mixed. К счастью, PHP в этом случае положит содержимое файлов одним
Я попробовал, это несложно. Для того, чтобы разобрать
if (isset($_POST['file'], $_POST['file'][0])) {
if ($idx = strpos($_POST['file'][0], "\n")) {
$bound = substr($_POST['file'][0], 2, $idx-2);
$body = "MIME-Version: 1.0\nContent-type: multipart/form-data; boundary={$bound}\n\n".
$_POST['file'][0];
unset($_POST['file'][0]);
$f = &$_FILES['file'];
$f['name'] = $f['type'] = $f['tmp_name'] = $f['error'] = $f['size'];
$msg = mailparse_msg_create();
if (mailparse_msg_parse($msg, $body)) {
$i = 0;
foreach(mailparse_msg_get_structure($msg) as $st) {
$section = mailparse_msg_get_part($msg, $st);
$data = mailparse_msg_get_part_data($section);
if ($data['content-type'] == 'multipart/form-data') {
continue;
}
ob_start();
if (mailparse_msg_extract_part($section, $body)) {
$tmp = tempnam(sys_get_temp_dir(), 'php');
file_put_contents($tmp, ob_get_clean());
$f['name'][$i] = $data['disposition-filename'];
$f['type'][$i] = $data['content-type'];
$f['tmp_name'][$i] = $tmp;
$f['error'][$i] = 0;
$f['size'][$i] = filesize($tmp);
$i++;
} else {
ob_end_clean();
}
}
}
unset($f);
mailparse_msg_free($msg);
}
}
var_dump($_FILES); // результат помещатся в $_FILES, не забудьте удалить временные файлы после обработки!У меня ожидается, что содержимое файлов будет передано как параметр «file[]» (в $_POST это будет $_POST[’file’][0]), но пример несложно переделать на любое другое имя или сделать это имя параметром.
Input multiple
Я
<input type="file" name="input" multiple="true" />Ещё более интересно, что в свежей бете (№4) этого браузера есть возможность (как я понял) получить доступ к выбранным файлам
Попробовал посмотреть как выгдядит прикрепление нескольких файлов со стороны PHP, оказалось всё просто — достаточно сказать PHP, что из входящих данных нужно сделать массив и всё работает (например, указать name=«input[]»): в каждом поле каждого элемента массива $_FILES содержится массив значений. Вот как это выглядит для двух файлов:
array(1) {
["input"]=>
array(5) {
["name"]=>
array(2) {
[0]=>
string(14) "2009.09.23.jpg"
[1]=>
string(14) "2009.08.25.jpg"
}
["type"]=>
array(2) {
[0]=>
string(10) "image/jpeg"
[1]=>
string(10) "image/jpeg"
}
["tmp_name"]=>
array(2) {
[0]=>
string(18) "Z:\tmp\php3740.tmp"
[1]=>
string(18) "Z:\tmp\php3741.tmp"
}
["error"]=>
array(2) {
[0]=>
int(0)
[1]=>
int(0)
}
["size"]=>
array(2) {
[0]=>
int(35005)
[1]=>
int(63030)
}
}
}Конструкция работает в Chrome с версии 3.0.191.0 и в Safari с версии 4.0.1. К сожалению, в Opera 10.20 alpha 1 поддержки нет, в IE8 — тоже.
Добавлено 29 ноября 2009 23:08: оказывается, «Опера» поддерживала с версии 3.5 загрузку сразу нескольких файлов в обычном, «однофайловом» диалоге,
Добавлено 29 ноября 2009 23:14: «Опера» 9.0 и выше поддерживает загрузку множества файлов в одном контроле, достаточно указать параметры min и max:
<form enctype="multipart/form-data" method="post">
<input type="file" min="1" max="9999" name="file" />
<input type="submit" name="submit" />
</form>Плохие новости заключаются в том, что PHP такой запрос от «Оперы» разбирать не умеет.
Добавлено через год: в «Опере» 11 атрибуты «min» и «max» удалили, но зато работает «multiple».
IE и HTML5
Ребята из Microsoft пообещали реализовать теги VIDEO и AUDIO в своём браузере. Интересно, что Microsoft просит W3C задуматься о расширении синтаксиса тегов, чтобы, например, можно было предоставить пользователю возможность просматривать (прослушивать) контент не только в разных кодеках, но и с разным качеством и/или на разных языках (!).
А мужики-то и не знают!
Сергей Чикуенок из студии Лебедева сделал потрясающее открытие: чем сложнее структура документа, тем больше тормозит браузер.
Забытый тег: KEYGEN
Реализация парсеров HTML различных браузеров содержит массу забытых тегов, о существовании которых помнят единицы, да и тем уже незачем их использовать. Один из таких тегов — KEYGEN, придуман, если не ошибаюсь, компанией Netscape для своего браузера (ещё до того как Netscape стал использовать Mozilla), содержит два атрибута — name и challenge и используется в составе форм (FORM).
Под Windows тег поддерживается всеми основными браузерами (с разным успехом) и не поддерживается альтернативным (вплоть по версии 8.0 beta2). В настоящий момент тег почти не используется. Прошло много лет и члены комитета WHATWG (основное детище который — куча браузеров и стандарт HTML5) вспомнили об этом теге.
Использование вкратце:
<form>
<keygen name="pubkey" challenge="случайная строка">
<input type="submit" value="Сгенерировать">
</form>Если ваш браузер поддерживает тег KEYGEN, вы увидите список из нескольких элементов, содержимое его зависит от браузера, но сводится к одному — длине ключа. При нажатии на кпопку отправки формы браузер сгенерирует пару ключей, публичный ключ (в формате SPKAC) будет отправлен на сервер (в поле, указанном в атрибуте «name» тега).
Сервер, получив сертификат, готовит специальный файл подписывает его и отсылает назад браузеру с заголовоком
После чего
Гадский IE8 в strict-режиме
Дома на ноуте у меня стоит Internet Explorer 8.0beta1. Принёс домой наш новый сайт, посмотреть как он будет смотреться под этим браузером. Гадский, гадский «Майкрософт»! Сайт (естественно) свёрстан в strict, так в этом браузере в strict режиме не работают фильтры! Естественно,
Кроме этого, не работают custom tags, что очень странно —
Ну и чтоб два раза не вставать — SVG в IE8 не будет.
Дополнение: переключение режима при помощи meta не дало результатов.
Data URL: так ли страшны издержки
Я уже несколько раз писал о data URL, так что наверное все уже запомнили что это такое. У этого способа внедрения ресурсов есть интересные плюсы, но, в своей массе,
из-за base64 размер изображения увеличивается на треть- невозможно использовать одно изображение несколько раз
- не работает в IE
Все эти минусы — мнимые.
По первому пункту. Многие сайты используют
По второму. Даже начинающий верстальщик знает как использовать изображение из data URL несколько раз. Для этого надо поместить его в CSS и сделать фоном контейнера.
По третьем пункту я уже высказывался. В IE до восьмой версии не было data URL (в IE8b1 поддержка есть, но очень урезанная — всего 32Кб данных), но я придумал способ как внедрять изображения в IE.
Валидный NOINDEX
Для многих валидная вёрстка — очень важная штука. На мой взгляд, валидность самоцелью быть не может и я знаю много ситуаций, где ей можно пожертвовать. Одна из этих ситуаций — использование тега NOINDEX. Для тех, кто не знает, поясню: этот тег показывает поисковой машине какую часть текста вашей страницы индексировать не нужно.
Т. е. присутсвие этого тега необходимо, но в стандарт HTML он не входит. Как быть, если требуется достичь валидности любой ценой? Обычное решение — выдавать отдельную копию страницы для поисковых машин. Изяществом оно не обладает, тем более есть способ, если не лучше, то проще. Автор утверждает, что способ был им протестирован. Я немного изменил код, потому что такое использование кажется мне более логичным:
<del class="inv"><![CDATA[<noindex>]]></del>
То, что запрещено к индексации
<del class="inv"><![CDATA[</noindex>]]></del>В таблице стилей прописывается «display: none» для класса inv:
.inv { display: none }HTML 5 draft
Странно, но группа W3C анонсировала первый публичный черновой вариант спецификации HTML5. Предрекали, что черновая версия выйдет через пару лет, а сам стандарт — лет через 15. Видимо, счастье наступит раньше. Кстати, читая стандарт HTML5 понимаешь, что «семантическая вёрска» в HTML4 — фикция (к слову, чтобы два раза не вставать, вёрстка «дивами» в текущем состоянии — хак на хаке и такое же гуано как вёрстка таблицами, но сложнее и дороже). Надо будет
ACID3 pre
Что интересно — тест ACID3 готовится к выпуску. Помимо поддержки CSS он проверяет так же и DOM. Тест пока не готов (пользоваться им нельзя, делать выводы — тоже), но лучше всего его пока проходит «Опера».