Update: немного «шлифанул» перевод напильником. Выражаю благодарность всем неравнодушным читателям.
Внимание! Под катом почти 1.5 Мб картинок и много интересных ссылок.
Итак, начнём-с…
1. В свойстве border-radius
можно использовать slash-синтаксис.
Об этом уже писалось 4 года назад, но многие новички и даже некоторые опытные разработчики не знают о существовании этой «фишки».
Верите или нет, но следующий код валиден:
.box {
border-radius: 35px 25px 30px 20px / 35px 25px 15px 30px;
}
Такой подход немного обескураживает в первый раз. Вот объяснение из спецификации:
Если значения указаны и «до», и «после» слеша, то значения «до» устанавливают горизонтальный радиус, а значения «после» « вертикальный.
Если slash отсутствует, то значения обоих радиусов считаются одинаковыми.
В спецификации также приводится следующая диаграмма:
Использование slash-а при указании значений позволит вам создавать несимметричные скругленные углы. Если хотите более подробно изучить эту тему, то почитайте указанную выше статью или, даже лучше, попробуйте интерактивное демо от MDN.
Большинство генераторов border-radius-ов не позволяют устанавливать дополнительные значения. Из всех найденных таких генераторов только MDN-овский это умеет.
2. Свойство font-weight
может принимать «относительные» значения.
Чаще всего свойство
font-weight
принимает значение normal или bold. Иногда встречаются и целочисленные значения, кратные ста, такие как 100, 200 и т.д. до 900.Но два возможных значения часто забывают —
bolder
и lighter
.Согласно спецификации, эти ключевые слова устанавливают шрифта жирнее или тоньше по сравнению с унаследованным. Такая возможность работы с отображением текста важна, если используемый шрифт имеет несколько вариантов «веса», а не только «жирный» и «нормальный».
В значениях веса, кратным ста, «жирный» равен 700, а «нормальный» — 400. Таким образом, если вы хотите установить вес в 300, то значение
lighter
, примененное к тексту, который унаследовал нормальный вес 400, установит как раз нужный вес. Если более «легкого» варианта шрифта нет (т.е. 400 — самый тонкий вариант шрифта), то те же 400 и останется, и от использования lighter
эффекта не будет.В примере используется шрифт Exo 2, который имеет 18 различных стилей, но из них нужны только некурсивные варианты шрифта — этого достаточно для всех числовых весовых значений.
В демке используется 12 вложенных box-элементов с различными значениями
font-weight
включая bolder
и lighter
, так что эффект от применения этих ключевых слов очевиден. Ниже приведены использованные стили. Обратите внимание на комментарии в коде и учтите, что каждый следующий элемент находится внутри предыдущего..box {
font-weight: 100;
}
.box-2 {
font-weight: bolder; /* maps to 400 */
}
.box-3 {
font-weight: bolder; /* maps to 700 */
}
.box-4 {
font-weight: 400;
}
.box-5 {
font-weight: bolder; /* maps to 700 */
}
.box-6 {
font-weight: bolder; /* maps to 900 */
}
.box-7 {
font-weight: 700;
}
.box-8 {
font-weight: bolder; /* maps to 900 */
}
.box-9 {
font-weight: bolder; /* maps to 900 */
}
.box-10 {
font-weight: lighter; /* maps to 700 */
}
.box-11 {
font-weight: lighter; /* maps to 400 */
}
.box-12 {
font-weight: lighter; /* maps to 100 */
}
В данном примере
bolder
и lighter
, в конечном итоге, устанавливают следующие значения веса: 100, 400, 700 и 900. С девятью различными css-стилями при использовании этих ключевых слов не получится добиться значений 200, 300, 500, 600 и 800.Это происходит из-за того, что вы указываете браузеру выбрать следующий вариант шрифта, который «жирнее» или «легче». А браузер выбирает не просто «следующий более жирный» или «следующий более тонкий» вариант, а «жирный» и «легкий» по отношению к текущему унаследованному варианту. Но, если самый «легкий» вариант шрифта имеет вес 300, например, как у Open Sans, а унаследованное значение равнялось 400, то при использовании «lighter» получится 300.
Такое поведение может сбивать с толку, но если вы «поиграетесь» с демо-примером, то всё встанет на свои места.
3. Существует свойство outline-offset
Свойство outline довольно широко известно из-за использования при дебагинге (из-за него страница не «расползается»). В спецификации, однако, добавлено свойство
outline-offset
, которые делает ровно то, что и означает — указывает сдвиг внешней границы от элемента.В демо при изменении положения ползунка меняется и величина сдвига границы. В примере указаны значения от 0px до 30px, но вы можете изменить пределы на своё усмотрение. Обратите внимание, на то, что свойство
outline
— сокращенное свойство и не включает в себя outline-offset
и его придется указывать отдельно.Главным недостатком свойства
outline-offset
является тот факт, что оно поддерживается всеми браузерами кроме Internet Explorer (даже в IE 11 его нет).4. Существует свойство table-layout
Не стоит путать это свойство с
display: table
.Т.к.
table-layout
— не самая простая «фишка» CSS для понимания, давайте сначала обратимся к спецификации, а потом посмотрим на демо:При таком подходе вертикальное выравнивание таблицы зависит не от содержимого ячейки, а от ширины таблицы, ширины колонки и границ или отступов между ячейками.
Возможно, это первый раз в истории спецификации W3C, когда что-то так сложно понять.
Но, если серьёзно, использование демо поможет.
В приведенном примере видно преимущество использования значения
fixed
для table-layout
по сравнению со значением auto
. Использование такого подхода не панацея, но всегда неплохо знать о такой возможности при использовании таблиц с ячейками различной ширины.Chris Coyier написал замечательную статью об использовании длинных строк в таблицах в прошлом году, в которой данная тема раскрывается очень хорошо.
5. Свойство vertical-align
работает по разному в ячейках таблиц и других элементах
Если вы занимаетесь разработкой сайтов с середины двухтысячных или раньше или знаете достаточно много о HTML и email-письмах, то вы, возможно, предполагаете, что свойство
vertical-align
является обычным улучшением старого HTML4-аттрибута valign
, который сайчас указан как устаревший и несоответствующий стандарту HTML5.Но свойство
vertical-align
в CSS работает не совсем так. Но не в таблицах. Что, по-моему, достаточно странно, но я полагаю, это лучше, чем свойство, вообще не работающее в таблицах.Итак, какова разница при использовании этого свойства в обычных элементах и ячейках таблиц?
Если
vertical-align
применяется НЕ к ячейкам таблиц, то оно работает по следующим правилам:- Применимо только к
inline
илиinline-block
элементам; - Не влияет на содержимое элемента, а только меняет его положение относительно других
inline
иinline-block
элементов - На свойсто могут влиять настройки текста или шрифта, такие как
line-height
и размер смежныхinline
иinline-block
элементов.
Демо.
Свойство
vertical-align
установлено у поля ввода input. При нажатии на кнопки значение свойства меняется. Обратите внимание, что все эти значения различны.Примите во внимание, что данная демка — лишь поверхностный взгляд на vertical-align. Более глубокое его рассмотрение можно изучить тут.
Когда
vertical-align
применяется к ячейке таблицы, то оно работает совсем по-другому. В частности, данное свойство применяется и к содержимому ячеек.Демо.
Как показано в примере, для
vertical-align
есть только 4 варианта значения, которые применимы к ячейкам таблицы, кроме того значение baseline
влияет и на ячейки того же уровня, что и ячейка, к которой свойство применено.6. Псевдо-элемент ::first-letter
умнее, чем вы думаете
Псевдо-элемент
::first-letter
позволяет вам стилизовать первую букву элемент (примечание переводчика — привет, капитан!), например, красиво выделить её как в печатных книгах много лет назад.Браузеры достаточно хорошо поддерживают стандарт относительно этой «первой буквы». Впервые этот псевдо-элемент я увидел в твите Matt Andrews, хотя он явно подразуемевает, что это всё таки плохая «фишка». Демо.
Это здорово, что 4 крупных браузера отображают этот псевдо-элемент одинаково, потому что, по-моему, это и есть правильный вариант отображения. Выглядело бы странным, если бы какой-нибудь символ, такой как одиночная скобочка, воспринимался как «первая буква» — это скорее можно было бы считать «первым символом», который достоин собственного нового псевдо-класса.
7. Вы можете использовать «невалидные» символы в качестве разделителей в перечне классов элемента
Этот подход обсуждал Ben Edvard в 2013 году, и, я думаю, стоит подробнее рассмотреть этот вопрос.
Ben писал об использование slash («/») в качестве разделителя HTML-классов по группам для того, чтобы сделать код более читаемым и проще сканируемым. Автор указывает, что несмотря на то, что неэкранированный slash является «невалидным» символом, браузеры его просто игнорируют, а не выдадут ошибку.
Допустим, у вас такой HTML-код:
<div class="col col-4 col-8 c-list bx bx--rounded bx--transparent">
При использовании slash-ей получается следующее:
<div class="col col-4 col-8 / c-list / bx bx--rounded bx--transparent">
Вы можете использовать любой символ (валидный или не очень) для получения того же эффекта:
<div class="col col-4 col-8 ** c-list ** bx bx--rounded bx--transparent">
<div class="col col-4 col-8 || c-list || bx bx--rounded bx--transparent">
<div class="col col-4 col-8 && c-list && bx bx--rounded bx--transparent">
Все перечисленные варианты работают нормально, в чем можно убедится, посмотрев демо
Конечно же, эти разделители не могут быть использованы в css-стилях как классы. Следующий код является неправильным и не применится к элементу:
./ {
color: blue;
}
Если вы вынуждены использовать подобные символы в названиях своих css-классов, то можно использовать вот этот инструмент. Таким образом, вышеуказанный код будет работать, если его преобразовать до такого:
.\/ {
color: blue;
}
Если продолжать эту тему, то Unicode-символы вообще не должны быть экранированы и можно творить разные безумные вещи:
.¦ {
color: hotpink;
}
.? {
color: yellow;
}
<div class="¦ ?"></div>
Кроме того, вы можете «экранировать» и эти символы тоже, вместо того чтобы использовать их напрямую. Следующие css-строки аналогичны предыдущим:
.\2665 {
color: hotpink;
}
.\2605 {
color: yellow;
}
8. Количество повторов анимации может принимать дробные значения
При описании анимации можно использовать свойство
animation-itereation-count
для того, чтобы указать, какое количество раз анимация будет проиграна:.example {
animation-iteration-count: 3;
}
Вышеуказанный код говорит, что анимация будет проигрываться 3 раза. Но, возможно, вы не знали, что можно указывать и дробные значения:
.example {
animation-iteration-count: .5;
}
В этом случае анимация будет проиграна лишь на половину первой итерации. В демо на CodePen верхнему кружку указано количество итераций 1, а нижнему — .5
Длительность итерации определяется не по изменению значений свойств во течение анимации, а именно по времени и с учетом сглаживания. В вышеупомянутом примере используется функция с линейной зависимостью от времени —
linear
.Но в этом примере уже применяется сглаживание:
Обратите внимание на то, что второй кружок прошел больше половины пути до остановки из-за другой временной функции.
Если вы разбираетесь в различных функциях сглаживания, то заметите, что при использовании
ease-in-out
второй кружок займет то же итоговое положение, что и при использовании linear
.9. Анимация, записанная в краткой форме может не работать из-за своего названия
Некоторые разработчики заметили это случайно, хотя в спецификации есть соответствующее предупреждение. Давайте рассмотрим следующую анимацию:
@keyframes reverse {
from {
left: 0;
}
to {
left: 300px;
}
}
.example {
animation: reverse 2s 1s;
}
Заметьте, я использую название анимаци
reverse
. На первый взгляд, всё хорошо, но давайте посмотрим на живой пример.Анимация не работает, т.к.
reverse
— валидное ключевое слово для свойства animation-direction
. Так же анимация не будет работать при использовании в краткой форме в названии других ключевых слов. Но всё работает хорошо при использовании «полной» формы описания.К ключевым словам-значениям
animation-direction
, «ломающими» анимации, стоит отнести и ключевые слова, относящиеся к функциям сглаживания, а так же infinite
, alternate
, running
, paused
и так далее.10. В селекторе можно указать диапазон элементов.
Не знаю, кто начал это первым использовать, но первым я увидел это демо от Gunnar Bittersmann. Допустим, у вас есть список из 20 элементов и нужно выбрать элементы с 7 по 14 включительно. Это можно сделать вот так:
ol li:nth-child(n+7):nth-child(-n+14) {
background: lightpink;
}
Демо.
В Safari из-за бага такой приём работать не будет. Однако, решение всё таки есть — Matt Pomaski починил это. Нужно всего лишь перечислить элементы выборки в другом порядке:
ol li:nth-child(-n+14):nth-child(n+7) {
background: lightpink;
}
Этот код использует цепочку связанных псевдо-классов. Хотя выражение немного запутанное, ключевые числа 7 и 14 в нём используются без изменений.
Постараюсь объяснить, как это работает. Первая часть выражения говорит: «выбрать седьмой элемент, а потом все ПОСЛЕ него». А вторая часть — «выбрать четырнадцатый элемент, а потом все ДО него». Т.к. части связаны, то на пересечении запросов получается требуемый диапазон.
Для более детального рассмотрения этой темы рекомендуется почитать более раннюю статью.
11. Псевдо-элементы могут быть применены к некоторым «пустым» элементам
Наверняка вы пробовали использовать псевдо-элементы с изображениями или input-ами. Но это не работает с «замещаемыми» элементами (примечание переводчика — в комментариях к этому переводу SelenIT2 постарался объяснить, что же это за зверь такой). Я думаю, многие разработчики предполагают, что пустые элементы (те, у которых нет закрывающего тега) так же попадают в эту категорию. Но это не так.
Вы можете использовать псевдо-элементы вместе с некторыми пустыми элементами, которые не являются «замещаемыми». Например, <hr> в этом демо.
Цветная область является тегом <hr> и его двумя псевдо-элементами
::before
и ::after
. Интересно, что подобного результата не получилось добиться от тега <br>, который тоже не является «замещаемым».Так же, вы можете использовать псевдо-элементы вместе с мета-тегами или <link>, если, конечно, готовы применить к ним свойство display: block как в этом демо.
12. Некоторые значения атрибутов регистро-зависимы при использовании в селекторах
Наконец-то, что-то непонятное. Допустим, есть такой HTML:
<div class="box"></div>
<input type="email">
Можно стилизовать оба этих элемента следующим образом:
div[class="box"] {
color: blue;
}
input[type="email"] {
border: solid 1px red;
}
Это замечательно работает. А как на счёт такого?
div[class="BOX"] {
color: blue;
}
input[type="EMAIL"] {
border: solid 1px red;
}
Значения обоих атрибутов написаны в верхнем регистре. В этом случае
.box
-элемент не получит стилизации, т.к. атрибут class
регистрозависим. Поле ввода email, однако, будет стилизовано, т.к. аттрибут type
регистронезависим. В этом нет ничего новаторского, но, возможно, вы это не замечали раньше.
Комментарии (21)
SelenIT2
21.07.2015 13:29+5Но это не работает с «замещаемыми» элементами (буду благодарен, если подскажете, что имелось ввиду — примечание переводчика).
Более того, я буду благодарен, если авторы спецификаций наконец соберутся с духом, договрятся друг с другом и объяснят всему сообществу, что имеется в виду:) А то разные спецификации в разное время понимали под этим совершенно разные вещи.
В CSS1 определение было очень простым:
Замещаемый элемент — элемент, который замещается контентом, указываемым из этого элемента. Например, в HTML элемент IMG замещается картинкой, указанной в его атрибуте SRC.
В CSS2.1 всё начало запутываться:
Замещаемый элемент
Элемент, контент которого не принадлежит модели форматирования CSS, напр. картинка, внедренный документ или аплет… У замещаемых элементов бывают внутренне присущие размеры (высота и ширина) и пропорции. Например, у растровой картинки есть внутренне присущие ширина и высота, определенные в абсолютных единицах (из чего очевидно определяются пропорции). С другой стороны, у других документов нет таких размеров (напр. у пустого HTML-документа).
Контент замещаемых элементов не рассматривается в модели рендеринга CSS.
В HTML5 вообще не стали заморачиваться с определением, а тупо в лоб перечислили, какие элементы относятся к замещаемым. Фактически туда попал весь "embedded content", который вообще как-либо отображается.
Вместе с тем существует давняя традиция относить к замещаемым элементам контролы форм, причем она активно поддерживается и разработчиками браузеров. В принципе, логика в этом есть (в каком-то смысле, системный контрол, которым замещается соотв. элемент, можно сравнить с тем же аплетом:), но, насколько я понял, документально это нигде не отражено, «так сложилось исторически» (ох, эти многострадальные контролы форм, давняя головная боль верстальщиков!).
С какого бока упомянутыйhr
попал в замещаемые — тоже вопрос (конечно, «объемная» черта, которым он по умолчанию рисовался во всяких IE3±, похожа на системный контрол...), но, опять же… вот так оно сложилось:)SelenIT2
21.07.2015 13:56Upd: традиция считать контролы форм замещаемыми, по-видимому, тянется из промежуточной версии CSS2.0 (наспех принятой в 1998-м и почти сразу же отмененной в пользу многострадальной 2.1, утрясавшейся аж до 2011-го, и то не до конца).
Zdomb Автор
22.07.2015 00:14Всё чудесатее и чудесатее!
Спасибо за развернутый комментарий, добавил его упоминание в перевод
titulusdesiderio
21.07.2015 13:37+2¦, ? — очешуеть!
за теги отдельный +Ohar
21.07.2015 16:10Ну это сильно лучше многих других виденных мной названий классов. Но это нисколько не оправдывает их применения в серьёзных проектах.
SelenIT2
21.07.2015 16:39+2На самом деле, как раз эта фича — хорошо забытое старое
двухпятивосьмилетней давности. Да и экранирование запрещенных символов в селекторах тоже не ново, во времена IE5.5-8 его умеренно активно юзали для стилизации VML-элементов (тогдашний IE считал двоеточие от неймспейс-префикса частью имени тега).
Да, для серьезных проектов лучше бы этой фиче оставаться малоизвестной, хотя… в наши дни автоматизации всего и вся, для всяких минификаторов — может, оно и имеет право на жизнь?
DjoNIK
21.07.2015 14:50-2Случайность, когнечно, но 12 малоизвестных фактов о CSS (продолжение)
zollotov
21.07.2015 23:43+1Да, сегодня день одинакового CSS на хабре !:)
mapron
22.07.2015 04:56+1Особенно интересно смотрятся названия постов. Читаешь «12 малоизвестных фактов о CSS », ставишь плюс, видишь «12 малоизвестных фактов о CSS — продолжение», думаешь, о, почитаю продолжение! И тут эффект дежа вю =)
tegArt
22.07.2015 08:25+4Справедливости ради слово «продолжение» есть в названии оригинальной статьи, но получилось забавно, согласен :)
berezuev
22.07.2015 13:00-2За .¦ .? надо палками из профессии гнать. И за другие «невалидные» символы, на всякий случай, тоже.
Понаверстают хрени, потом за ними переписывать.DmitryAnatolich
29.07.2015 22:25Кого надо гнать из профессии, так это кодеров LJ. За что? Да за то, что в CSS не может быть не-ASCII символов (включая кириллицу, да). Ни в каком виде.
tegArt
Блин… переводил-переводил, 2 пункта не осталось и на тебе :(
Zdomb Автор
Ох не зря я вчера ночью этот перевод доделывал, видимо (:
tegArt
Я не знаю какие неведомые силы я на себя натравлю, но мне совесть не позволит забить и не выложить свой вариант… столько времени на перевод ушло… А вам успехов и добро пожаловать на хабр )
vmb
На трекерах обычно бывает раздел анонсов, где люди объявляют о планах рипнуть какой-то HD-фильм, чтобы другие не тратили на этот же фильм время. Наверное, нужно было бы создать такой же раздел или тему на Хабре, чтобы переводчики могли проверять, не взял ли уже кто-то в перевод статью.
vmb
Голосуйте: habrahabr.ru/post/263227
Zdomb Автор
Спасибо за пожелания.
Итогом этого небольшого конфликта интересов может быть новая полезная фишка на Хабре, что уже есть неплохо для первого поста (:
Даже не знаю, стоит ли загадывать подобных эффектов для следующих моих «творений»…
spmbt
Не толпитесь, уважаемые авторы, хлеба хватит на всех.
Оба варианта понравились и подобные вещи имеют право быть.
А чтобы не тратилось время 2 и более человек зря, самое удобное — сделать функцию нечёткого текстового поиска по названию или началу статьи по ссылке для авторов, собирающихся публиковаться.
Тогда сайт мог бы рекомендовать ввести УРЛ оригинала и перевод названия сразу, для проверки, не занимается ли переводом кто-то ещё. Тогда, если каждый автор начнёт работу со ввода заготовки статьи или даже одного URL оригинала, всем последующим при таком же вводе выдавалось бы предупреждение, что столько-то человек с таким-то переводческим рейтингом этим же самым интересовались, а столько-то — имеют заготовку перевода. В этой же форме можно писать сообщение от переводчика, когда планирует закончить и при желании — раскрытие авторства. А отдельно в Твиттер — кто-то из авторов запишет, кто-то забудет, а кто-то вообще не будет знать.