Я начну с провокационного утверждения: я считаю, что CSS — один из самых сложных в освоении компьютерных языков. У него нет сложного синтаксиса, и вам, конечно, не нужна докторская степень в области ИТ, чтобы понять это. Однако это один из немногих популярных языков, который не «логичен», и я имею в виду это в самом буквальном смысле.
В отличие от других знакомых языков веб-разработки, таких как JavaScript, PHP или даже SQL , проблемы не решаются с помощью общей логики. Говорящие алгоритмы, такие как «если X, затем сделай Y, в противном случае сделай Z» или «выбери все из Y, сделай X с ними», не переводятся на такой язык, как CSS . Проще говоря; это язык стиля. Язык для дизайнеров , а не разработчиков. Некоторые из наиболее опытных программистов, с которыми я работал, борются за понимание CSS именно по этой причине.
Каскад — это метафорический термин для синтаксиса CSS . Он вычисляет такие элементы, как происхождение, специфичность, порядок и важность, используя специальные глифы, известные как комбинаторы , для нацеливания на элементы (и псевдоэлементы) и соответственно стилизуют их. Ни одна статья не может сделать синтаксис CSS справедливым, как того заслуживает — для этого нужны спецификации W3 и Dan . Однако, предполагая, что вы уже знаете кое-что о CSS , давайте рассмотрим некоторые менее известные комбинаторы и не как , а когда их использовать.
В школе дизайна нас всех учили о классах и удостоверениях личности, использовании .
и #
соответственно для непосредственного нацеливания на элементы. Этого достаточно для создания функционального веб-сайта, но он недостаточно гибок, чтобы справиться с полным изменением дизайна. Это также создает намного больше работы, чем необходимо, используя презентационные значения в разметке. Давайте посмотрим на альтернативный подход к этим труднодоступным элементам.
Смежный брат и сестра комбинатор
Мы начнем с селектора, который хорошо использовать в тонких ситуациях — используя соседний братский комбинатор. Соседний братский комбинатор обозначается соединением двух элементов с символом +
:
h1 + p
Это выберет все элементы p
которые появляются непосредственно после элемента h1
в DOM. Типографская теория предполагает, что мы должны отступать от абзацев в основном тексте, но только если они заменяют другой абзац. Таким образом, практическое использование этого селектора заключается в добавлении значений text-indent
к абзацам без нацеливания на первый элемент в дереве, как показано ниже;
p + p { text-indent: 1em; }
Это лучше, чем стилизация всех абзацев с text-indent
и обнуление первого с помощью class="first"
любой день. Три строки, без классов и надежная поддержка браузера. Если вы img
теги img
уровня содержимого в теги p
(как и должно быть), мы можем просто вернуть их левые поля с отрицательным значением -1em
:
p + p img { margin-left: -1em; }
Достаточно просто, верно? Что если бы мы хотели оформить первую строку всех абзацев, которые следуют непосредственно за заголовком, не затрагивая другие абзацы? Еще раз, мы можем воздержаться от использования презентационного класса для этого. Простой селектор, состоящий из соседнего братского комбинатора и псевдоэлемента , сделает свое дело:
h1 + p::first-line { font-variant: small-caps; }
Примечание: while :first-line
является псевдоэлементом, одобренным CSS 2.1, нотация ::
была введена на уровне CSS 3 для установления различия между псевдоклассами и псевдоэлементами.
Детский комбинатор
Обычный протокол разметки состоит в том, чтобы обернуть ваши секции верхнего уровня в элемент с именем что-то вроде строк #page
или #wrap
:
<div id="page"> <header></header> <article> <section id="main"></section> <aside></aside> </article> <footer></footer> </div>
в<div id="page"> <header></header> <article> <section id="main"></section> <aside></aside> </article> <footer></footer> </div>
Независимо от того, используете ли вы синтаксис HTML 5 или XHTML 1.1, этот базовый формат должен показаться вам знакомым. Если вы используете фиксированную ширину 960 пикселей и выровняете документ по центру так, чтобы каждый элемент горизонтально заполнял оболочку, ваш CSS, скорее всего, будет выглядеть следующим образом:
#page { width: 960px; margin: 0 auto; } header, article, footer { width: 100%; }
Или, может быть, вы немного конкретнее и используете префикс #page
parent, чтобы избежать попадания в него, когда / если он находится за пределами этого выбора:
#page header, #page article, #page footer { width: 100%; }
Есть лучший способ. Мы все видели универсальный селектор элементов ; *
, вероятно, через сброс браузера или подобное. Когда мы комбинируем это с дочерним селектором, мы можем нацеливаться на все элементы, которые являются прямыми потомками #page
не #page
их внуков или дальше:
#page > * { width: 100%; }
Это поможет нашему документу в будущем, если мы когда-нибудь захотим добавить или удалить элементы из структуры верхнего уровня. Возвращаясь к нашей исходной схеме разметки, мы #main
элементы header
, article
и footer
не касаясь #main
и #main
пределах article
.
Селекторы атрибутов строки и подстроки
Селекторы атрибутов являются одними из самых мощных, которые у нас есть. Они также были в некоторой степени начиная с CSS 2.1 и обычно находятся в форме input[type="text"]
или a[href="#top"]
. Тем не менее, CSS 3 вводит более глубокий уровень управления в виде строк и подстрок .
Примечание: до этого момента все, что мы обсуждали, было стандартом CSS 2.1, но теперь мы переходим к территории CSS 3. Мы оставим это на уровне представления, так что сейчас можно использовать их.
У нас есть четыре основных селектора строки атрибута, доступных для нас, где «v» = значение и «a» = атрибут:
- v является одним из списка значений, разделенных пробелами :
element[a~="v"]
- a начинается именно с v :
element[a^="v"]
- a заканчивается точно на v :
element[a$="v"]
- a содержит значение :
element[a*="v"]
Потенциал для селекторов строки атрибута почти бесконечен, но прекрасным примером является иконография. Возможно, у вас есть неупорядоченный список ссылок на ваши профили в социальных сетях:
<ul id="social"> <li><a href="http://facebook.com/designfestival">Like on Facebook</a></li> <li><a href="http://twitter.com/designfestival">Follow on Twitter</a></li> <li><a href="http://feeds.feedburner.com/designfestival">RSS</a></li> </ul>
Стилизовать их так же просто, как выполнить запрос подстроки через их атрибут href
чтобы найти ключевое слово. Затем мы можем постепенно улучшать эти ссылки, например:
#social li a::before { content: ''; background: left 50% no-repeat; width: 16px; height: 16px; } #social li a[href*="facebook"]::before { background-image: url(images/icon-facebook.png); } #social li a[href*="twitter"]::before { background-image: url(images/icon-twitter.png); } #social li a[href*="feedburner"]::before { background-image: url(images/icon-feedburner.png); }
Точно так же мы можем нацелить все ссылки на документы PDF с помощью селектора подстрок суффикса:
a[href$=".pdf"]::before { background-image: url(images/icon-pdf.png); }
Браузеры, которые не поддерживают подстроки атрибутов CSS 3, не будут отображать эти значки, но это нормально — они не важны для функциональности, они просто «приятны в использовании».
Структурные псевдоклассы
Наконец, я хочу обрисовать преимущества структурных псевдоклассов, которые не следует путать с псевдоэлементами или псевдоклассами связей и состояний . Мы можем использовать их для нацеливания элементов на основе их положения в DOM, а не их содержимого. Прекрасным примером того, когда использовать структурный псевдокласс, может быть нацеливание на первый (или последний) элемент в дереве элементов или чередование нечетных и четных элементов:
<ul> <li>List Item 1</li> <li>List Item 2</li> <li>List Item 3</li> <li>List Item 4</li> <li>List Item 5</li> <li>List Item 6</li> </ul> ul li { border-top: 1px solid #DDD; } ul li:last-child { border-bottom: 1px solid #DDD; } ul li:nth-child(even) { background: #EEE; }
Примечание:: :first-child
— единственный псевдоэлемент, доступный в спецификации CSS 2.1. Все остальные псевдоэлементы, в том числе :last-child
, соответствуют стандартам CSS 3.
Ключ к структурным псевдоэлементам, однако, когда их не использовать. Они должны быть строго зарезервированы для случаев, когда селекторы относятся к положению элемента, а не к его содержимому. Если элемент должен быть стилизован определенным образом, независимо от его положения в DOM, тогда вам следует использовать более значимый семантический селектор, такой как класс, идентификатор или строка.
Резюме
Возможно, вы уже используете некоторые или все эти комбинаторы и селекторы сегодня — возможно, правильным образом, возможно, нет — но не помешает иметь напоминание о том, когда вы можете использовать их вместо применения класса или идентификатора к элемент. Потому что в этом виноваты даже лучшие из нас.