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

Играет на уровне мастера, то есть пытается либо выиграть, либо свести к ничьей. Вычисления позиций проводил через реализацию
Кстати, несмотря на всю винтажность, от браузера требуется поддержка CSS3, включая трансформации.
Я сильно не тестировал, спать уже надо ложиться. Если будут ошибки, пишите, постараюсь поправить, если только они не относятся к недостаткам алгоритма Остермиллера.
CSS hack for FireFox 6
Меня тут попросили сделать
x::-moz-progress-bar, body {
background: orange; /* FF 6.0+ */
}
@-moz-document regexp(".*") {
body {
background: orange; /* FF 6.0+ */
}
}Проверено на Firefox 6.0 и 7.0.1.
Аналог conditional comments появится в CSS
Ура, ребята из W3C одумались и в CSS появится аналог conditional comments. Первого сентября появился черновик нового модуля CSS3 — «CSS Conditional Rules Module Level 3». Самое интересное в нём — новое правило «@supports», которое позволяет проверить поддерживает ли браузер определённый функционал (жаль только нет правила
Есть поддержка «not», «or» и «and», а так же группировки скобками:
@supports (transition-property: color) or
((animation-name: foo)) and
(transform: rotate(10deg))) {
// …
}Начинание хорошее, но выглядит очень уж громоздко, в документации есть вот такой пример:
@supports ( box-shadow: 2px 2px 2px black ) or
( -moz-box-shadow: 2px 2px 2px black ) or
( -webkit-box-shadow: 2px 2px 2px black ) or
( -o-box-shadow: 2px 2px 2px black ) {
.outline {
color: white;
box-shadow: 2px 2px 2px black;
-moz-box-shadow: 2px 2px 2px black;
-webkit-box-shadow: 2px 2px 2px black;
-o-box-shadow: 2px 2px 2px black;
}
}Я легко могу представить когда нужна будет ещё более ветвистая и страшная конструкция. Трудности я понимаю — нужно хорошо вписать конструкцию в уже существующий синтаксис CSS. Была бы моя воля, я бы сделал
.outline {
box-shadow: 2px 2px 2px black !fallback(no-box);
-moz-box-shadow: 2px 2px 2px black !fallback(no-box);
-webkit-box-shadow: 2px 2px 2px black !fallback(no-box);
-o-box-shadow: 2px 2px 2px black !fallback(no-box);
}
@fallback no-box, no-smth-else {
/* попадаем сюда, если все условия с таким именем внутри селектора не выполнились */
}Менее гибко в плане условий, но более просто, коротко и не позволяет городить сложные условия (я считаю, что они сильно снижают читаемость).
Кто-нибудь делал CSS snap to grid?
У меня тут задача возникла очень нетривиальная — сделать CSS snap to grid. Если не получится, сделаю через JavaScript. С ходу вчера мне не удалось придумать как это сделать по горизонтали (а мне надо именно так), только по вертикали возникли
Текстовые ссылки в графике

Читая последнюю, на настоящий момент, статью в Ководстве Лебедева «Правила оформления ссылок» обратил внимание, что Студия в этом месте, вроде как, не всегда следует своим же советам.
В правом верхнем углу располагается логотип Студии, являющийся ссылкой, где текстом написано «Студия Артемия Лебедева». Я понимаю, что это картинка, но простой пользователь этого не поймёт, да и какая разница — текст есть текст, прорендерен ли он заранее в графике или это сделала операционная система позже.
Написал письмо Артемию, посмотрим что ответит.
Технических трудностей, между тем, в подчёркивании таких ссылок никаких — прочертил линию в графике и всё, ссылка подчёркнута. Другое дело в подствечивании при наведении, кажется что это невозможно. Но это только на первый взгляд. Я уже демонстировал (неоднократно), что это делается очень просто.
Такие опыты я производил четыре года назад, так даже постоянные читатели вряд ли помнят. В GIF или PNG под ссылкой «прорезается» (прочерчивается прозрачным) полоска, которая будет имитировать наше подчёркивание. Картинке в CSS ставится фон ссылки (например, синий), при наведении фон меняется, схематически:
img {
background: blue;
}
img:hover, img:visited {
background: red;
}JS CSS в одном файле у меня на сайте
Я
Особых трудностей не встретил, только убрал все комментарии из файлов с JavaScript руками и добавил удаление BOM из файлов, браузеры
Схема,
Вот ещё тонкость, обязательно нужно добавить новый
AddType */* .cssjsОказалось, что последний «Хром» ни в какую не хочет рендерить CSS с таким типом, пришлось заменить на «text/css,*/*» на «text/css», предыдущий вариант не работал в IE9.
Надо посмотреть как отнесётся к этому второй FF, а пока, если у вас «Хром» или IE9 и показывает неправильно, обновите, пожалуйста, страницу, чтобы она не из кеша взялась, всё должно нормально отрендериться.
Посмотрим «в поле» насколько это стабильно работает.
CSSO
Ребята из симферопольского «Яндекса» сказали новое слово в оптимизации CSS — CSSO. Оптимизатор интересен тем, что умеет минимизировать с изменением структуры — то есть удалять перекрываемые свойства, производить слияние блоков с одинаковыми селекторами и тому подобное.
Сергей Крыжановский, который занимается программированием CSSO, в своём блоге хорошо описал отличия CSSO от YUI Compressor, CSSTidy и им подобных.
Например, CSSO умеет вот такое:
/* до CSSO */
.a {
color: red;
border: 0;
}
.b {
color: red;
}
/* после CSSO */
.a{border:0}.a,.b{color:red}Меня несказанно печалит, что оптимизатор написан на JavaScript, потому что хостинг с серверным JS найти крайне проблематично, но зато оптимизацию в действии можно попробовать прямо в браузере.
CSS и JS в одном файле
Раз уж я затронул тему снижения числа коннектов к серверу при загрузке сайта, то было бы уместо вспомнить незаслуженно забытую технику — объединение JS и CSS в одном файле.
Насколько я знаю, первым эту технику исследовал некий ShivaP в статье «Combine CSS with JS and make it into a single download!» ещё четыре года назад.
Идея такова: в файле специальными ухищрениями помещается и код JavaScript, и код CSS, файл подключается два раза — один раз через тег SCRIPT, второй раз через тег LINK (как CSS), браузер грузит файл один раз, а второй раз берёт его уже из кеша.
Автор проверил свою идею на двух браузерах — IE и FireFox, на том и остановился.
Я проверил эту идею на гораздо бо́льшем числе браузеров (обнаружил проблемы на некоторых «Хромах» и исправил), а так же немного её видоизменил, разрешив использовать многострочный CSS без особых неудобств. Последнее нужно персонально мне, так как у меня нет возможности прогонять свой CSS через оптимизаторы и вытягивать таким образом код CSS в одну строку, а я хочу использовать эту технику у себя на сайте.
У техники есть ограничение, которое не портит много крови, но о нём необходимо знать — в тексте CSS и JS не должна встречаться конструкция «*/». Если в CSS достаточно просто выкусить все комментарии («*/» там, можно считать, нигде больше встретиться не может), то в JS за этим придётся следить, так как такая комбинация вполне может встретиться, в частности, в регулярных выражениях. Например: var regexp = /smth*/g;
В таких случаях звёздочку необходимо прятать (например, заменять её в регулярных выражениях на \x2A или разбивать строку: «smth*» + «/»).
Как ShivaP, первый исследователь этой техники, решил проблему размещения JS и CSS в одном файле можно почитать в оринальной статье, я же поступил несколько иначе, но сходным образом. Конструкции размещаются так, чтобы JS оказывался в комментариях CSS и наоборот. Я похожими вещами уже занимался неоднократно.
Мой код выглядит следующим образом (я поставил рядом две картинки, чтобы можно было сравнить как один и тот же код воспринимается интерпретатором JavaScript и парсером CSS):

Как видите, принцип довольно несложен.
Теперь несколько слов о том как это всё подключается:
<link type="text/css" rel="stylesheet" href="core.jscss" />
<script type="text/javascript" src="core.jscss#2"></script>Обратите внимание на «#2» после core.jscss, этот хак позволяет обойти странное поведение некоторых версий «Хрома» — без него браузер не делал попыток подгрузить файл ещё раз и JavaScript не выполнялся.
Немаловажно так же, что заголовок
У себя на сайте я буду использовать скрипт наподобие нижеприведённого, чтобы разом разрешить все проблемы и выставить правильные заголовки. Формат вызова простой: скрипту через запятую перечисляются файлы, которые нужно объединить и подключить (файлы берутся из папки «media», см. переменную «$dir»): /util/js+css.php?core.js,core.css,another.css,another.jsЧитать дальше
<?
ob_start();
$dir = 'media/';
$expires = 10 * 365 * 24 * 60 * 60; // 10 years
$files = explode(',', str_replace('..', '', $_SERVER['QUERY_STRING']));
$css = $js = array();
foreach ($files as $file) {
switch (pathinfo($file, PATHINFO_EXTENSION)) {
case 'css':
$css[] = $dir . $file;
break;
case 'js':
$js[] = $dir . $file;
break;
}
}
$css = @array_map('file_get_contents', array_unique($css));
$js = @array_map('file_get_contents', array_unique($js));
$css = implode($css);
$js = implode($js, ';');
// removes /* comments */ from css
$css = preg_replace('!/\*.*?\*/!s', '', $css);
// removes only first /* comment */ from js
$js = preg_replace('!^/\*.*?\*/!s', '', $js);
echo <<<JSCSS
// /*
$js
"*/{"/*"}
$css
*/
JSCSS;
$len = ob_get_length();
$txt = ob_get_clean();
$etag = '"' . sha1($etag) . '"';
header("Content-type: */*; charset=utf-8");
header("Expires: " . gmdate('D, d M Y H:i:s \G\M\T', $_SERVER['REQUEST_TIME'] + $expires));
header("Cache-control: max-age=$expires, public");
header("Content-length: " . $len);
header('ETag: ' . $etag);
if (isset($_SERVER['HTTP_IF_NONE_MATCH'])) {
list ($hash) = explode(';', $_SERVER['HTTP_IF_NONE_MATCH']);
if ($hash == $etag) {
header('HTTP/1.1 304 Not modified, thanx for yr question');
exit;
}
}
echo $txt;
Размер табуляции в CSS
В CSS3 есть хорошее свойство
Тем временем, свойство уже реализовано в некоторых браузерах, с собственным префиксом. Свойство первым поддержала «Опера» (с версии 10.60, именно от этой компании и было выдвинуто предложение добавить это свойство в CSS3), затем оно было реализовано в четвёртой версии FireFox. Остальные браузеры пока не подтянулись.
Вот как выглядит
body {
-o-tab-size: 4; /* размер табуляции — 4 (для Оперы 10.60+) */
-moz-tab-size: 4; /* размер табуляции — 4 (для FireFox 4+) */
-webkit-tab-size: 4; /* для будущих версий Safari и Chrome */
tab-size: 4; /* размер табуляции — 4, на будущее */
}Значение
Добавлено позднее: для WebKit уже есть патч для поддержки свойства
Синтаксис @font-face, совместимый с IE
@font-face {
font-family: 'MyFontFamily';
src: url('myfont-webfont.eot#') format('eot'),
url('myfont-webfont.woff') format('woff'),
url('myfont-webfont.ttf') format('truetype'),
url('myfont-webfont.svg#svgFontName') format('svg');
}У IE
Посмотрите на третью строку, видите там „#“? IE
Вот такой простой и красивый трюк.
Добавлено позднее: не все поняли. После решётки в адресе страницы идёт идентификатор внутри страницы. Эта часть на сервер на отсылается.
Прозрачный фон SVG в Хроме и Сафари
Владислав Шкодин написал статью на «Хабре», где рассказал как ему удалось победить старый баг в движке WebKit — если вставить SVG с прозрачным фоном в тег OBJECT, что «Сафари» и «Хром»
Решение очень простое. Прямо внутри файла SVG, после тега svg нужно написать следующее:
<style>
svg { -webkit-background-clip: text; }
</style>
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» нарушают стандарт уже в этом месте, я проверил), если не задан специальный
Прочитайте комментарий, там есть немаловажные подробности.
Невидимая страница
Если бы мне сегодня показали исходник страницы (будет видно только в «Опере» и «FireFox»), который я встретил сейчас на «Хабре», я был бы озадачен куда больше.
Кода у этой страницы просто нет. Ларчик открывается (в «Опере» и FF) просто: есть такой RFC 5988, озаглавленный «Web Linking», где описан способ подключать в документ различные ресурсы прямо через
Идея проста: подключаем через заголовок CSS для пустой страницы и внутри CSS уже формируем то, что нужно (текст можно писать через свойство «content»).
Link: </pathto/magic.css>;rel=stylesheetIE9 и CSS3 2D Transforms
Появился Internet Explorer 9 PP6, из интересного — появилась поддержка
Кроме того, появилась поддержка семантических тегов HTML5 (section, nav, article и так далее). Раньше при разборе дерева элементы, содержащие эти теги наследовались от HTMLUnknownElement, теперь — от HTMLElement.
Мощь SVG и media queries
Вадим Макеев демонстрирует сейчас на фестивале «404» мощь SVG — картинка сама (через CSS media queries) изменяется для разных разрешений экрана, при масштабировании полноценное лого с текстом ужимается, текст сначала переносится, потом исчезает и остаётся один логотип.
Ребята, о таком применении SVG я даже и не думал, это очень круто.
Другой пример — внутри SVG выбирает один из внедрённых растров, опять же в зависимости от разрешения экрана (а можно, кстати, показывать специальную
Дополнено позднее: Вадим выложил слайды своего доклада (смотреть надо в «Опере»).
Зачем нужны все эти -moz-, -o-, -ms-, -webkit-?
На сайте
Хотя я
CSS vs. JSSS
Почти никто не помнит, но в прошлом веке, в браузере Netscape Navigator (который позже стал Communicator) был ещё один способ задавать таблицы стилей — JSSS.
Вообще, сейчас принято с теплотой вспоминать поделие Netscape и осуждать Microsoft за самоуправство в стандартах, но тогда время было такое. Кто такие были W3C и кто — Microsoft с Netscape. В Netscape придумывали «стандартов» никак не меньше (а то и больше), чем в Microsoft. И где сейчас LAYER, MULTICOL или тот же JSSS? Впрочем, фирма Netscape в 1996 году отправила JSSS в W3C.
Выглядел JSSS примерно так (даже функции поддерживались!):
<style type="text/javascript">
tags.p.fontSize = "14pt";
with(tags.H2)
{
color = "red";
fontSize = "16pt";
marginTop = "2cm";
}
contextual(tags.H1, tags.EM, ids.x78, classes.foo.all).color = evaluate_color();
tags.P.firstLine.fontStyle = "small-caps";
tags.IMG.width = .50 * document.width;
if (visual.colorDepth > 2) {
body.bgColor = "white";
body.color = "blue";
} else {
body.bgColor = "black";
body.color = "white";
}
</style>И иногда, перебирая в голове ушедшие технологии, я задумываюсь — а не было бы принятие JSSS вместо CSS более удачным шагом? Нужно было бы учить на один язык меньше (JS уже есть в браузере), да и последние тенденции в CSS3 показывают, что он медленно двигается в сторону
Вот пример:
@media only screen and (max-width: 1024px) {
div {
width: -moz-calc(100% - 2 * 3px);
height: -moz-max(50%, 18px);
}
}
@-webkit-variables {
step: -1;
}
ol {
counter-reset: list -webkit-var(step);
}
li:before {
counter-increment: list;
content: counter(list) ". ";
}Уже похоже
Так вот, нужно ли это всё было городить? В JavaScript это уже есть. Впрочем, нужны, конечно, ограничения, чтобы JSSS не превратился в труднопроходимую кашу, CSS более лаконичен и строг. Но вопрос в том, удобно ли уже сейчас читать CSS больших проектов? Я пробовал, мой ответ — вряд ли. Это чудовищно сложно.
В общем, мне кажется, что Netscape был
CSS хак для WebKit («Хром» и «Сафари») через «__qem»
Я тут понял, что CSS Unit «__qem» вполне себе подходит на роль
К примеру:
div {
background: #000; /* фон будет чёрным везде, кроме… */
background: 0__qem #fff; /* …WebKit, тут он будет белым */
border: 0; /* бордюра не будет, кроме… */
border: 0__qem solid black; border-width: 10px; /* …WebKit, тут будет чёрный толстый бордюр */
position: relative; /* блок будет виден везде, кроме… */
top: -100000_qem; /* …WebKit, тут его видно не будет */
}Я попробовал поиграть с Media Queries, скомбинировать с «__qem» не удалось, но зато выяснилось, что браузеры и тут стандарт нарушают:
@media (color: 0!) {
/* работает в «Хроме», по крайней мере, в 6-м */
}
@media (color: 0_) {
/* работает в «Опере», по крайней мере, в 10.60 */
@media {
/* работает в «Опере» 10.60, «Хроме» 6, не работае в FF4, IE8, IE9PP2 */
}
}Судя по всему, эта нестандартная единица измерения не распознаётся
Снова про кроссбраузерные скруглённые уголки
Решение проблемы скруглённых уголков через VML есть в статье Льва Солнцева «Кроссбраузерные закруглённые уголки» (без JavaScript). Проблема заключается в следующем:
В VML есть предопределённая фигура: прямоугольник с закруглёнными углами roundrect. […] Но у этой фигуры есть один значительный недостаток: радиус кривизны задаётся через отношение к большей стороне, что делает результат непредсказуемым и неподходящим для многих случаев.
То есть, при одинаковом параметре закругления блоков разного размера, радиус кривизны будет различаться.
Идея: кнопка добавления в Google Reader
В комментариях к одному из постов, меня попросили сделать кнопку добавления RSS комментариев в «Google Reader» (если я правильно помню суть просьбы).
Мне эта идея не нравится, потому что я не знаю какое количество моих читателей пользуется «Google Reader», остальным, понятно, эта кнопка ни к чему. Я тут подумал — хорошо было бы ставить эту кнопку тем, что этим сервисом «Гугла» пользуется. Но как узнать кто пользуется, а кто нет?
Сейчас меня осенило (впрочем, скоро это не будет работать в Firefox, когда выйдет версия 3.7). Всё просто — надо найти URL по которому заходит только авторизованный пользователь «Google Reader», причём URL этот должен быть инвариантен пользователю, может это
Далее всё просто — у данной ссылки есть то свойство, значит пользователь недавно логинился в «Google Reader», если нет, не логинился. На основании этого можно ставить или убирать кнопку добавления RSS в этот сервис. Можно ещё выставить куку, чтобы в дальнейшем основываться уже на её наличии (если есть — пользователь пользуется «Google Reader», нет — ничего не значит).